Understanding Three.js Lighting — A Concise Reference
TL;DR: Start with an Ambient/Hemisphere fill, add a Directional for sun, use Point/Spot sparingly for local effects, and RectArea for studio soft light.
Read time: ~3–4 minutes
Lighting transforms a flat scene into something believable. This short reference explains the six core Three.js lights (plus a note on LightProbe), when to use them, and practical performance tips.
The lights at a glance
| Light | Real-world | What it does | Use / performance | Notes |
|---|---|---|---|---|
| AmbientLight | Overcast / studio fill | Uniform light, no shadows | ✅ Very cheap — always add a little | Use low intensity (0.1–0.5) to avoid flatness |
| DirectionalLight | Sun / flood | Parallel rays, good shadows | 🟡 Moderate — efficient for large scenes | No distance falloff; tune shadow.camera for quality |
| HemisphereLight | Sky above / ground below | Sky color on up-facing, ground color on down-facing | ✅ Cheap — natural outdoor tint | Params: skyColor, groundColor, intensity
|
| PointLight | Bulb / candle | Radiates in all directions, attenuates | 🔴 Expensive if many + shadows | Use distance and decay (constructor: color, intensity, distance, decay) |
| RectAreaLight | Softbox | Soft directional illumination | 🔴 Expensive — studio-quality | Works only with MeshStandardMaterial / MeshPhysicalMaterial; requires examples lib init |
| SpotLight | Flashlight / headlight | Cone-shaped beam; adjustable angle & penumbra | 🔴 Most expensive if casting shadows | Needs a target added to the scene; tune angle, penumbra, decay
|
Note — LightProbe: Useful for image-based PBR lighting (cheap ambient for materials). Pairs with environment maps and PMREMGenerator.
Quick, practical setups
Assumes
sceneandTHREEare available.
1) Outdoor / daylight (realistic, moderate cost)
scene.add(new THREE.AmbientLight(0xffffff, 0.3));
const sun = new THREE.DirectionalLight(0xffffff, 0.9);
sun.position.set(10, 15, 5);
sun.castShadow = true;
sun.shadow.mapSize.set(1024, 1024);
sun.shadow.camera.left = -20;
sun.shadow.camera.right = 20;
sun.shadow.bias = -0.0005;
scene.add(sun);
Good for landscapes and day/night cycles. Ambient prevents pitch-black shadows.
2) Interior / dynamic (medium cost)
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const lamp = new THREE.PointLight(0xffeecc, 1, 15, 2); // color, intensity, distance, decay
lamp.position.set(0, 3, 0);
lamp.castShadow = true;
scene.add(lamp);
const accent = new THREE.SpotLight(0xff9000, 0.8, 30, Math.PI / 6, 0.2, 2);
accent.position.set(5, 4, 3);
scene.add(accent);
scene.add(accent.target); // remember to add the target to the scene
Limit shadow-casting lights to a few; prefer baked lighting for fixed interiors.
3) Studio / product (higher cost — high quality)
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
RectAreaLightUniformsLib.init();
scene.add(new THREE.AmbientLight(0xffffff, 0.4));
const key = new THREE.RectAreaLight(0xffffff, 2, 4, 4);
key.position.set(-5, 4, 3);
key.lookAt(0, 0, 0);
scene.add(key);
const back = new THREE.DirectionalLight(0xff9900, 0.6);
back.position.set(0, 3, -8);
scene.add(back);
Note: RectAreaLight only lights MeshStandardMaterial / MeshPhysicalMaterial and requires RectAreaLightUniformsLib.init() (examples helper).
Performance rules of thumb
- Start with Ambient (0.2–0.3). Cheap and prevents black areas.
-
Use 1 Directional for sun/moon effects; tune
shadow.camerabounds for shadow quality. - Cap Point/Spot lights to ~3–5 in real-time; each shadowed light is costly.
-
Disable shadows on lights that don’t need them:
light.castShadow = false. - Decay = 2 is standard for realistic attenuation with PointLight/SpotLight; modern Three.js uses physical units by default.
-
Shadow tuning: reduce
shadow.mapSize, constrainshadow.camera, and useshadow.biasto fight acne.
Key takeaways
- 2–4 lights is usually enough — more lights ≠ better visuals, just more cost.
- AmbientLight is your safety net. Use a low intensity to soften contrast.
- Reserve Point/Spot/RectArea for visual impact where they matter.
- Profile your scene (Three.js DevTools / Chrome DevTools) to find bottlenecks.
Top comments (0)