MIT License NuGet

Home / Features / Post-processing

Post-processing and compute effects

Bloom, TAA, GTAO, the sky LUTs and the debug views are not hard-wired stages. They are compute effects registered against a frame phase, and the twenty-line contract that carries them is the same one your own effect implements.

What ships in the box

Effects live in Rendering/Effects/. Each one registers into a compute phase, declares the textures it produces, and can be inspected as a 2D sprite by name — which is how the reference application's debug mode works.

TypePhasePurpose
BloomEffectAfterSceneDownsample / upsample chain over HDR scene colour.
GtaoEffectAfterSceneAmbient occlusion for indirect diffuse.
TaaEffectAfterSceneJittered temporal resolve with variance clipping and sharpening.
DdgiEffectAfterSceneProbe tracing and irradiance atlas update.
SkyAtmosphereEffectFrameStartScattering LUTs, cloud noise and the aerial volume.
SceneColorCopyEffectAfterSceneA readable snapshot of scene colour for effects that need it.
DepthViewEffectAfterSceneLinearised depth as an inspectable texture.
VelocityViewEffectAfterSceneMotion vectors, visualised.
Sdf3DViewEffectFrameStartSlice through a signed distance field of the kind DDGI traces.
PlasmaEffectFrameStartA minimal compute example — the one to copy when writing your own.

Any of them can be put on screen with three lines, because effect outputs are addressable textures:

AddControl(new Sprite2D
{
    Name = Season.Rendering.Effects.GtaoEffect.TextureName,
    Color = Colors.White,
    PosX = 20, PosY = 580, Width = 240
});

Names follow one scheme: compute:// for 2D textures and compute3d:// for volumes. GTAO publishes compute://gtao/ao, the sky publishes compute://sky/skyview and compute3d://sky/aerial, and the plasma sample publishes compute://plasma. Nothing about consuming them is special — a Sprite2D or a material override takes the name and that is the whole interface.

The effect contract

ComputeEffect is an abstract class with five members. That is the entire extension surface.

public abstract class ComputeEffect
{
    public abstract string Name { get; }
    public abstract ComputePhase Phase { get; }

    // Create textures and pipelines. Return false and the effect is
    // dropped with nothing left behind.
    public abstract bool Initialize(IGraphics g);

    // Dispatch. Called once per frame, in phase order.
    public abstract void Record(IGraphics g);

    // Swapchain changed size. Recreate anything resolution-dependent.
    public virtual void OnResize(IGraphics g) { }
}
Contract

Initialize returning false must leave no residue — no half-created textures, no dangling names in FrameSchedule. That is what makes an effect genuinely optional: a backend without compute support and a user who switched the effect off produce the same, correct frame.

Writing a compute effect walks through PlasmaEffect line by line.

Bloom

A threshold-and-knee soft clip followed by a six-level downsample and upsample chain over HDR scene colour. Because scene colour is genuinely HDR, the threshold means something: it selects pixels brighter than white rather than pixels that happened to clip.

SettingDefaultMeaning
BloomEnabledonOff skips the chain and clears FrameSchedule.BloomTexture.
BloomThreshold1.0Radiance above which a pixel contributes.
BloomKnee0.5Softness of the threshold, so the bloom fades in rather than switching on.
BloomIntensity0.3How much of the chain is added back.
BloomMipCount6Chain depth. More levels means a wider, softer glow.

Anti-aliasing: four tiers, honestly labelled

AaMode has four values and they are not four qualities of the same thing — they operate in different colour spaces at different points in the frame.

ModeWhere it runsNotes
OffNo filtering.
Msaa4xRasterLegacy tier, D3D12 only. HDR resolve quality is compromised and bandwidth cost is high; it stays as a VR fallback.
FxaaPost-tonemap LDRFXAA 3.11, applied in the Post composite and at FinalBlit. Cheap and universal.
TaaHDR, before tonemapDefault. Needs velocity and compute; selecting it forces MotionVectors on at initialization. Falls back to Fxaa where unavailable.

TAA is implemented and stabilised on D3D12, Vulkan, Metal and WebGPU. The fallback to FXAA is automatic rather than an error, which means a scene requesting TAA still renders on a device that cannot deliver it — softer, but rendered.

TAA in detail

The camera jitters the projection matrix by a sub-pixel offset each frame, the resolve reprojects the previous result through motion vectors, and variance clipping decides how much of the history to trust. The interesting part is that both the jitter and the history live on Camera3D, where you can read them.

SettingDefaultMeaning
MotionVectorsonWhether the Scene pass writes velocity. TAA forces it.
JitterPhaseCount7Length of the jitter sequence before it repeats.
JitterScale1.0Jitter amplitude in pixels. Above 1 trades stability for coverage.
TaaFeedback0.9History weight for moving pixels.
TaaStaticFeedback0.97History weight where nothing moved — more history, more resolve.
TaaVarianceClipGamma1.0How tightly history is clamped to the neighbourhood. Lower is more ghost-resistant and more aliased.
TaaSharpness0.5Post-resolve sharpening, because temporal accumulation softens.
On Camera3DWhat it is for
ProjectionJitteredThe projection actually used to render, jitter included.
PrevViewProjectionLast frame's matrix, which is what makes reprojection possible.
JitterNdc, JitterPixelsThis frame's offset, in both spaces.
UpdateTemporal, ResetTemporalAdvance the sequence, or discard history after a camera cut.
Call ResetTemporal after a teleport

Reprojecting across a discontinuous camera move smears the old frame across the new one for as long as the feedback weight takes to decay. Cutting the camera is exactly the case motion vectors cannot describe.

Known gaps

  • Partial GTAO is a lite variant. Half-resolution horizon-based AO with depth-reconstructed normals, interleaved-gradient noise and a depth-aware blur. It is not full ground-truth AO, and the name is inherited from the technique family rather than claiming the reference implementation.
  • Absent Depth of field, motion blur, chromatic aberration, colour grading LUTs. The post chain is tonemap, bloom and AA. Anything else is an effect you would write.
  • Absent Upscalers. No FSR, DLSS or temporal upscaling. TAA resolves at native resolution.