Three.js Shadows — PCF, VSM, CSM & Tuning
Three.js implements shadow mapping: the scene is rendered from the light's point of view into a depth texture, which is then compared during the main render pass. This guide covers enabling shadows, choosing shadow types, eliminating shadow acne, and scaling to large scenes with cascaded shadow maps.
1Enable shadows on renderer, lights, and objects
Shadow rendering requires three opt-in flags — all three must be set:
DirectionalLight, SpotLight, and
PointLight. AmbientLight and
HemisphereLight do not cast shadows — they have no single
direction.
2Shadow map types — BasicShadowMap to VSM
| Type | Quality | Cost | Best for |
|---|---|---|---|
BasicShadowMap |
Hard, aliased | Lowest | Debugging / stylised |
PCFShadowMap |
Soft PCF filter | Low | Default; most games |
PCFSoftShadowMap |
Softer, wider | Medium | Architectural viz |
VSMShadowMap |
Very soft, bilinear | Medium+ | Open landscapes |
3Tuning the shadow camera frustum
A DirectionalLight uses an orthographic shadow camera.
Its frustum must be as tight as possible around the
visible scene for best shadow texel density:
mapSize — texture memory is
limited and a 4096² map uses 64× more memory than a 512² one.
4Eliminating shadow acne with bias
Shadow acne (self-shadowing stripes) appears because
depth comparison precision is limited. Fix it with
bias and normalBias:
5Cascaded Shadow Maps (CSM) for large scenes
CSM splits the view frustum into near/mid/far cascades, each with its
own shadow map. Near objects get more texels; distant objects fewer.
Available via three/examples/jsm:
6Performance tips
-
Freeze static shadows — set
renderer.shadowMap.autoUpdate = falseand callrenderer.shadowMap.needsUpdate = trueonly when objects move. - Limit active shadow lights — each shadow light is a full GPU scene render. Keep it to 1–2 at most unless using mobile-optimised techniques.
-
Use smaller mapSize for point lights — a
PointLightrenders 6 shadow maps (one per cube face). Even512×512= 6 shadow render passes. -
Disable shadows on small/distant objects — set
obj.castShadow = falsefor objects that never cast a visible shadow. -
Half-float VSM — Three.js uses RGB packing for VSM
by default. Enable
renderer.shadowMap.type = THREE.VSMShadowMaponly if you need very smooth, blurrable shadows.
Frequently Asked Questions
What will I learn in this tutorial?
Master shadow rendering in Three.js: shadow map types (PCF, PCFSOFT, VSM), cascaded shadow maps, bias tuning, and performance best practices.
What topics are covered in this tutorial?
This tutorial covers: Enable shadows on renderer, lights, and objects, Shadow map types — BasicShadowMap to VSM, Tuning the shadow camera frustum, Eliminating shadow acne with bias, Cascaded Shadow Maps (CSM) for large scenes, Performance tips.
What tools and technologies does this tutorial use?
This tutorial uses Three.js, Shadow Maps, PCF, VSM, CSM.
How long does this tutorial take?
This tutorial takes approximately 40 minutes to complete.
What prerequisites do I need before starting?
This is a Intermediate-level tutorial — no special preparation beyond basic JavaScript is assumed.