You need to use the same object for uniforms, what youâre doing is replacing the whole object instead of updating its properties. While assigning a âkeyâ might solve the issue, but I think, every time the key value changes it creates a new shaderMaterial.
First, make sure uniform object doesnât get changed. You can memoize it:
// this always returns the same object,
// no matter how many times the component get rerendered
const uniforms = useMemo(() => ({
u_resolution: { value: new Vector2(width, height) },
u_scale: { value: 3 }
}), []);
Then what you can do is to assign a ref to your material component:
uniforms canât be changed like that in threejs, you canât just overwrite them. you need to create getters/setters for them or else they remain inaccessible.
i also think that defining a shader in jsx is not ideal. why not just use plain THREE.ShaderMaterial (or drei/shaderMaterial, perhaps better/easier) and then extend? this way your material is re-usable:
ps. drei/shaderMaterial creates a plain THREE.ShaderMaterial but it takes out some boilerplate as it creates auto setter/getters for uniforms. also defining uniforms is easier. not react specific, could also be used in vanilla:
const FooMaterial = shaderMaterial(uniforms, vert, frag)
const mesh = new THREE.Mesh(new THREE.BoxGeometry(), new FooMaterial())
Thank you for this post. I have been scratching my head for hours in why my uniform property wouldnât update. This not only corrected it but also set it as âthe same objectâ. Glad I found this.