UV projection of `pointerValues` for FX is wrong
nhtoby311 opened this issue · 4 comments
Following this setup to assign custom pointer values to FX hooks (Ex: useFluid) results in a wrong UV projection, as while pointer value goes from 0 -> 1, the effects display from 0.5 -> 1 on the UV instead.
useFrame((props) => {
const pointerValues = updatePointer(refPointer.current);
//This however returns the correct values of pointerValues
console.log('pointerValues', pointerValues);
//Therefore, I suspects the issue lie inside the updateFluid
const fluid = updateFluid(props, { pointerValues: pointerValues });
const fx = updateBlending(props, {
map: fluid,
alphaMap: false,
});
materialRef.current!.material.uniforms.u_fx.value = fx;
});2024-03-04.20-52-56.mp4
If I use my custom code for useFluid that I created in this PR #65, it works well like below:
2024-03-04.20-58-43.mp4
@nhtoby311
What is the value of refPointer.current?
Do you have an image of initializing the raycaster for the mesh in the middle?
If so, please refer to the following!
const updatePointer = usePointer();
const raycaster = useMemo(() => new THREE.Raycaster(), []);
const rayCursor = useRef<THREE.Vector2 | null>(null);
useFrame((props) => {
updateFluid(props);
raycaster.setFromCamera(props.pointer, camera); // This camera must be the same scene camera as the object you want to target the raycaster
const intersects = raycaster.intersectObject(mesh); // Here the target object 3D
if (intersects.length > 0) {
const uv = intersects[0]?.uv as THREE.Vector2; //
if (!uv) return;
rayCursor.current = uv.multiplyScalar(2).subScalar(1); // Depending on how you set the uv value of attribute, the default uv of THREE is 0 to 1.
}
if (rayCursor.current) {
mesh.material.uniforms.uFx.value = updateFluid(props, {
pointerValues: updatePointer(rayCursor.current), // pointer requires vec2 normalized to -1~1
});
}
});Yes, I use onPointerMove R3F events on the primitive, which use raycaster in the background. Refers to https://docs.pmnd.rs/react-three-fiber/api/events
I see, so pointerValues expects value from range -1 -> 1, while UV value is 0 -> 1. However, when I try something like below, it becomes quite buggy, especially when mouse move slowly, and then break out of nowhere after a while (no console error) 😢 Any ideas why it's happening like that?
const refPointer = useRef(new Vector2(0, 0));
const handlePointerMove = (e: any) => {
//This value returns the correct current UV at pointer position.
refPointer.current = e.uv;
};
useFrame((props) => {
const actualValue = refPointer.current.multiplyScalar(2).subScalar(1);
const fluid = updateFluid(props, {
pointerValues: updatePointer(actualValue),
});
const fx = updateBlending(props, {
map: fluid,
alphaMap: false,
});
materialRef.current!.material.uniforms.u_fx.value = fx;
});
...
<primitive
onPointerMove={handlePointerMove}
rotation-x={-Math.PI / 2}
position={[0, -5, 0]}
/>broken-pointerValues.mp4
It seems .multiplyScalar(2).subScalar(1) inside useFrame cause the buggy issue above. I move the calculation outside and it seems to work well now. Thanks!
const handlePointerMove = (e: any) => {
refPointer.current = e.uv.multiplyScalar(2).subScalar(1);
};
useFrame((props) => {
const fluid = updateFluid(props, {
pointerValues: updatePointer(refPointer.current),
});
const fx = updateBlending(props, {
map: fluid,
alphaMap: false,
});
materialRef.current!.material.uniforms.u_fx.value = fx;
});@nhtoby311
Oh, I see, if I use onPointerMove I can skip the hassle of initialising my own RayCaster!
Thanks for letting me know.