From 1c4469e20c7a45adb7774ad3d67654ad4ef8a2c9 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Mon, 28 Jul 2025 20:30:28 +0200 Subject: [PATCH] ui: fix memory management in renderLoop --- pkgs/clan-app/ui/src/scene/RenderLoop.ts | 20 +++++++++++--------- pkgs/clan-app/ui/src/scene/cubes.tsx | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pkgs/clan-app/ui/src/scene/RenderLoop.ts b/pkgs/clan-app/ui/src/scene/RenderLoop.ts index af50e2646..4046ad2a9 100644 --- a/pkgs/clan-app/ui/src/scene/RenderLoop.ts +++ b/pkgs/clan-app/ui/src/scene/RenderLoop.ts @@ -3,8 +3,8 @@ import { MapControls } from "three/examples/jsm/controls/MapControls.js"; import { CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js"; /** - * Private class dont try to import it - * + * Private class to manage the render loop + * @internal */ class RenderLoop { // Track if a render is already requested @@ -81,17 +81,12 @@ class RenderLoop { private render() { // TODO: Disable console.debug in production - console.debug("Rendering scene...", this); + // console.debug("Rendering scene...", this); - this.renderer.autoClear = false; this.renderer.clear(); this.renderer.render(this.bgScene, this.bgCamera); - - this.controls.update(); - this.renderer.render(this.scene, this.camera); - this.labelRenderer.render(this.scene, this.camera); } @@ -99,7 +94,14 @@ class RenderLoop { // Dispose controls, renderer, remove listeners if any this.controls.dispose(); this.renderer.dispose(); - // clear refs + // clear refs, this prevents memory leaks by allowing garbage collection + this.scene = null!; + this.bgScene = null!; + this.camera = null!; + this.bgCamera = null!; + this.renderer = null!; + this.controls = null!; + this.labelRenderer = null!; this.initialized = false; } } diff --git a/pkgs/clan-app/ui/src/scene/cubes.tsx b/pkgs/clan-app/ui/src/scene/cubes.tsx index f4b467169..f7cf022c0 100644 --- a/pkgs/clan-app/ui/src/scene/cubes.tsx +++ b/pkgs/clan-app/ui/src/scene/cubes.tsx @@ -479,6 +479,7 @@ export function CubeScene(props: { renderer.setSize(container.clientWidth, container.clientHeight); renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; + renderer.autoClear = false; container.appendChild(renderer.domElement); // Label renderer