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.