Hello everyone.
I am using React (“react”: “^18.2.0”) and Three.js (“three”: “^0.151.3”)
The problem I am facing is that, while you go from page to page, three.js animations get slower. I was thinking that is a memory leak, but now I am not so sure what is the problem. I think that everything I did is like you guys described, but something is bothering me. I will give you one sample component I am using, every else, is pretty much the same. I just need clarification that is not up to three.js, but something else, some other JavaScript that is making a problem. I am disposing everything I can, and also the whole scene and renderer itself when leaving the page, but next page get slower…
Note. I am getting warnings: “WARNING: Too many active WebGL contexts. Oldest context will be lost…” so that is the reason why I am thinking that maybe this part of the code is making me that problem. I also made a global renderer, and use it for the whole website, but that changed nothing.
Thank you all in advance!
export default memo(
({ antialias, engineOptions, adaptToDeviceRatio, sceneOptions, onRender, onSceneReady, handleMaskFade, ...rest }) => {
const reactCanvas = useRef(null);
let renderer;
let scene;
let camera;
let mousePosition = new THREE.Vector3();
let cameraCtrl;
let mouse = new THREE.Vector2();
let raycaster = new THREE.Raycaster();
let mixerarr = [];
let geometries = [];
let clock = new THREE.Clock();
let geometryDodecahedronGeometry;
let composer, iMesh;
let pointLight;
let cscale = chroma.scale(["#dd3e1b", "#0b509c"]);
let mousePlane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
let textureAtlas1;
let geometryGlow1;
let materialGlow1;
let mouseOver;
let NUM_INSTANCES = 1000;
let instances = [];
let { randFloat: rnd, randFloatSpread: rndFS } = THREE.MathUtils;
let unmounted = true;
let materialShader;
let meshphongFragBody, meshphongFragHead;
useEffect(() => {
const { current: canvas } = reactCanvas;
sceneOptions = {
useGeometryUniqueIdsMapSearch: true,
useMaterialMeshMapSearch: true,
useClonedMeshMap: true,
};
if (!canvas) return;
unmounted = false;
// create a new WebGL renderer
renderer = new THREE.WebGLRenderer({ canvas, antialias, ...engineOptions });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x00ff00, 0);
renderer.alpha = true;
renderer.antialias = true;
scene = new THREE.Scene();
// scene.background = null;
// create a new camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
creatingAssets();
cameraConfig();
threeManager = {
activeScene: scene,
transitionScene: null,
};
function animate() {
}
animate();
const resize = () => {
const width = window.innerWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
if (isPhone()) {
renderer.setSize(window.outerWidth, window.outerHeight);
} else {
renderer.setSize(width, height);
}
};
if (window) {
window.addEventListener("resize", resize);
}
return () => {
unmounted = true;
if(renderer.attributes) renderer.attributes.remove(iMesh.instanceMatrix)
if (geometryDodecahedronGeometry) geometryDodecahedronGeometry.dispose();
materialShader.dispose();
instances = [];
scene.remove(iMesh);
scene.remove(pointLight);
scene.remove(womanMaskMesh);
iMesh = null;
if (geometryGlow1) geometryGlow1.dispose();
if (textureAtlas1) textureAtlas1.dispose();
if (materialGlow1) materialGlow1.dispose();
if (materialShader) materialShader.dispose();
if (composer) composer.dispose();
if (pointLight) pointLight.dispose();
if (scene.current && camera.current) {
scene.current.dispose();
camera.current.dispose();
}
if (renderer.current) {
renderer.current.dispose();
}
if (window) {
window.removeEventListener("resize", resize);
}
document.body.removeEventListener("click", randomColors);
document.body.removeEventListener("mousemove", onMouseMove, false);
renderer = null;
scene = null;
camera = null;
pointLight = null;
womanMaskMesh = null;
materialGlow1 = null;
mousePlane = null;
reactCanvas.current = null;
};
}, []);
return (
<div>
<canvas ref={reactCanvas} {...rest}></canvas>
</div>
);
function randomColors() {
const c1 = chroma.random(),
c2 = chroma.random();
cscale = chroma.scale([c1, c2]);
updateColors();
}
function updateColors() {
const colors = [];
for (let i = 0; i < NUM_INSTANCES; i++) {
const color = new THREE.Color(cscale(rnd(0, 1)).hex());
colors.push(color.r, color.g, color.b);
}
iMesh.geometry.setAttribute("color", new THREE.InstancedBufferAttribute(new Float32Array(colors), 3));
}