Clustered Shading
Clustered Shading is a technique that bridges the gap between Forward and Deferred rendering. It allows for thousands of light sources while maintaining the material flexibility of Forward rendering and the transparency support that Deferred rendering often lacks.
Conceptual Overview
Section titled “Conceptual Overview”The core idea is to spatially partition the view frustum into a 3D grid of “clusters”.
- Grid Dimensions: Typically 16x9x24 (Width x Height x Depth slices).
- Depth Slicing: Exponential slicing is used to provide higher resolution near the camera.
Implementation Details
Section titled “Implementation Details”The implementation follows a Hybrid Compute-Graphics pipeline.
graph TD
Start([Frame Start]) --> Collect[Collect & Upload Lights]
subgraph "Per-Camera Execution"
Collect --> Build["Build Cluster Grid<br/>(Compute Shader)"]
Build --> Cull["Cull Lights<br/>(Compute Shader)"]
Cull --> DrawOpaque[Draw Opaque Geometry]
DrawOpaque --> DrawTrans[Draw Transparent Geometry]
end
DrawTrans --> End([End Camera])
1. Cluster Construction (Compute)
Section titled “1. Cluster Construction (Compute)”At the start of the frame, a compute shader calculates the AABB (Axis-Aligned Bounding Box) for every cluster in the grid based on the camera’s view projection.
2. Light Culling (Compute)
Section titled “2. Light Culling (Compute)”A second compute pass intersects every light source (including Reflection Probes and Light Probes) with every cluster.
- Input: Global list of lights and probes.
- Output: A concise list of light indices per cluster.
- Data Structure:
LightIndexList: A single large buffer containing contiguous lists of light IDs.LightGrid: A 3D texture (or buffer) where each cell contains{offset, count}pointing intoLightIndexList.
3. Forward Lighting (Pixel Shader)
Section titled “3. Forward Lighting (Pixel Shader)”During the geometry pass, the pixel shader:
- Calculates the screen-space position and linear depth of the fragment.
- Determines which cluster index
(i, j, k)the fragment belongs to. - Fetches
offsetandcountfrom theLightGrid. - Loops through the lights in
LightIndexListfor that range.
Advantages
Section titled “Advantages”- O(1) Light Lookup: no need to loop through all lights or use complex branching.
- Transparency: Since it’s a forward pass, transparent objects handle multiple lights correctly.
- MSAA: Fully compatible with hardware MSAA.