共享材质,材质变体如何使用

Creator v2.4.3

我的需求很简单,加载一个 Material,然后作用到两个 sprite,然后设置材质的某个属性 (setDefine),但是不希望两个 sprite 一起变化。

我翻到论坛有人提到过:
https://docs.cocos.com/creator/manual/zh/render/material.html?q=materialvariant

这里有写到共享材质和变体材质 MaterialVariant 的内容,但是我简单的试了下, 怎么写都不对。下面是我的代码。

显示加载材质

cc.loader.loadRes("testMaterial", cc.Material, function(err, data) {
    this.loadedMaterial = data;
});

材质很简单:

void main () {
        #if DEFINE_TEST
            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
        #else
            gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
        #endif
    }

然后写了个按钮,实际应用

this.materialVariantA = cc.MaterialVariant.create(this.loadedMaterial, this.spriteA.getComponent(cc.Sprite));
this.spriteA.getComponent(cc.Sprite).setMaterial(0, this.materialVariantA);

this.materialVariantB = cc.MaterialVariant.create(this.loadedMaterial, this.spriteB.getComponent(cc.Sprite));
this.spriteB.getComponent(cc.Sprite).setMaterial(0, this.materialVariantB);

这里其实是了很多种写法,按钮点击以后,材质都能生效,但是接下来就不对了。

再写一个按钮

this.materialVariantA.define("DEFINE_TEST", true);

这里点击按钮以后,两个 sprite 还是一起变了颜色。

想请教一下各位大佬,这个想要材质单独变化,究竟应该怎么写猜才对呢?

复制一个:smirk:

你可以获得cc.Sprite的getMaterial,然后修改后使用setMaterial。getMaterial默认会复制

大佬我觉得会不会是,官方的 这个共享材质,变体材质,对于 setProperty 是有效果的。但是对于 setDefine 是没有效果的。

你说的获得 get Material 后,修改,再 set,这个具体是怎么个写法的?因为我的 material 是动态加载的,我加载好了,就直接 set 了。要怎么做到先把之前的 get 出来,再 set ?

cc.loader.loadRes("testMaterial", cc.Material, function(err, data) {
    this.loadedMaterial = data;
   //
   let oldMaterialA = this.spriteA.getComponent(cc.Sprite).getMaterial(0);
   // 然后是要对这个 oldMaterialA 操作吗?
});

请大佬指点下,谢谢了 ~~~

//修改了oldMaterialA后
this.spriteA.getComponent(cc.Sprite).setMaterial(0,oldMaterialA);

就这样

大佬我试了下,但是我还是不太理解你说的,修改 oldMaterialA 是要怎么写。我试了下面的代码

let oldMaterialA = this.spriteA.getComponent(cc.Sprite).getMaterial(0);
// oldMaterialA = this.loadedMaterial;   // 这个直接赋值也试过了,但是不对
oldMaterialA = cc.MaterialVariant.create(this.loadedMaterial); // 这个也试过了,也不对
this.spriteA.getComponent(cc.Sprite).setMaterial(0, oldMaterialA);

let oldMaterialB = this.spriteB.getComponent(cc.Sprite).getMaterial(0);
// oldMaterialB = this.loadedMaterial;
oldMaterialB = cc.MaterialVariant.create(this.loadedMaterial);
this.spriteB.getComponent(cc.Sprite).setMaterial(0, oldMaterialB);

像上面这样,给 A,B 分别重新设置了 setMaterial,但是修改 A 的define以后,AB还是一起变了:

this.spriteA.getComponent(cc.Sprite).getMaterial(0).define("DEFINE_TEST", false);

是不是,你说的 修改了oldMaterialA 要手动改属性,类似这样的:

oldMaterialA._effect = this.loadedMaterial._effect;
oldMaterialA.xxx = this.loadedMaterial.xxx;

oldMaterialA.define(“DEFINE_TEST”, false); // 这里不就是修改了吗
this.spriteA.getComponent(cc.Sprite).setMaterial(0,oldMaterialA);