3

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

3 Answers 3

2

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()}}

Sign up to request clarification or add additional context in comments.

Comments

0

try just with mathRef.current.uTime if you are using the shaderMaterial from 'dre' it should be okay just by writing that line instead of mathRef.current.uniforms.uTime

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

referencing this post:

Try setting a key value to your shaderMaterial component so react can keep track of it and update the uniforms. It worked for me.

  <shaderMaterial
    key={colorDomain} //important for updating the uniforms!!
    ref={shaderMatRef}
    uniforms={{ uDomainColor: { value: new THREE.Color(colorDomain) } }}

Or as suggested in this thread, create a stable reference to the uniforms:

  const uniforms = useMemo(
    () => ({ uDomainColor: { value: new THREE.Color(colorDomain) } }),
    []
  );
  useEffect(() => {
    uniforms.uDomainColor.value.set(colorDomain);
  }, [colorDomain]);
  return( ...<shaderMaterial
    vertexShader={vertexShader}
    fragmentShader={fragmentShader}
    uniforms={uniforms}
  />...);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.