Shader variables are ignored if the shader material is the currently cached one

Hi there. Apologies if this has already been reported - I did a search but did not find an equivalent report.

Anyway, I encountered a problem with caching of shader materials. If you change a shader variable’s value (i.e. materal.setFloat(“var”, 1.0) ), if, when it comes time to bind this material and the engine determines this material was the last one used, it is used as-is, ignoring the changed value.

After a few hours of trying to track down an obscure bug caused by this in my current project I narrowed it down to this line in shaderMaterial.ts line 824:

let mustRebind = this.getScene().getCachedMaterial() !== this;

If this is true then no variables are bound, even if they differ from when the material was last used.

I fixed this in my project by manually caching the variable values and if they’d changed doing a “scene.resetCachedMaterial()” prior to the material bind.

I’m unsure if this is the intended functionality, but can be the source of hard-to-find bugs if you’re unaware of it.

Fixing it, I guess the easiest solution would be to add a hasChanged boolean to the material that is set whenever a variable is changed using one of the setXXX() calls, and this boolean overrides the mustRebind flag above.

Hope that helps.

ping @Evgeni_Popov

Yes, this caching can get in the way sometimes.

However, it can happen only if you use the same material on at least two different meshes and if you set some shader variables with different values during the course of a single frame (the cached material gets reset each frame, so the problem can’t occur from one frame to the other).

I think the best way to handle this case is to have a different material for each mesh (clone the material).