react-three-renderer
                                
                                
                                
                                    react-three-renderer copied to clipboard
                            
                            
                            
                        <shaderMaterial />'s uniforms as a prop not updating on rerender?
Hi, I've been using react-three-renderer with a lot of joy for a project, but have stumbled on an issue I can't seem to solve. I noticed that when uniforms are defined as a prop on <shaderMaterial /> they are not updated on each subsequent render?
This updates properly:
<shaderMaterial>
    <uniforms>
        <uniform type="f" name="time" value={this.state.time} />
    </uniforms>
</shaderMaterial>
The following doesn't seem to update properly:
<shaderMaterial
    uniforms={{
        time: { type: 'f', value: this.state.time },
    }}
/>
First thing that came to my mind was to update them through a ref, but applying the following before render also does not seem to do the trick?
meshref.material.uniforms.time.value = this.state.time;
meshref.material.needsUpdate = true;
I'd love to know if there is an escape hatch that allows for this as I am trying to add a shader I made that adds to the existing THREE.js MeshPhongMaterial.
I have setup a small repo that illustrates the issue here.
Edit: I added a key prop to the <shaderMaterial /> which does seem to work, but unfortunately it slows down the scene the moment the object is in view. I found that workaround in this issue.
Many thanks in advance, have a great weekend!
Hi!
First of all, sorry for late reply.
Yes this seems to be a bug and I'll mark it as such so that it will be elevated in priority. I will need to study how to properly update uniforms for threejs and apply that for the repository...
The key trick works because it recreates the material, I'm hoping it will not be necessary for the proper fix.
@toxicFork thank you! No worries, I am very grateful for all the work you have put in, it makes my scenes much easier to reason about and the recent update to 84.0 is great! Although I still have to upgrade.
Adding the key attribute indeed seemed to work, but it also seems to perform other operations in the background scene that cause it to slow down. I very briefly spoke about this with @AndrewRayCode on Gitter quite some time ago. I think he mentioned that it might be recreating the entire scene/object.
For others that might be reading this and looking for an alternative way of doing it, I created the <mesh> in componentDidMount using new THREE.Mesh(geo, mat) and added it to the scene via a ref attached to a <group />.
Have a great weekend @toxicFork! :-)
Here is what I'm using meanwhile as a workaround. @toxicFork Am happy to submit a PR if you think it's worthwhile.
const uniforms = {
   woodTexture: { type: 't', value: THREE.ImageUtils.loadTexture('textures/wood.jpg') },
   size: {type: 'f', value: 0.5},
   vec: {type: 'v3', value: new THREE.Vector3(1,2,3)},
}
Sample uniforms object above is added to uniforms with the function below
      <shaderMaterial
        vertexShader={vert}
        fragmentShader={frag}
        side={THREE.DoubleSide}
        transparent
      >
        <uniforms>
          {Object.keys(uniforms).map((key) => {
            const uniform = uniforms[key];
            return (
              <uniform type={uniform.type} value={uniform.value} name={key} key={key} />
            );
          })}
        </uniforms>
      </shaderMaterial>
                                    
                                    
                                    
                                
I'm curious why this issue marked closed if not actually resolved? The "bug" seems to still exist, as far as I can tell? The workaround above could be all right, but seems extremely verbose to achieve something so straightforward?
It's not closed though