[SOLVED] Setting material opacity using setParameter

I’m trying to set the material opacity on specific model without affecting other models using the same material:

this.entity.model.model.meshInstances.forEach(mi => mi.setParameter("material_opacity", 0.5));

Unfortunately, it doesn’t work :frowning:
Setting another parameters work as expected, e.g:

this.entity.model.model.meshInstances.forEach(mi => mi.setParameter('material_diffuse', [1,0,0]));

What I’m doing wrong?

P.S. Is it possible to find the complete list of all the possible parameter like material_opacity and material_diffuse?

1 Like

Hi @Igor,

What is the initial value of opacity in your material?

To have the opacity shader chunk included in the generated shader program usually you have to trick the engine by putting a non 1.0 value.

If it’s 1.0 initially, put 0.999 and try again.

1 Like

About that list, not sure if there is one but at any point you can check in the console the generated shader definition of the material under:

material.shader;

All the included uniforms in the vertex and pixel shaders can be adjusted using the setParameter method.

1 Like

Thanks @Leonidas, setting initial opacity to 0.999 solves the problem.

2 Likes

I got tired of manually setting my material opacities to 0.999 (annoying if you are fading an entire object and it has a lot of materials). I also just never liked the idea that a fully opaque material was being rendered as being a tiny bit transparent. So I just check to see if the material opacity is undefined or not. If it is, I set it to 0.999999 using material.update(), and then set it back to its initial value with setParameter(). That establishes the shader chunk for the material’s transparency and I can just use setParameter() from this point forward for any other opacity changes.

if(this.entity.model.meshInstances[0].parameters.material_opacity === undefined){
   this.initialOpacity = this.entity.model.meshInstances[this.miStep].material.opacity;
   this.entity.model.meshInstances[this.miStep].material.opacity = (this.initialOpacity * 0.999999);
   this.entity.model.meshInstances[this.miStep].material.blendType = pc.BLEND_NORMAL;
   this.entity.model.meshInstances[this.miStep].material.update();
   this.entity.model.meshInstances[this.miStep].setParameter('material_opacity', ( this.initialOpacity));
}	
3 Likes

Bumping an old thread but why do we need to set opacity to < 1 for this to work when it works without it in this example?

https://developer.playcanvas.com/en/tutorials/fading-objects-in-and-out/

The opacity intensity of the material is set to 1 and it’s not altered anywhere in the script prior to setParameter, yet it works just fine. Why is that?

Hmm, actually it doesn’t work against the latest engine build. When launched from editor it doesn’t fade in/out for me.

The main reason for having to change a default parameter on a material channel, is to force the engine to include a shader program part (chunk) to the final compiled shader. So you can easily update a uniform using setParameter, without having to recompile the shader, using material.update().

2 Likes

Oh right, it works just on the example page.

Shouldn’t that chunk inclusion be determined from blend mode or something instead? It feels really silly to have to have slightly transparent materials if you want to alter opacity from code. Or is it supposed to be a feature or is it a bug? At least the example should be updated as it doesn’t work now.

Feature. It’s an optimisation so it’s quicker to compile and I think the performance is slightly better too.

Yeah, not sure why it is like that. Someone from the team might get some time to fix that.

1 Like

Fixed!

1 Like
        this.tween2 = this.entity
            .tween(this.aa)
            .to({ value: this.targetAlpha }, this.timeIn, this.getCurve(this.typeIn))
            .on('update', function() { 
                this.material.opacity = this.aa.value;
                this.material.update();
            }.bind(this), this)
            .loop(false)
            .yoyo(false);
    this.tween2.start();

and no problems
full code: https://pastebin.com/0xXTpueC

1 Like