React-Three-Fiber sending uniforms to custom shader with TypeScript

Viewed 1089

Im converting to TypeScript and I cant seem to get uniform sent into shader. There are no errors anywhere and everything runs but uniform is not updating, nor is it really being sent in the first place I think. I think that because I set uTime to 0.5 and my box is just green, meaning red channel value that my uTime uniform is supposed to affect doesnt do anything.

this is what I have

function Box(props: JSX.IntrinsicElements['mesh']) {
  const matRef = useRef<THREE.ShaderMaterial>(null!)

  useFrame(({clock, mouse }) =>{
    if(matRef.current){
      matRef.current.uniforms = {uTime: {value: clock.getElapsedTime()}}
    }
  })

  return (
    <mesh>
      <boxGeometry args={[1, 1, 1]} />
      <shaderMaterial
        ref={matRef}
        attach='material'
        vertexShader={vertex}
        fragmentShader={fragment}
        uniforms={{uTime: { value: 0.5}}}
      />
    </mesh>
  )
}

fragment shader

export const fragment = `
      precision mediump float;
      uniform float uTime;
      uniform sampler2D uTexture;
      uniform float uMouseX;
      uniform float uMouseY;
      uniform float uScreenW;
      uniform float uScreenH;

      varying float uCol;
      varying vec2 vUv;
      varying vec3 v_position;


      void main() {

        vec3 color = vec3(sin(uTime), 1.0, 0.0);

        gl_FragColor = vec4(color, 1.0);
      }
    `

EDIT Inital value is getting to shader. So problem is in updating uniform

1 Answers

by this line matRef.current.uniforms = {uTime: {value: clock.getElapsedTime()}} you are mutating the uniforms obj, so the other uniforms value are gone.

if you want to change uTime only, you can use this instead matRef.current.uniforms.uTime = {value: clock.getElapsedTime()}

or

you can copy the previous other uniforms with spread operator: matRef.current.uniforms = {...matRef.current.uniforms, uTime: {value: clock.getElapsedTime()}}

Related