Lighting
A 3D context carries a list of lights. Each one has a colour and an intensity, and — depending on its type — a direction, a position, a falloff and a cone. Both the Canvas and WebGPU backends resolve the same lighting model, so a rig looks the same whichever one you render with.
NOTE
For the full API, see the 3D API Reference.
Demo
The default rig
A context with no lighting configured carries an ambient light at intensity 0.3 and a directional light at 0.7, which together resolve to the flat shading model earlier versions used. Add to that list, or clear it and build your own.
context.lights.add(createPointLight({ position: [0, 3, 0], intensity: 8 }));context.lightDirection and context.lightMode remain as shorthands for the default rig's directional light. Once you replace the rig, they no longer apply.
Light types
Ambient
Reaches every surface equally regardless of orientation. Use it to lift the shadows rather than as the main source — on its own it flattens a shape completely.
createAmbientLight({ color: '#404860', intensity: 0.25 });Hemisphere
Fades from one colour overhead to another underfoot, reading as bounced daylight. Cheaper and more natural than two opposed directional lights.
createHemisphereLight({ color: '#a0c8ff', groundColor: '#4a3520', intensity: 0.6 });Directional
Infinitely far away, casting parallel rays. The workhorse for a key light; has a direction but no position, so distance never affects it.
createDirectionalLight({ direction: [-1, -1, -1], color: '#fff2e0', intensity: 0.8 });Point
Radiates in every direction from a position, dimming with distance.
createPointLight({
position: [2, 3, 1],
intensity: 10,
distance: 12,
decay: 2,
});Spot
A point light confined to a cone, with an optionally soft edge.
createSpotLight({
position: [0, 5, 0],
direction: [0, -1, 0],
angle: Math.PI / 8,
penumbra: 0.4,
intensity: 20,
});Properties
color: the light's colour (default'#ffffff')intensity: how strongly it contributes (default1)enabled: whether it contributes at all (defaulttrue)direction: the direction the light travels in, normalized on assignment — directional and spot onlyposition: the light's world-space position — point and spot onlydistance: the distance at which the light falls to zero;0means it never does (default0)decay: the exponent of the inverse-distance falloff (default2, physically plausible)angle: half-angle of a spot cone in radians, clamped below a right angle (defaultMath.PI / 6)penumbra: how softly a spot cone fades at its edge,0to1(default0)groundColor: the downward colour of a hemisphere light (default'#000000')space:'world'or'camera'— whether orientation is fixed or follows the camera (default'world')
Falloff and cone attenuation follow the same conventions as three.js, so a rig tuned against those numbers reads the same here.
Camera-space lights
A 'world' light stays put as the camera orbits, which is what you want for a scene with a sense of place. A 'camera' light travels with the viewer — a head torch — which keeps a shape readable while the camera moves around it.
createDirectionalLight({ direction: [0, 0, -1], space: 'camera' });Managing the list
const key = createDirectionalLight({ direction: [-1, -1, -1] });
context.lights.add(key);
context.lights.remove(key);
context.lights.clear();
context.lights.length;
context.lights.find('directional');Changing a property on a light already in the list repaints the scene, so a slider bound to light.intensity works with no further wiring.
WARNING
A render pass carries at most 8 lights. Beyond that, the extras are dropped and a warning is logged.
Fog
Distance haze blends geometry towards a colour, and both backends resolve it identically.
context.fog = {
color: '#101820',
near: 5,
far: 40,
};
context.fog = {
mode: 'exponential',
color: '#101820',
density: 0.04,
};