How can I create transparent effect with material plugin

I am creating transparent shader effect with material plugin. But changing the gl_FragColor.a doesn’t work properly. It seems the needAlphaBlending property needs to be set. I wonder how can I set the blending in a proper way?

My playground:

I tried to force needAlphaBlending always return true.

m.material.transparencyMode = 2;
m.material.needAlphaBlending = () => { return true; };

It works great when gl_FragColor.a < 1.0 but when gl_FragColor.a == 1.0 the backside of the mesh appears.
Like this:

cc @Evgeni_Popov

Welcome aboard!

Alpha blending should not be enabled when alpha == 1, because in that case the depth buffer is not updated and you can get artifacts because of the order the triangles are drawn.

The system will do the correct thing if you use the alpha property of the material because it is doing:

public needAlphaBlending(): boolean {
    if (this._disableAlphaBlending) {
        return false;

    return this.alpha < 1.0 || this._opacityTexture != null || this._shouldUseAlphaFromAlbedoTexture();

But as you set the alpha value directly in the shader code, the system does not know the alpha value you used. The easiest way to fix it is to set material.alpha with the same value than the one you use in the shader code. And even easier, simply use alpha in your shader code, as this variable is already defined and contains the alpha value you set at the material level (modulated by the alpha from the opacity texture, if any):


@Evgeni_Popov Thanks for the support!
I am working on AR occlusion effect similar to this issue: Add support for AR occlusion · Issue #857 · BabylonJS/BabylonNative · GitHub. Every pixel of mesh will go through a render check according to distance from camera and depth map.
I think I find the solution, adding material.forceDepthWrite = true; can fix the triangles drawing order. So that the back side of mesh will not mix up with front.

Yes it works, but note that depending on the order the transparent meshes are drawn, you may not get proper blending.

For eg:

The (transparent) green cube is drawn before the box, so it works.

The green cube is drawn after the box. It does not work because the depth buffer (filled by the box because of forceDepthWrite=true) prevents the cube to be drawn.

As Babylon.js is sorting transparent objects from back to front, it will work as expected as long as you have a single transparent object with forceDepthWrite=true. If you have more than one transparent object, you can/will get some artifacts depending on the camera view.

@Evgeni_Popov Thanks for the advice!
As I know, BabylonJS sorts transparent objects first by alphaIndex and then distance from camera. If all of my objects have the same alphaIndex then I won’t get artifacts?
Or is there a better solution for this problem?

You can get artifacts if your objects are concave.

There’s no perfect solution when dealing with transparent meshes. See this doc page for in-depth discussion and some possible solutions:

1 Like