| name | threejs-lighting |
| description | Configures Three.js lights — AmbientLight, DirectionalLight, PointLight, SpotLight, RectAreaLight, shadows, HDR environment lighting, and light probes. Use when the user asks about lighting, shadows, light setup, HDR, environment maps for lighting, or realistic rendering. Trigger keywords: light, lighting, shadow, DirectionalLight, PointLight, SpotLight, ambient, HDRI, environment. |
Three.js Lighting
Light Types
const ambient = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambient);
const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b7355, 0.5);
scene.add(hemi);
const dir = new THREE.DirectionalLight(0xffffff, 1.5);
dir.position.set(5, 10, 5);
dir.castShadow = true;
scene.add(dir);
const point = new THREE.PointLight(0xff8800, 2, 20, 2);
point.position.set(0, 3, 0);
scene.add(point);
const spot = new THREE.SpotLight(0xffffff, 3, 30, Math.PI / 6, 0.3, 2);
spot.position.set(0, 10, 0);
spot.target.position.set(0, 0, 0);
scene.add(spot);
scene.add(spot.target);
const rectArea = new THREE.RectAreaLight(0xffffff, 5, 4, 2);
rectArea.position.set(0, 3, 5);
rectArea.lookAt(0, 0, 0);
scene.add(rectArea);
import { RectAreaLightUniformsLib } from "three/addons/lights/RectAreaLightUniformsLib.js";
RectAreaLightUniformsLib.init();
See SHADOWS.md for complete shadow configuration.
Shadow Setup
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
dir.castShadow = true;
dir.shadow.mapSize.set(2048, 2048);
dir.shadow.camera.near = 0.5;
dir.shadow.camera.far = 50;
dir.shadow.camera.left = -10;
dir.shadow.camera.right = 10;
dir.shadow.camera.top = 10;
dir.shadow.camera.bottom = -10;
dir.shadow.bias = -0.001;
dir.shadow.normalBias = 0.02;
mesh.castShadow = true;
ground.receiveShadow = true;
const helper = new THREE.CameraHelper(dir.shadow.camera);
scene.add(helper);
HDRI Environment Lighting
import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
const pmrem = new THREE.PMREMGenerator(renderer);
pmrem.compileEquirectangularShader();
new RGBELoader().load("/env/studio.hdr", (hdr) => {
const envMap = pmrem.fromEquirectangular(hdr).texture;
scene.background = envMap;
scene.environment = envMap;
hdr.dispose();
pmrem.dispose();
});
Light Intensity Scale
Three.js r155+ uses physical light units when renderer.useLegacyLights = false (default from r155):
dir.intensity = 3;
point.intensity = 100;
renderer.useLegacyLights = true;
Light Helpers
scene.add(new THREE.DirectionalLightHelper(dir, 1));
scene.add(new THREE.PointLightHelper(point, 0.3));
scene.add(new THREE.SpotLightHelper(spot));
scene.add(new THREE.HemisphereLightHelper(hemi, 1));
spotHelper.update();
Common Gotchas
RectAreaLight does NOT cast shadows
AmbientLight and HemisphereLight do NOT cast shadows
SpotLight.target must be added to the scene separately
- Shadow camera frustum must tightly wrap your scene — too large = blurry shadows
shadow.bias fixes acne but too negative causes peter-panning (shadow detaches)
- Physical light units (r155+): multiply your old intensity values by ~π for similar results
- Always
CameraHelper the shadow camera when debugging shadow issues