Fixing Three.js Shadow Artifacts with normalBias

This article explains the role of the normalBias property in Three.js and how it is used to eliminate shadow artifacts, such as shadow acne, without causing detached shadows. You will learn the mechanical differences between standard bias and normalBias, and how to apply this property to achieve clean, realistic shadows in your 3D scenes.

In Three.js, shadows are generated using shadow maps, which are depth textures rendered from the perspective of the light source. Because of the discrete resolution of these shadow maps, surfaces can incorrectly cast shadows on themselves. This phenomenon is known as “shadow acne” and appears as distracting, Moire-like striped patterns across 3D meshes.

Traditionally, developers used the standard bias property to solve this. The bias property slightly offsets the depth values of the shadow map along the light’s direction. While effective at removing shadow acne, a high bias value introduces a new artifact called “peter-panning,” where shadows appear detached from the objects casting them, making elements look like they are floating.

The normalBias property addresses this limitation. Instead of shifting the depth calculation along the view vector of the light, normalBias offsets the shadow query position along the geometry’s surface normals (the direction pointing directly outward from each face).

By shifting the calculation along the surface normal, normalBias prevents self-shadowing on curved and angled surfaces without pushing the overall shadow away from the base of the object. This makes it highly effective for organic shapes, rounded meshes, and complex geometries where standard bias would fail.

To use normalBias in Three.js, you apply it directly to a light’s shadow object:

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.castShadow = true;

// Set normalBias to a small positive value
directionalLight.shadow.normalBias = 0.05; 

When fine-tuning shadows, the best practice is to keep both bias and normalBias values as close to zero as possible. Start by setting bias to 0, and gradually increase normalBias in tiny increments (such as 0.01 to 0.05) until the shadow acne disappears. Combining a very small standard bias with a targeted normalBias often yields the most visually accurate results.