Configure DirectionalLight Shadow Camera in Three.js

Configuring the shadow camera bounds for a DirectionalLight in Three.js is essential for achieving sharp, high-quality shadows without sacrificing performance. Because directional lights project shadows using an orthographic projection, you must manually define a bounding box (frustum) that encapsulates only the objects in your scene that cast or receive shadows. This guide provides a direct, step-by-step approach to setting up, optimizing, and visualizing these shadow camera boundaries.

Understanding the Shadow Camera

In Three.js, a DirectionalLight uses an OrthographicCamera hidden inside its shadow property to render shadow maps. This camera is configured using six main boundaries: left, right, top, bottom, near, and far.

If this bounding box is too large, your shadows will look pixelated and blurry because the shadow map texture is stretched over too wide an area. If the box is too small, shadows will be clipped or cut off.

Step-by-Step Configuration

To properly configure the shadow camera, you need to adjust its boundary properties and update its projection matrix.

1. Enable Shadows and Set Resolution

First, enable shadow casting on your directional light and set the resolution of your shadow map. Higher values yield sharper shadows but cost more performance.

const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, 20, 10);
light.castShadow = true;

// Set the shadow map resolution (must be powers of 2)
light.shadow.mapSize.width = 2048; 
light.shadow.mapSize.height = 2048;

2. Define the Camera Bounds

Adjust the left, right, top, bottom, near, and far properties of the shadow camera. Keep these boundaries as tight as possible around your active scene objects.

const d = 15; // The reach of the shadow camera from the light's center

light.shadow.camera.left = -d;
light.shadow.camera.right = d;
light.shadow.camera.top = d;
light.shadow.camera.bottom = -d;

// Define how close and how far the camera looks
light.shadow.camera.near = 0.5; 
light.shadow.camera.far = 50;

3. Update the Projection Matrix

Whenever you modify the shadow camera’s properties, you must tell Three.js to recalculate its projection mathematical matrix.

light.shadow.camera.updateProjectionMatrix();
scene.add(light);

4. Visualize the Bounds (Crucial for Debugging)

It is highly recommended to use the CameraHelper to visually inspect the boundary box in your scene. This lets you see exactly where the shadow camera is cutting off.

const shadowHelper = new THREE.CameraHelper(light.shadow.camera);
scene.add(shadowHelper);

Using this helper, adjust the d variable (and the near/far planes) until the yellow helper box snugly fits your 3D models. Once you are satisfied with the shadow quality and coverage, you can remove or hide the helper.