iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

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…