Alpha test transparency mode doesn't work with opacityTexture

I’ve found that alpha test transparency mode (cutout) doesn’t work with an opacityTexture, instead the areas that should be transparent are solid white.

alpha blend transparency works with the same opacityTexture, and alpha test transparency works when the diffuseTexture contains the alpha channel.

Demonstration of the issue:
https://playground.babylonjs.com/#6T7564#3

Expected behavior is for the middle cube to have the same coloring as the left cube and the same transparency as the right cube.

1 Like

Pinging @sebavan

Alpha testing is a feature linked to the albedo texture. To be enabled, the hasAlpha property of the albedo texture must be true:

https://playground.babylonjs.com/#6T7564#4

Yup it currently in PBR can not be used from the OpacityTexture which is meant to only control blending. This basically improves perf and memory by relying only on one sampler. Is that an issue for you ?

Thanks, that’s an interesting little gotcha as alphablend mode doesn’t require this to be set and technically the albedo texture doesn’t have an alpha channel. Is there a way to make this more friendly?

I’m not sure, see the answer from @sebavan, it’s related to perf consideration.

Isn’t it safe to assume that we will be using some form of alpha blending if an opacity texture is set? It seems like it should automatically enable all required alpha settings when an opacity texture is used as it feels a bit wrong to have to enable a non-existent alpha channel on the albedo texture just for alphatest mode.

Yes, regarding alpha blending it is linked to the opacity texture and the albedo texture:

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

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

Alpha blending is a single parameter that applies as a whole at the end of the rendering to mix the new color with the existing pixel color. On the contrary, alpha testing is something done at the texture level and would have to be enabled on a per texture level: albedo and opacity (and possibly other textures too, if you want to be even more general). To avoid having a setting per texture (and a test per texture), it is enabled at the albedo level but the test itself is done after the alpha value is computed from the albedo + opacity texture, it is not just done from the albedo texture. Maybe having the alpha setting on the albedo texture is a bit unfortunate but it’s still more natural/performant to have it here than on the opacity texture (you generally have already an albedo texture for your material, so if you want alpha testing just add an alpha channel to this texture versus adding a new texture (opacity) just for the alpha channel). Also, having it on the texture and not on the material as a whole let’s the ability later to have a different setting for the albedo and opacity textures, should the need arises.

Right now being able to separate the alpha channel from the albedo texture is very useful for filesize optimization - high resolution photographic PNG files are huge, basis textures don’t support alpha channel on all platforms (especially mobile) and ktx textures for some platforms are still very big.

Being able to apply a separate alpha channel means jpeg / basis compression can be used for cutout textures on all platforms.

Maybe we could get something added to the documentation mentioning that hasAlpha must be set to true on the albedo texture if an opacity texture is used?

You’re right, I made a PR to update the doc:

Note also that you can override the Material.needAlphaTesting method to enable alpha testing without having to set hasAlpha to true:

https://playground.babylonjs.com/#6T7564#7

Ah, so it’s controlled just by that method.

I’ve gone ahead and submitted a pull request with a fix that enables alpha cutout if an opacity texture is present, it actually works perfectly without any diffuse/albedo texture at all which is nice.

1 Like