Three.js Architecture Overview

How a 3D scene flows from JavaScript objects to GPU pixels — tracing the data path through every major subsystem.

What Three.js Is

Three.js is a scene graph abstraction over WebGL. It manages the full pipeline from high-level objects (meshes, lights, cameras) down to raw GPU draw calls, shader compilation, and buffer uploads.

The entry-point pattern from the README:

import * as THREE from 'three';

// Scene graph
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10);
camera.position.z = 1;

// Geometry + Material → Mesh
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

// Renderer: orchestrates the whole pipeline
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
renderer.setAnimationLoop(animate);
document.body.appendChild(renderer.domElement);

function animate(time) {
  mesh.rotation.x = time / 2000;
  mesh.rotation.y = time / 1000;
  renderer.render(scene, camera); // ← everything happens here
}

Every call to renderer.render(scene, camera) triggers the full pipeline described in this documentation.

Architecture Map

The major subsystems and their relationships:

USER CODE scene.add(mesh) renderer.render(scene, camera) │ │ ▼ ▼ SCENE GRAPH WEBGL RENDERER Scene │ └─ Object3D (hierarchy) ├─ 1. updateMatrixWorld() ← scene traversal + matrix calc ├─ Mesh ├─ 2. projectObject() ← visibility / frustum cull │ ├─ BufferGeometry ├─ 3. RenderList.sort() ← opaque front→back, transparent back→front │ └─ Material ├─ 4. shadowMap.render() ← depth pass for shadows ├─ Light ├─ 5. renderScene() ← opaque → transmissive → transparent └─ Camera │ └─ renderObject() │ ├─ getProgram() ← compile/cache GLSL shaders │ ├─ setUniforms() ← lights, textures, matrices GPU │ └─ bindingStates.setup() ← VAO, attribute pointers WebGL Context ←────────────── └─ 6. gl.drawElements() ← actual GPU draw call Shader Program Vertex Buffer (VBO) Index Buffer (IBO) Vertex Array Object (VAO) Framebuffer / Texture
Data Flow: Step by Step
1
Scene Graph Construction
User creates Scene, Mesh (geometry + material), and Camera. scene.add(mesh) sets parent/child links in the Object3D tree. No GPU work yet — this is all JavaScript object management.
2
Matrix Hierarchy Update
scene.updateMatrixWorld() walks the tree depth-first, composing each node's local transform (position × rotation × scale) into a world-space matrixWorld. The camera also gets a matrixWorldInverse (the view matrix) and projectionMatrix.
3
Scene Traversal & Culling
projectObject() walks the scene graph recursively. Each Mesh is checked against the camera frustum and layer mask. Visible objects are pushed into a RenderList categorized as opaque, transmissive, or transparent, with their clip-space Z depth recorded.
4
Render List Sorting
Opaque objects sort front-to-back (Z ascending) to maximize early Z-rejection on the GPU. Transparent objects sort back-to-front (Z descending) so alpha blending composites correctly. Within each group, objects sort by material ID to reduce GPU state changes.
5
Shadow Pass
For each shadow-casting light, the scene is rendered from the light's perspective into a depth texture (shadow map). Later, the main render samples this texture to determine which fragments are in shadow.
6
Shader Program Compilation & Caching
getProgram() computes a cache key from the material type, light configuration, fog, skinning, and other state. If no cached program exists, it compiles GLSL vertex and fragment shaders from built-in chunks, links them, and stores the result.
7
Uniform Upload & Vertex Binding
Per-draw uniforms (model/view/projection matrices, material color, textures, light data) are written to the GPU. Vertex attributes (position, normal, UV) are bound via a Vertex Array Object (VAO) that maps BufferAttribute arrays to shader attribute slots.
8
GPU Draw Call
gl.drawElements() (indexed) or gl.drawArrays() (non-indexed) fires. The vertex shader runs per vertex, the rasterizer interpolates, and the fragment shader runs per pixel. Output goes to the canvas (or a render target for post-processing).
Component Pages
Key Concepts & External References

Scene Graph

Rendering Pipeline

Math

Transparency & Sorting

Source Code Entry Points

All links are permalinks to commit d59cf621.