Scene
A Three.js scene is the root Object3D — a tree of meshes, lights, cameras, helpers. Add children with add(), traverse with traverse(), dispose carefully when removing.
Build, traverse, dispose, scene graph
EXAMPLE
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
// 1) Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0b0b0b);
scene.fog = new THREE.Fog(0x0b0b0b, 10, 50);
const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 1000);
camera.position.set(5, 5, 10);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputColorSpace = THREE.SRGBColorSpace;
document.body.appendChild(renderer.domElement);
// 2) Lights
scene.add(new THREE.AmbientLight(0xffffff, 0.25));
const sun = new THREE.DirectionalLight(0xffffff, 2);
sun.position.set(5, 10, 7);
scene.add(sun);
// 3) Meshes
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(50, 50),
new THREE.MeshStandardMaterial({ color: 0x555555 }),
);
floor.rotation.x = -Math.PI / 2;
floor.name = 'floor';
scene.add(floor);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0x0ea5e9 }),
);
cube.position.set(0, 0.5, 0);
cube.name = 'hero-cube';
scene.add(cube);
// 4) Group — organise children
const building = new THREE.Group();
building.name = 'building';
building.add(makeWall());
building.add(makeRoof());
building.add(makeDoor());
building.position.set(5, 0, 0);
scene.add(building);
// 5) Resize handler
addEventListener('resize', () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
// 6) Render loop
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
function tick() {
controls.update();
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(tick);
}
tick();
// 7) Traverse the scene
scene.traverse((obj) => {
if (obj.isMesh) {
obj.castShadow = true;
obj.receiveShadow = true;
}
});
// Find by name
const target = scene.getObjectByName('hero-cube');
// Filter
const meshes = [];
scene.traverse((o) => o.isMesh && meshes.push(o));
// 8) Add / remove children
const extra = new THREE.Mesh(...);
scene.add(extra);
// Later:
scene.remove(extra);
// IMPORTANT — dispose GPU resources
extra.geometry.dispose();
extra.material.dispose();
if (extra.material.map) extra.material.map.dispose();
// 9) Helper — dispose a whole subtree
function disposeNode(node) {
node.traverse((o) => {
if (o.geometry) o.geometry.dispose();
if (o.material) {
const mats = Array.isArray(o.material) ? o.material : [o.material];
for (const m of mats) {
for (const k of ['map','normalMap','roughnessMap','metalnessMap','aoMap','emissiveMap','envMap','alphaMap']) {
if (m[k]) m[k].dispose();
}
m.dispose();
}
}
});
}
scene.remove(building);
disposeNode(building);
// 10) Load a glTF model
const loader = new GLTFLoader();
const gltf = await loader.loadAsync('/models/car.glb');
const car = gltf.scene;
car.scale.setScalar(0.5);
car.position.set(-3, 0, 0);
scene.add(car);
// 11) Background — solid, color, texture, environment
scene.background = new THREE.Color(0x0b0b0b);
scene.background = new THREE.TextureLoader().load('/sky.jpg');
// Environment map (PMREM for PBR materials)
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
const pmrem = new THREE.PMREMGenerator(renderer);
const hdr = await new RGBELoader().loadAsync('/env/studio.hdr');
const envMap = pmrem.fromEquirectangular(hdr).texture;
hdr.dispose(); pmrem.dispose();
scene.environment = envMap;
scene.background = envMap;
// 12) World vs local coordinates
cube.position.set(0, 0, 0);
building.add(cube);
// cube.position is now relative to building. World position:
const world = new THREE.Vector3();
cube.getWorldPosition(world);
// 13) Updating object transforms
cube.position.x = 5;
cube.rotation.set(0, Math.PI / 4, 0);
cube.scale.setScalar(2);
cube.updateMatrixWorld(); // usually automatic each render; force if you need it now
// 14) Helpers for debugging
scene.add(new THREE.AxesHelper(2));
scene.add(new THREE.GridHelper(20, 20));
scene.add(new THREE.BoxHelper(cube, 0xff0000));
// 15) Performance + memory tips
// • Reuse geometries + materials across many meshes (InstancedMesh for thousands)
// • Dispose textures + materials when removing objects
// • renderer.info gives draw calls, triangle counts
// • Use scene.matrixAutoUpdate = false on static groups to save matrix work
// • Frustum culling is automatic; if your object 'disappears' check frustumCulled
// 16) Teardown when leaving the page
function cleanup() {
cancelAnimationFrame(rafId);
disposeNode(scene);
renderer.dispose();
renderer.domElement.remove();
controls.dispose();
}
Why it matters
Three.js doesn’t garbage-collect GPU resources for you. Build a disposeNode helper early and call it whenever you remove a subtree — long-running apps leak fast otherwise.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
const scene = new THREE.Scene(); scene.background = new THREE.Color(0x111); scene.add(mesh);Try it Yourself »
Exercise
Add an object to the scene.
scene.
(cube);
Three letters.
Discussion
Loading…