Hi!
I’m trying to create a ripple effect when moving the mouse. I’m currently using a RenderTexture (from react three drei) to create this ripples to send it as a texture to the main scene, and display it in a plane with full size covering the viewport. My problem is that when I resize the window, the rendered texture gets distorted, and the ripples move different than it should, sometimes they doesn’t reach the window borders and sometimes they move out of the window.
This is how it looks working correctly when the window hasn’t been resized:
And this is how it looks after the resize:
My code is the following:
import { Canvas } from "@react-three/fiber";
import {
OrthographicCamera,
RenderTexture,
useTexture,
} from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useRef } from "react";
import { AdditiveBlending } from "three";
import "./styles.css";
const meshes = [...Array(50).keys()];
function Fluid() {
const renderTextureRef = useRef();
const sizes = useThree((state) => state.size);
const texture = useTexture("/brush.png");
const meshesRef = useRef({});
const prevMouse = useRef([0, 0]);
const currentWave = useRef(0);
const trackWave = (mousePosX, mousePosY) => {
if (
Math.abs(mousePosX - prevMouse.current[0]) < 4 &&
Math.abs(mousePosY - prevMouse.current[1]) < 4
) {
prevMouse.current = [mousePosX, mousePosY];
return;
}
// Set new wave
const mesh = meshesRef.current[currentWave.current];
mesh.position.x = mousePosX;
mesh.position.y = mousePosY;
mesh.visible = true;
mesh.material.opacity = 1;
mesh.scale.x = mesh.scale.y = 1;
currentWave.current = (currentWave.current + 1) % meshes.length;
prevMouse.current = [mousePosX, mousePosY];
};
useFrame((state, delta) => {
trackWave(
(state.pointer.x * state.size.width) / 2,
(state.pointer.y * state.size.height) / 2,
);
meshes.forEach((i) => {
const mesh = meshesRef.current[i];
if (!mesh.visible) return;
mesh.rotation.z += delta * 0.5;
mesh.material.opacity *= 0.96;
mesh.scale.x = mesh.scale.x * 0.98 + 0.1;
mesh.scale.y = mesh.scale.x;
if (mesh.material.opacity < 0.02) mesh.visible = false;
});
});
return (
<>
<mesh>
<planeGeometry args={[sizes.width, sizes.height, 1, 1]} />
<meshBasicMaterial>
<RenderTexture ref={renderTextureRef} attach="map">
{meshes.map((i) => (
<mesh
key={i}
ref={(ref) => (meshesRef.current[i] = ref)}
position={[0, 0, 0]}
rotation={[0, 0, Math.random() * Math.PI * 2]}
visible={false}
>
<planeGeometry args={[40, 40, 1, 1]} />
<meshBasicMaterial
map={texture}
transparent
blending={AdditiveBlending}
depthTest={false}
depthWrite={false}
/>
</mesh>
))}
<OrthographicCamera
makeDefault
args={[
sizes.width / -2,
sizes.width / 2,
sizes.height / 2,
sizes.height / -2,
-1000,
1000,
]}
position={[0, 0, 2]}
/>
</RenderTexture>
</meshBasicMaterial>
</mesh>
<OrthographicCamera
makeDefault
args={[
sizes.width / -2,
sizes.width / 2,
sizes.height / 2,
sizes.height / -2,
-1000,
1000,
]}
position={[0, 0, 2]}
/>
</>
);
}
export default function App() {
return (
<Canvas>
<Fluid />
</Canvas>
);
}
Here is my codesandbox:
https://codesandbox.io/p/sandbox/render-texture-v2pfmd
Does anyone know how to fix my problem?
(This is my first question here, please let me know if I did something wrong)