fand / vfx-js

WebGL effects made easy.
https://amagi.dev/vfx-js
616 stars 18 forks source link

Custom Uniforms Progress #31

Closed wyhinton closed 2 months ago

wyhinton commented 2 years ago

Is it true that as of yet there's no way to pass values into the shader without recompiling the shader? I.e. something like:

//some value we'd change later in the script
var changingValue = "vec2(10.0)"

const blink = `
uniform vec2 resolution;
uniform vec2 offset;
uniform float time;
uniform sampler2D src;

void main() {
    vec2 uv = (gl_FragCoord.xy - offset + changingValue) / resolution;
    gl_FragColor = texture2D(src, uv) * step(.5, fract(time));
}
`;

I imagine this would be really inefficient.

Any thoughts on a workaround for the time being that doesn't involve recompiling the shader?

fand commented 2 years ago

Hi @wyhinton ! You can pass any uniform values to VFX elements like this:

const blink = `
uniform vec2 resolution;
uniform vec2 offset;
uniform float time;
uniform sampler2D src;
uniform vec2 changingValue; // ADD THIS LINE

void main() {
    vec2 uv = (gl_FragCoord.xy - offset + changingValue) / resolution;
    gl_FragColor = texture2D(src, uv) * step(.5, fract(time));
}
`;

const App = () => {
  const x = useRef(10);

  return <>
    <button type="button" onClick={() => { x.current *= -1; }}>CLICK</button>
    <VFXImg shader={blink} uniforms={{ 
      changingValue: () => [x.current, x.current],  //  VEC2
    }} />
  </>;
}

CodeSandbox: https://codesandbox.io/s/heuristic-snowflake-ptorj?file=/src/App.js

Note that you should use useRef instead of useState to create values to pass into uniforms.