Material.onBeforeCompile not firing if assigned within GLTFLoader

Hi,

Sorry for the beginner question, I’m still new to three.js and relatively new to JS.

For reasons related to my production pipeline i need to use a custom shader for what i am rendering in Three. I am using a modified version of the GLTFLoader which is just a copy of the current one with some extra code added to address this.

After reading around various discussions it seemed like the best approach was to use onBeforeCompile to replace certain chunks of the MeshStandardMaterial with the behaviour i needed.

To do this, i created a test case, in the returned Promise of the GLTFParser.prototype.loadMaterial function, specifically the first ‘else’ for when the materialType !== GLTFMeshStandardSGMaterial.
Right now all this is doing is:
material.onBeforeCompile = function(shader){shader.fragmentShader = "void main() {gl_FragColor = vec4(1,0,0,1);}"}
So i simply expect all models coming through the importer to be an unlit red.

This onBeforeCompile is never executing (tested by throwing a console log into that function).

Is there a reason why this does not work? I cannot see anything else in the importer assigning over that onBeforeCompile, and i have used the same method on an explicitly created material in my index.js which i then assigned to the meshes, and that worked as expected.

I solved it - the assignFinalMaterial function is performing a clone() on the material created earlier on in the importer to create a cachedMaterial, and the onBeforeCompile is not supported by .clone()

The solution was to move the callback assignment to the cachedMaterial

1 Like