Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UV projection of pointerValues for FX is wrong #84

Closed
nhtoby311 opened this issue Mar 4, 2024 · 4 comments
Closed

UV projection of pointerValues for FX is wrong #84

nhtoby311 opened this issue Mar 4, 2024 · 4 comments

Comments

@nhtoby311
Copy link

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
@takuma-hmng8
Copy link
Member

@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
       });
    }
 });

@nhtoby311
Copy link
Author

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

@nhtoby311
Copy link
Author

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

@takuma-hmng8
Copy link
Member

@nhtoby311
Oh, I see, if I use onPointerMove I can skip the hassle of initialising my own RayCaster!
Thanks for letting me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants