React Three Fiber lighting
Check installed Three.js, Fiber, and Drei versions and the renderer first. This example targets Fiber 9 / React 19, Three.js r185, and WebGL.
Start with a deliberate lighting setup
- Use environment lighting for PBR reflections/fill and direct lights for direction and real-time shadowing. More ambient light will not restore missing metallic reflections.
- A scene background and
scene.environment serve different purposes. Drei Environment assigns lighting; background additionally makes it visible behind the scene.
- Prefer an owned HDR/EXR asset in production. Drei presets are useful for prototyping but depend on external hosting. Check loader support before choosing newer formats.
Sky is visible sky geometry, not automatically a matching sun light or environment. Align the sky, direct light, and environment when visual consistency matters.
Shadowed scene
Mount inside <Canvas shadows="percentage">. On Three.js r182+, PCFShadowMap is soft; Fiber 9's bare shadows selects the deprecated PCFSoftShadowMap.
export default function Example() {
return (
<>
<ambientLight intensity={0.3} />
<directionalLight
position={[3, 5, 3]}
intensity={3}
castShadow
shadow-mapSize={[1024, 1024]}
shadow-camera-left={-4}
shadow-camera-right={4}
shadow-camera-top={4}
shadow-camera-bottom={-4}
shadow-camera-near={0.5}
shadow-camera-far={15}
shadow-normalBias={0.02}
/>
<mesh castShadow position={[0, 0.5, 0]}>
<boxGeometry />
<meshStandardMaterial color="coral" />
</mesh>
<mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[8, 8]} />
<meshStandardMaterial color="silver" />
</mesh>
</>
)
}
Bias and frustum values above are for this small scene; retune them for actual dimensions.
Shadows and light targets
- Shadow mapping needs renderer shadows enabled, a shadow-casting light, casting meshes, and receiving materials/meshes. Ambient and hemisphere lights do not cast shadows.
- Tighten the shadow camera to the useful region before increasing map resolution. Inspect its frustum with a CameraHelper; bias should address acne without detaching shadows from objects.
- Point-light shadows render six directions. Limit shadow-casting lights and large maps; cost depends on affected geometry and passes, not just light count.
- Moving a directional/spot light's target requires a target Object3D whose world matrix updates. Add a custom target to the scene graph; changing only a detached target's position can leave its world transform stale.
- With WebGL, RectAreaLight affects Standard/Physical materials and does not cast built-in shadows. Initialize
RectAreaLightUniformsLib when using the native light path that requires it.
- Object/camera layers are not general per-light material masks in WebGLRenderer. Do not promise that matching a light layer to a mesh makes selective illumination work.
Environment and helper cost
- Drei
Lightformer is emissive geometry captured into an Environment; it is not an ordinary real-time light and does not cast direct-light shadows.
- Set
frames={1} for genuinely static environment captures or ContactShadows. Animated objects/lighting need recapture; a frozen capture will remain stale.
- ContactShadows renders an offscreen depth/blur approximation. It is not free and does not replace all directional shadows.
- AccumulativeShadows converges across samples; changing the scene can require reset/reaccumulation. BakeShadows freezes updates rather than producing a portable baked lightmap.
- SoftShadows patches WebGL shader code. Verify it against the installed Three.js shadow implementation before adding it, especially after a renderer upgrade.
- Keep tone mapping/exposure consistent while tuning lights. Current physically based light intensities should not be mixed blindly with old legacy-light tutorials.
Verify
Check shadow contact, acne, clipping, loaded-model cast/receive flags, and moving objects. Compare static versus animated capture behavior and measure total render passes on the target device.
Sources
1---2name: r3f-lighting3description: Light React Three Fiber scenes with direct lights, environment maps, and shadows. Use for light placement, image-based lighting, shadow artifacts, and lighting performance.4---5
6# React Three Fiber lighting
7
8Check installed Three.js, Fiber, and Drei versions and the renderer first. This example targets Fiber 9 / React 19, Three.js r185, and WebGL.
9
10## Start with a deliberate lighting setup
11
12- Use environment lighting for PBR reflections/fill and direct lights for direction and real-time shadowing. More ambient light will not restore missing metallic reflections.
13- A scene background and `scene.environment` serve different purposes. Drei `Environment` assigns lighting; `background` additionally makes it visible behind the scene.
14- Prefer an owned HDR/EXR asset in production. Drei presets are useful for prototyping but depend on external hosting. Check loader support before choosing newer formats.
15- `Sky` is visible sky geometry, not automatically a matching sun light or environment. Align the sky, direct light, and environment when visual consistency matters.
16
17## Shadowed scene
18
19Mount inside `<Canvas shadows="percentage">`. On Three.js r182+, PCFShadowMap is soft; Fiber 9's bare `shadows` selects the deprecated PCFSoftShadowMap.
20
21```tsx
22export default function Example() {
23 return (
24 <>
25 <ambientLight intensity={0.3} />
26 <directionalLight
27 position={[3, 5, 3]}
28 intensity={3}
29 castShadow
30 shadow-mapSize={[1024, 1024]}
31 shadow-camera-left={-4}
32 shadow-camera-right={4}
33 shadow-camera-top={4}
34 shadow-camera-bottom={-4}
35 shadow-camera-near={0.5}
36 shadow-camera-far={15}
37 shadow-normalBias={0.02}
38 />
39 <mesh castShadow position={[0, 0.5, 0]}>
40 <boxGeometry />
41 <meshStandardMaterial color="coral" />
42 </mesh>
43 <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]}>
44 <planeGeometry args={[8, 8]} />
45 <meshStandardMaterial color="silver" />
46 </mesh>
47 </>
48 )
49}
50```
51
52Bias and frustum values above are for this small scene; retune them for actual dimensions.
53
54## Shadows and light targets
55
56- Shadow mapping needs renderer shadows enabled, a shadow-casting light, casting meshes, and receiving materials/meshes. Ambient and hemisphere lights do not cast shadows.
57- Tighten the shadow camera to the useful region before increasing map resolution. Inspect its frustum with a CameraHelper; bias should address acne without detaching shadows from objects.
58- Point-light shadows render six directions. Limit shadow-casting lights and large maps; cost depends on affected geometry and passes, not just light count.
59- Moving a directional/spot light's target requires a target Object3D whose world matrix updates. Add a custom target to the scene graph; changing only a detached target's position can leave its world transform stale.
60- With WebGL, RectAreaLight affects Standard/Physical materials and does not cast built-in shadows. Initialize `RectAreaLightUniformsLib` when using the native light path that requires it.
61- Object/camera layers are not general per-light material masks in WebGLRenderer. Do not promise that matching a light layer to a mesh makes selective illumination work.
62
63## Environment and helper cost
64
65- Drei `Lightformer` is emissive geometry captured into an Environment; it is not an ordinary real-time light and does not cast direct-light shadows.
66- Set `frames={1}` for genuinely static environment captures or ContactShadows. Animated objects/lighting need recapture; a frozen capture will remain stale.
67- ContactShadows renders an offscreen depth/blur approximation. It is not free and does not replace all directional shadows.
68- AccumulativeShadows converges across samples; changing the scene can require reset/reaccumulation. BakeShadows freezes updates rather than producing a portable baked lightmap.
69- SoftShadows patches WebGL shader code. Verify it against the installed Three.js shadow implementation before adding it, especially after a renderer upgrade.
70- Keep tone mapping/exposure consistent while tuning lights. Current physically based light intensities should not be mixed blindly with old legacy-light tutorials.
71
72## Verify
73
74Check shadow contact, acne, clipping, loaded-model cast/receive flags, and moving objects. Compare static versus animated capture behavior and measure total render passes on the target device.
75
76## Sources
77
78- [Drei Environment](https://drei.docs.pmnd.rs/staging/environment), [ContactShadows](https://drei.docs.pmnd.rs/staging/contact-shadows).
79- [Three.js shadows](https://threejs.org/manual/en/shadows.html), [RectAreaLight](https://threejs.org/docs/#RectAreaLight), [DirectionalLight](https://threejs.org/docs/#DirectionalLight).
80- [Migration guide](https://github.com/mrdoob/three.js/wiki/Migration-Guide) — PCF changes in r182 and environment rotation changes in r184.