Lights
Lights drive shading on PBR materials. Three.js ships ambient (flat fill), directional (sun), point (bulb), spot (cone), and area (rectAreaLight). Most scenes use one directional + one ambient + an environment map.
Add lights, cast shadows, IBL
EXAMPLE
import * as THREE from 'three';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
// 1) Ambient light — flat fill, no direction, no shadows
const ambient = new THREE.AmbientLight(0xffffff, 0.25);
scene.add(ambient);
// 2) Hemisphere light — sky color above, ground color below
const hemi = new THREE.HemisphereLight(0xb1e1ff, 0xb97a20, 0.4);
scene.add(hemi);
// 3) Directional light — parallel rays, like the sun
const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(5, 10, 7);
sun.castShadow = true;
sun.shadow.mapSize.set(2048, 2048); // detail of the shadow
sun.shadow.camera.near = 0.5;
sun.shadow.camera.far = 50;
sun.shadow.camera.left = -20;
sun.shadow.camera.right = 20;
sun.shadow.camera.top = 20;
sun.shadow.camera.bottom = -20;
sun.shadow.bias = -0.0001;
scene.add(sun);
// 4) Point light — radial bulb
const bulb = new THREE.PointLight(0xffeedd, 5, 20, 2);
bulb.position.set(2, 3, 0);
bulb.castShadow = true;
scene.add(bulb);
// 5) Spot light — cone
const spot = new THREE.SpotLight(0xffffff, 10);
spot.position.set(0, 8, 0);
spot.angle = Math.PI / 6;
spot.penumbra = 0.2;
spot.decay = 2;
spot.distance = 30;
spot.castShadow = true;
scene.add(spot);
// Make the spot follow a target object
const target = new THREE.Object3D();
scene.add(target);
spot.target = target;
// 6) Rectangle area light (PBR realistic; doesn't cast shadows)
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
RectAreaLightUniformsLib.init();
const rect = new THREE.RectAreaLight(0xffffff, 10, 4, 1);
rect.position.set(0, 5, 0);
rect.lookAt(0, 0, 0);
scene.add(rect);
// 7) Receive shadows — meshes must opt-in
mesh.castShadow = true;
mesh.receiveShadow = true;
floor.receiveShadow = true;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 8) Image-based lighting (IBL) — environment maps drive PBR realism
const pmrem = new THREE.PMREMGenerator(renderer);
pmrem.compileEquirectangularShader();
const hdr = await new RGBELoader().loadAsync('/env/studio.hdr');
const envMap = pmrem.fromEquirectangular(hdr).texture;
hdr.dispose(); pmrem.dispose();
scene.environment = envMap; // every PBR material now reflects this
scene.background = envMap; // optional — visible background too
// 9) Tone mapping + exposure — make HDR lighting look right
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
// 10) Helpers — see where the light is going
scene.add(new THREE.DirectionalLightHelper(sun, 1));
scene.add(new THREE.PointLightHelper(bulb, 0.5));
scene.add(new THREE.SpotLightHelper(spot));
scene.add(new THREE.HemisphereLightHelper(hemi, 1));
// 11) Lighting recipes
// Outdoor — ambient(0.2) + directional sun(3) + envmap = sky
// Indoor — env map(2) + point/spot bulbs(5) + low ambient(0.05)
// Studio — three-point: key + fill + rim
// 12) Performance
// • Each shadow-casting light is one extra render pass per frame
// • Use 2K shadow maps for the sun, 1K for accent lights
// • Bake static lighting into lightmaps when possible (offline)
Why it matters
Image-based lighting (HDRI envmap) is the difference between “3D-looking” and “photo-real.” One scene.environment assignment shadows your PBR materials with realistic reflections and ambient color — far cheaper than dozens of point lights.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
scene.add(new THREE.AmbientLight(0xffffff, 0.3)); const dir = new THREE.DirectionalLight(0xffffff, 1); dir.position.set(5, 10, 7); scene.add(dir);Try it Yourself »
Discussion
Loading…