Note that this is being replaced in the future for a PostProcess Component which is much easier to manage, much like Ambient Occlusion, if you want to directly do generic traces in your shader, refer to Screen Space Tracing

Dynamic reflections are implemented as Screen Space Reflections in a three passes.

This document focuses mostly on what needs to be done to implement the first pass, which generates the reflection G-buffer.

The input is based on the material API structure, tailored specifically for Physically Based Rendering (PBR) materials.

Reflection Pipeline

The reflection pipeline follows these stages:

  1. Reflections() MODE - Captures pixel intersection data and populates the reflection G-buffer.
  2. Denoise - Makes it pretty to be composited through reprojection and temporal gathering.
  3. Composite - Integrates the reflection during the main forward pass.

This implementation includes legacy aspects from a time when our control over the rendering pipeline via C# was limited, so it taps into some internal rendering functions. Note that this means the API for this could change, existing compiled shaders should remain unaffected if that happens.

Usage

Dynamic reflections can be added to a shader in two ways:

  1. Inline within the same shader: Add Reflections(S_MODE_REFLECTIONS) within MODES, add a combo for that in the main shader.

  2. As a separate shader: Add Reflections("foo_reflections.shader") within MODES, create a new shader that just does reflection.

    \

  3. You can choose to make it toggleable per material with an explicit F_DYNAMIC_REFLECTIONS and S_MODE_REFLECTIONS combos

Inline Shader Example

For inline usage, define your entry point signature as follows:

FinalOutput MainPs(PixelInput i) Target
{
    Material m = Foo();
    #if S_MODE_REFLECTIONS
        return Reflections::From(i, m);
    #else
        return ShadingModel::From(i, m);
    #endif
}

Note: This approach doubles shader combos.

Separate Shader Example

When using a separate shader, there is no need to vary the entry point signature. Simply pass ReflectionOutput and the desired target to composite the material, similar to your main shader:

ReflectionOutput MainPs(PixelInput i)
{
    Material m = Foo();
    return Reflections::From(i, m, SampleCountIntersection);
}





Created 16 Aug 2024
Updated 9 Dec 2024