Skip to content

Deferred Pipeline

This pipeline uses a technique commonly known as deferred shading. In a nutshell, a geometry pass outputs geometry data per pixel and then lighting is computed by separate shaders.

This decouples the material complexity from the lighting evaluation complexity, improving compilation time and performance.

Here is an overview of the deferred pipeline logic.

%%{ init: { 'flowchart': { 'curve': 'basis' } } }%%
flowchart TD
    subgraph Deferred Layer
        A[Depth Prepass] --> B[Material]
        B --> C[Direct Light]
        B --> D[Indirect Light]
        C & D --> E[SubSurface Scatter]
        E --> F[Combine]
    end

Deferred Layers

Screen space transmission rays need access to the radiance of objects behind them. Materials tagged to use raytrace transmission will be put in a separate deferred layer.

Layers are rendered one after another and the whole deferred pipeline is run for each of them. The content of a layer can only affect itself and the content of subsequent layers.

It is also possible that we add support for colored transparency for deferred material using this layering in the future (example use case would be ocean, windows).

Polymorphic GBuffer

We use a polymorphic gbuffer whose layout can vary per pixel. The most common data are written through framebuffer attachement (fast) and write the remaining ones through arbitrary writes (slow).

The goal of this approach is to allow to vary the amount of data written per pixel and reduce the bandwidth usage for pixels that have simple material.

Here is a breakdown of the layout.

Header Normal Data Closure Data
Format R16_UINT RG16_UNORM RGB10_A2_UNORM
Framebuffer Output Header Normal x 1 Closure Data x 2
Optional Image Output N/A Normal x 2 + Additional data Closure Data x N

Note that the use of arbitrary writes forces us to use early depth testing.

Pixel Classification