Hello,
Is it possibly to have a material’s (effect’s) blend mode overwrite the modes specified in the sprite component? I think @ckhoo 's post here has me on the right track : ( [SOLVED] Support for GL min/max blend equation functions ) , but no matter what I pass as arguments to blendEq, blendSrc or blendDst, the sprite continues to its own blending.
Using arguments of “derp” for all 3 also don’t throw an error. So I’m wondering If I’m completely missing a step.
Depending on the version, Cocos Creator resets the blend equation or resets the material when a sprite image is applied. To overcome this, I wrote a RenderMaterialOverride component whose sole purpose is to enforce the material applied and its settings.
const {
ccclass,
property,
menu,
requireComponent,
executeInEditMode
} = cc._decorator;
@ccclass
@menu('Renderer Component/Render Material Override')
@requireComponent(cc.RenderComponent)
@executeInEditMode
export default class RenderMaterialOverride extends cc.Component {
@property({
type: cc.Material
})
private material: cc.Material = null;
private renderComp: cc.RenderComponent = null;
private renderCompMatOriginal: cc.Material = null;
private _materialInst: cc.Material = null;
public get materialInst (): cc.Material {
return this._materialInst;
}
// LIFE CYCLE ---------
protected onEnable (): void {
this.renderComp = this.node.getComponent(cc.RenderComponent);
cc.assert(this.renderComp != null);
// At runtime, we only apply the material once - when the override component is enabled...
if (!CC_EDITOR)
this.applyMaterial();
}
// LIFE CYCLE ---------
protected onDisable (): void {
// Revert to the original material
if (this.renderComp != null && this.renderCompMatOriginal != null)
this.renderComp.setMaterial(0, this.renderCompMatOriginal);
}
protected update (): void {
// In the editor, we apply it as many times as necessary...
if (!CC_EDITOR)
return;
// Keep fetching the render component in case it's removed / replace
this.renderComp = this.node.getComponent(cc.RenderComponent); ;
if (this.renderComp == null)
return;
const renderCompMat: cc.Material = this.renderComp.getMaterial(0);
if (renderCompMat !== this._materialInst || this.material !== this._materialInst)
this.applyMaterial();
}
// IMPLEMENTATION ------
public setMaterial (mat: cc.Material): void {
if (this.material === mat)
return;
this.material = mat;
this._materialInst = null;
if (this.enabled)
this.applyMaterial();
}
public getMaterial (): cc.Material {
return this.material;
}
protected setupMaterialInstanceSettings (targetMat: cc.Material, refMat: cc.Material): void {
targetMat.define('_USE_MODEL', this.renderComp instanceof cc.Graphics);
this.copyDefine('USE_ALPHA_TEST', targetMat, refMat);
this.copyDefine('USE_TEXTURE', targetMat, refMat);
this.copyProperty('texture', targetMat, refMat);
this.copyProperty('alphaThreshold', targetMat, refMat);
}
private copyDefine (defineName: string, targetMat: cc.Material, refMat: cc.Material): void {
const srcDef = refMat.getDefine(defineName);
if (srcDef !== undefined)
targetMat.define(defineName, srcDef);
}
private copyProperty (propName: string, targetMat: cc.Material, refMat: cc.Material): void {
const srcProp = refMat.getProperty(propName);
if (srcProp !== undefined)
targetMat.setProperty(propName, srcProp);
}
protected applyMaterial (): void {
if (this.renderComp == null)
return;
const renderMat = this.renderComp.getMaterial(0);
// Render component isn't using a material (no texture?)? There's nothing left to do...
if (renderMat == null)
return;
// First time replacing the render component material? Make a note of the original material
if (this.renderCompMatOriginal == null)
this.renderCompMatOriginal = renderMat;
if (this._materialInst == null && this.material != null) {
this._materialInst = cc.Material.getInstantiatedMaterial(this.material, this);
this.setupMaterialInstanceSettings(this._materialInst, this.renderCompMatOriginal);
} else if (CC_EDITOR)
this._materialInst = this.material;
// Copy over the known settings as necessary
const appliedMatInst = this._materialInst || this.renderCompMatOriginal;
this.renderComp.setMaterial(0, appliedMatInst);
}
}