Lighting
Lighting is essential for creating realistic 3D scenes in Three.js.
Light Types
AmbientLight
Provides uniform lighting from all directions.
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
// With color and intensity
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
ambientLight.color.setHex(0x404040);
ambientLight.intensity = 0.5;
DirectionalLight
Simulates sunlight with parallel rays.
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.target.position.set(0, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);
// Configure shadow
directionalLight.castShadow = true;
directionalLight.shadow.camera.left = -10;
directionalLight.shadow.camera.right = 10;
directionalLight.shadow.camera.top = 10;
directionalLight.shadow.camera.bottom = -10;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 50;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
PointLight
Emits light in all directions from a single point.
const pointLight = new THREE.PointLight(0xffffff, 1, 100, 2);
pointLight.position.set(0, 5, 0);
scene.add(pointLight);
// Parameters: color, intensity, distance, decay
const pointLight = new THREE.PointLight(0xffffff, 1, 100, 2);
pointLight.castShadow = true;
pointLight.shadow.camera.near = 0.1;
pointLight.shadow.camera.far = 25;
pointLight.shadow.mapSize.width = 1024;
pointLight.shadow.mapSize.height = 1024;
SpotLight
Emits light in a cone shape.
const spotLight = new THREE.SpotLight(0xffffff, 1, 100, Math.PI / 4, 0.5, 2);
spotLight.position.set(0, 10, 0);
spotLight.target.position.set(0, 0, 0);
scene.add(spotLight);
scene.add(spotLight.target);
// Parameters: color, intensity, distance, angle, penumbra, decay
spotLight.castShadow = true;
spotLight.shadow.camera.near = 0.1;
spotLight.shadow.camera.far = 25;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
HemisphereLight
Simulates outdoor lighting with sky and ground colors.
const hemisphereLight = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.5);
scene.add(hemisphereLight);
// Parameters: skyColor, groundColor, intensity
hemisphereLight.color.setHex(0x87ceeb); // Sky color
hemisphereLight.groundColor.setHex(0x8b4513); // Ground color
hemisphereLight.intensity = 0.5;
RectAreaLight
Emits light uniformly from a rectangular area.
// Requires RectAreaLightUniformsLib
import { RectAreaLightUniformsLib } from 'three/examples/jsm/lights/RectAreaLightUniformsLib.js';
RectAreaLightUniformsLib.init();
const rectAreaLight = new THREE.RectAreaLight(0xffffff, 1, 10, 10);
rectAreaLight.position.set(0, 5, 0);
rectAreaLight.lookAt(0, 0, 0);
scene.add(rectAreaLight);
// Parameters: color, intensity, width, height
Shadows
Enable Shadows
// Enable shadows in renderer
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Shadow map types
renderer.shadowMap.type = THREE.BasicShadowMap;
renderer.shadowMap.type = THREE.PCFShadowMap;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.shadowMap.type = THREE.VSMShadowMap;
Configure Shadow Casting
// Light casts shadows
directionalLight.castShadow = true;
pointLight.castShadow = true;
spotLight.castShadow = true;
// Objects cast shadows
mesh.castShadow = true;
// Objects receive shadows
groundMesh.receiveShadow = true;
Shadow Camera Settings
// Directional light shadow camera
directionalLight.shadow.camera.left = -10;
directionalLight.shadow.camera.right = 10;
directionalLight.shadow.camera.top = 10;
directionalLight.shadow.camera.bottom = -10;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 50;
// Point light shadow camera
pointLight.shadow.camera.near = 0.1;
pointLight.shadow.camera.far = 25;
pointLight.shadow.camera.fov = 90;
// Spot light shadow camera
spotLight.shadow.camera.near = 0.1;
spotLight.shadow.camera.far = 25;
spotLight.shadow.camera.fov = 30;
Shadow Quality
// Increase shadow map resolution
light.shadow.mapSize.width = 2048;
light.shadow.mapSize.height = 2048;
// Shadow bias (reduce shadow acne)
light.shadow.bias = -0.0001;
// Shadow radius (softer shadows)
light.shadow.radius = 5;
// Shadow blur samples
light.shadow.blurSamples = 25;
Light Helpers
// Directional light helper
const directionalLightHelper = new THREE.DirectionalLightHelper(
directionalLight,
1
);
scene.add(directionalLightHelper);
// Point light helper
const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
scene.add(pointLightHelper);
// Spot light helper
const spotLightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotLightHelper);
// Hemisphere light helper
const hemisphereLightHelper = new THREE.HemisphereLightHelper(
hemisphereLight,
1
);
scene.add(hemisphereLightHelper);
// RectArea light helper
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper.js';
const rectAreaLightHelper = new RectAreaLightHelper(rectAreaLight);
scene.add(rectAreaLightHelper);
// Shadow camera helper
const shadowHelper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(shadowHelper);
Lighting Setups
Basic Three-Point Lighting
// Key light (main light)
const keyLight = new THREE.DirectionalLight(0xffffff, 1);
keyLight.position.set(5, 10, 5);
keyLight.castShadow = true;
scene.add(keyLight);
// Fill light (softer, opposite side)
const fillLight = new THREE.DirectionalLight(0x8888ff, 0.3);
fillLight.position.set(-5, 5, 2);
scene.add(fillLight);
// Back light (rim lighting)
const backLight = new THREE.DirectionalLight(0xffffff, 0.5);
backLight.position.set(0, 5, -5);
scene.add(backLight);
// Ambient light (overall illumination)
const ambientLight = new THREE.AmbientLight(0x404040, 0.2);
scene.add(ambientLight);
Outdoor Scene
// Sun (directional light)
const sunLight = new THREE.DirectionalLight(0xffffff, 1);
sunLight.position.set(100, 100, 100);
sunLight.castShadow = true;
sunLight.shadow.camera.left = -50;
sunLight.shadow.camera.right = 50;
sunLight.shadow.camera.top = 50;
sunLight.shadow.camera.bottom = -50;
sunLight.shadow.camera.far = 200;
scene.add(sunLight);
// Sky light (hemisphere)
const skyLight = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.6);
scene.add(skyLight);
Indoor Scene
// Ceiling lights
const ceilingLight1 = new THREE.PointLight(0xffffff, 0.8, 20);
ceilingLight1.position.set(5, 8, 5);
ceilingLight1.castShadow = true;
scene.add(ceilingLight1);
const ceilingLight2 = new THREE.PointLight(0xffffff, 0.8, 20);
ceilingLight2.position.set(-5, 8, -5);
ceilingLight2.castShadow = true;
scene.add(ceilingLight2);
// Window light
const windowLight = new THREE.RectAreaLight(0xffffff, 2, 10, 10);
windowLight.position.set(-10, 5, 0);
windowLight.lookAt(0, 0, 0);
scene.add(windowLight);
// Ambient light
const ambientLight = new THREE.AmbientLight(0x404040, 0.1);
scene.add(ambientLight);
Light Animation
// Animate light position
function animate() {
const time = Date.now() * 0.001;
// Orbit light around scene
pointLight.position.x = Math.cos(time) * 10;
pointLight.position.z = Math.sin(time) * 10;
// Pulsing intensity
pointLight.intensity = 0.5 + 0.5 * Math.sin(time * 2);
// Color cycling
pointLight.color.setHSL((time * 0.1) % 1, 1, 0.5);
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Performance Optimization
// Limit number of lights
const maxLights = 8; // WebGL limit varies
// Use light distance property
pointLight.distance = 50; // Light doesn't affect objects beyond this distance
// Disable shadows for less important lights
ambientLight.castShadow = false;
fillLight.castShadow = false;
// Use lower shadow map resolution for distant lights
distantLight.shadow.mapSize.width = 512;
distantLight.shadow.mapSize.height = 512;
// Use hemisphere light instead of multiple directional lights
const hemisphereLight = new THREE.HemisphereLight(0x87ceeb, 0x8b4513, 0.5);
Light Probes
// Light probe for image-based lighting
const lightProbe = new THREE.LightProbe();
scene.add(lightProbe);
// Copy from cube camera
const cubeCamera = new THREE.CubeCamera(1, 1000, 512);
cubeCamera.position.set(0, 0, 0);
cubeCamera.update(renderer, scene);
lightProbe.copy(cubeCamera);