Reputation: 11
I'm trying to update an uniform vec2 when the mouse is moving but i get an error: TypeError: Failed to execute 'uniform2fv' on 'WebGL2RenderingContext': Overload resolution failed.
for this I create a ref uniforms
const uniformRef = useRef({
uAlpha: 0,
uOffset: { x: 0.0, y: 0.0 },
uTexture: imageTexture,
});
then I created a useEffect to listen the event "mousemove"
useEffect(() => {
document.addEventListener("mousemove", onMouseMove);
return () => document.removeEventListener("mousemove", onMouseMove);
}, [onMouseMove]);
and finally i create the functiopn call on "mousemove"
const onMouseMove = useCallback((e: MouseEvent) => {
if (!planeRef.current || planeRef.current === undefined) return;
// mouse coordinate
let x = (e.clientX / window.innerWidth) * 2 - 1;
let y = -(e.clientY / window.innerHeight) * 2 + 1;
const position = new THREE.Vector3(x, y, 0);
// change position of the mesh
gsap.to(planeRef.current?.position, {
duration: 1,
x,
y,
ease: Power4.easeOut,
onUpdate: () => onPositionUpdate(position),
});
}, []);
// update the offset
const onPositionUpdate = (position: THREE.Vector3) => {
if (planeRef.current) {
let offset = planeRef.current.position
.clone()
.sub(position)
.multiplyScalar(-0.25);
gsap.to(uniformRef.current, {
uOffset: { x: offset.x, y: offset.y },
duration: 1,
ease: Power4.easeOut,
});
}
};
And this is the initialisation of my shader
const ColorShiftMaterial = shaderMaterial(
{
uTexture: new THREE.Texture(),
uOffset: new THREE.Vector2(0.0, 0.0),
uAlpha: 0,
},
...)
If you could help me on this or just give tips, it will help me a lot ! Thanks
I tried a lot of things, but every time i tried someting new, I still get the error, I was thinking it may be because i give to uOffset a vec3. So I change to a vec2 but even with this I still get the error.
Upvotes: 0
Views: 298
Reputation: 64
First off, you should use react-three fiber when dealing with 3JS and react.
By naming convention you should name your uniforms like u_mouse (with an underscore).
In three fiber there is an onPointerMove that you can use to get your mouse movement.
For example:
<mesh onPointerMove={(e) => handleMove(e)}>
To pass your values to the shader, you need to have uniforms.
const uniforms = {
u_time: { value: 0.0 },
u_mouse: { value: { x: 0.0, y: 0.0 } },
u_resolution: { value: { x: 0, y: 0 } },
};
You can use a useEffect to get the values of the screensize and use these values in your resolution uniform. Then you can use these values in your shader to calculate the movement of the mouse regardless of the screen size.
I'm not sure how you have written your shader, but you can create a vec2 for the mouse and a vec2 for the resolution and do something like
vec2 v = u_mouse/u_resolution; // mouseposition / screensize
vec3 color = vec3(v.x, (v.y/v.x+0.2), v.y); // use the v-value for the x- and y-axis
gl_FragColor = vec4(color, 1.0); // add the new colors to your output
It all depends on what you want to happen and how you want it to look.
Upvotes: 0