Skip to main content

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);