Cascaded Shadow Maps for Wide-Area Shadows in DirectX

Cascaded Shadow Maps (CSMs) are the industry-standard solution for rendering high-fidelity, wide-area directional shadows in modern graphics APIs like DirectX. When rendering outdoor scenes illuminated by a directional light source such as the sun, a single shadow map cannot provide adequate resolution across both near and distant geometry. CSMs resolve this issue by partitioning the camera's view frustum into multiple depth zones, assigning a dedicated shadow map to each partition. This overview explores how CSMs solve perspective aliasing, their technical implementation in DirectX, and the techniques used to blend cascades seamlessly.

The Problem of Perspective Aliasing

Directional lights cover vast, theoretically infinite areas because their rays are parallel. In a traditional shadow mapping pipeline, an orthographic projection matrix encompasses the entire visible scene.

When this single projection is mapped to a standard texture:

  • Geometry close to the camera occupies a massive portion of the screen but only a small fraction of the shadow map, causing severe perspective aliasing (blocky, pixelated shadow edges).
  • Distant geometry occupies few screen pixels but takes up significant texture space, wasting shadow map resolution where high detail is imperceptible.

Increasing the resolution of a single shadow map to eliminate close-up aliasing quickly becomes unfeasible due to video memory limitations and fill-rate bottlenecks.

How Cascaded Shadow Maps Solve the Problem

Cascaded Shadow Maps address perspective aliasing by aligning shadow map resolution with visual importance. The camera frustum is sliced into a series of sub-frustums along the Z-axis (view depth).

Each slice receives its own orthographic projection tightly bounded to that specific region:

  1. Near Cascades: Encompass small volumes close to the player, yielding high texel density per world unit and crisp shadow edges.
  2. Far Cascades: Encompass much larger volumes extending toward the horizon, providing lower texel density where screen-space perspective naturally conceals the loss of detail.

By distributing shadow texels non-linearly across the viewing range—typically using logarithmic or practical split schemes—CSMs maintain a uniform perceptual quality from the foreground to the horizon.

Implementation in DirectX

In DirectX (Direct3D 11 and 12), implementing CSMs relies on efficient resource management and specialized shader techniques:

  • Texture Arrays (Texture2DArray): Rather than creating individual textures for each cascade, developers allocate a single Texture2DArray. Each slice of the array represents one cascade layer. This enables the engine to bind all cascades simultaneously to the pixel shader using a single shader resource view (SRV).
  • Depth-Only Rendering: During the shadow pass, scene geometry is rendered to the shadow maps. In Direct3D 11/12, this can be done by rendering the scene once per cascade with different viewports and render target slices, or by using a Geometry Shader (or amplification/mesh shaders in modern pipelines) to clone primitives across cascades dynamically via the SV_RenderTargetArrayIndex system value.
  • Cascade Selection in HLSL: In the main lighting pass, the pixel shader determines which cascade to sample based on the fragment’s view-space depth. Once the correct cascade index is determined, the world position is transformed into light space using that cascade's light view-projection matrix.

Filtering and Seam Blending

Because adjacent cascades have different texel densities, noticeable seams can appear where two cascades meet. DirectX implementations mitigate these artifacts through specific filtering methods:

  • Percentage Closer Filtering (PCF): Hardware-accelerated comparison sampling (SamplerComparisonState in HLSL) is combined with multi-tap PCF to soften shadow edges and mask discretization artifacts.
  • Cascade Blending: Near the boundary between two cascades, the pixel shader samples both the current and the next cascade, performing a linear interpolation between the two shadow factors based on the fragment's distance to the split plane. This eliminates hard transitions as the camera moves through the environment.

Performance Considerations

CSMs dramatically improve visual quality over large viewing distances, but they multiply the geometric workload of the shadow pass by the number of cascades (typically 3 to 4). To maintain high frame rates in DirectX, developers utilize:

  • Frustum Culling per Cascade: Ensuring objects are only submitted for draw calls if they intersect the specific bounding volume of that cascade.
  • Static Shadow Caching: Separating non-moving geometry in distant cascades into static caches that are not regenerated every frame.
  • Conservative Cascade Fitting: Stabilizing the orthographic projection to snap in texel-sized increments, preventing shadow shimmering (swimming edges) as the camera translates.