Three.js Scene and Renderer: The Setup Every Project Starts With
Every Three.js project starts with the same three objects working together: a Scene (the container holding everything, meshes, lights, fog), a Renderer (WebGLRenderer or WebGPURenderer, which draws the scene from a camera's point of view into a canvas element), and a render loop (renderer.setAnimationLoop()) that calls renderer.render(scene, camera) every frame.
Scene, renderer, camera: the core trio
THREE.Scene is just a container: a special Object3D that holds everything you add to it (scene.add(mesh)), plus scene-level settings like background and fog. It doesn't render anything by itself.
The renderer (WebGLRenderer or WebGPURenderer, see WebGPU vs WebGL) owns the actual <canvas> element and does the drawing. Key setup: renderer.setSize(width, height), renderer.setPixelRatio(window.devicePixelRatio) (capped, usually at 2, since uncapped device pixel ratio on high-DPI mobile screens can tank performance for negligible visual gain), and appending renderer.domElement to the page.
The camera (PerspectiveCamera or OrthographicCamera) defines the viewpoint the scene is rendered from. It's passed to renderer.render(scene, camera) every frame, but isn't itself part of the scene's visual output.
The render loop
renderer.setAnimationLoop(callback) is the standard way to drive a continuously updating scene. It's Three.js's wrapper around requestAnimationFrame, with the added benefit of working correctly inside a WebXR session (where requestAnimationFrame alone doesn't sync to the headset's refresh rate, see the WebXR guide). Inside the callback: update any animated state (physics step, AnimationMixer, TSL uniforms), then call renderer.render(scene, camera).
For a scene that never changes after the first frame (a static product shot, for example), you don't need a continuous loop at all. A single renderer.render(scene, camera) call is enough, called again only when something actually changes (camera moved, a property updated).
Resize handling and cleanup
On window resize, three things need updating together: camera.aspect (or the orthographic frustum) plus camera.updateProjectionMatrix(), and renderer.setSize(width, height). Missing any one of these causes a stretched or incorrectly-sized render.
Cleanup matters for single-page apps that mount/unmount a Three.js scene repeatedly (e.g. a React component). Geometries, materials and textures hold GPU resources that aren't automatically freed when a JavaScript object goes out of scope. Call .dispose() on geometries, materials and textures, and renderer.dispose() on the renderer itself, when a scene is torn down, or repeated mount/unmount cycles will leak GPU memory.
Code
Learn this properly
Learn Practical TSL
Your First Node Material
This exact setup is where the course's first lesson begins.
Frequently asked questions
Do I need requestAnimationFrame with Three.js?
Use renderer.setAnimationLoop() instead. It wraps requestAnimationFrame and is required (not just recommended) for WebXR sessions to sync correctly with the headset's refresh rate.
Why does my Three.js scene leak memory over time?
Geometries, materials and textures hold GPU resources that aren't freed automatically. Call .dispose() on them (and renderer.dispose() on the renderer) when tearing down a scene, especially in apps that mount/unmount a Three.js scene repeatedly.
What pixel ratio should I use in Three.js?
renderer.setPixelRatio(window.devicePixelRatio), but capped: Math.min(devicePixelRatio, 2) is the common pattern, since uncapped device pixel ratio on high-DPI mobile screens can significantly hurt performance for a mostly imperceptible visual gain.
Keep reading
Camera
Use PerspectiveCamera for anything meant to look real: it renders with foreshortening, so distant objects appear smaller…
WebGPU vs WebGL
WebGPU is the successor to WebGL: a lower-level, more modern graphics API that exposes compute shaders and reduces CPU o…
What is Three.js
Three.js is a free, open-source JavaScript library for rendering 3D graphics in a web browser using WebGL or WebGPU. It …
All Three.js Guides
Back to the guides hub.