Post-processing in Prowl is implemented as plainDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ProwlEngine/Prowl/llms.txt
Use this file to discover all available pages before exploring further.
MonoBehaviour components that live on the same GameObject as a Camera. The DefaultRenderPipeline inspects those components at render time, discovers any that override OnRenderImage, and ping-pongs them through a temporary RenderTexture pair. No special registration step is needed — add the component, configure its properties, and it runs automatically. Four built-in effects ship with the engine: KawaseBloomEffect, MotionBlurEffect, SSAOEffect, and ToneMapperEffect.
How OnRenderImage Works
The rendering pipeline runs image effects in two groups each frame:- Opaque effects — components marked
[ImageEffectOpaque]run before the transparent geometry pass - Final effects — all other
OnRenderImagecomponents run after transparent geometry
src and a temporary buffer as dest. After all effects have run, the final dest is blitted to the camera’s output target.
Effect Attributes
Three attributes control how the pipeline treats anOnRenderImage component:
[ImageEffectOpaque]
Runs the effect between the opaque and transparent passes. Use this for effects that must read depth (SSAO, ambient occlusion), because the depth buffer is fully populated after opaque geometry.
[ImageEffectAllowedInSceneView]
Lets the effect run in the editor Scene View camera. Without this attribute, effects are skipped in the editor viewport.
[ImageEffectTransformsToLDR]
Signals that this effect outputs an LDR (8-bit) buffer. The pipeline switches the working format from
R16_G16_B16_A16_Float to R8_G8_B8_A8_UNorm after this effect runs. Always use this on your tone mapper.KawaseBloomEffect
KawaseBloomEffect implements a multi-pass Kawase blur bloom. It extracts bright pixels above Threshold, performs iterative dual Kawase blur passes, then composites the bloom on top of the source image.
Resolution modes
| Value | Scale | Notes |
|---|---|---|
Full | 1× | Full resolution — best quality, most expensive |
Half | 0.5× | Good balance for HD resolutions |
Quarter | 0.25× | Default — suitable for most games |
Eighth | 0.125× | Cheapest; only usable at very high base resolutions |
How it works internally
MotionBlurEffect
MotionBlurEffect samples the _CameraMotionVectorsTexture to reconstruct per-pixel velocity and accumulates samples along the motion path.
OnPreCull:
MotionBlurEffect requires a Camera component on the same GameObject — it is decorated with [RequireComponent(typeof(Camera))]. Adding the effect to a non-camera object will automatically add a camera as well.SSAOEffect
SSAOEffect (Screen-Space Ambient Occlusion) reads the depth buffer to estimate how much ambient light each pixel receives, darkening corners and crevices. It is marked [ImageEffectOpaque], so it runs before transparent geometry.
SSAOEffect is [ImageEffectOpaque], it runs before transparency and before the tone mapper — important for correct compositing over the opaque scene.
ToneMapperEffect
ToneMapperEffect converts the HDR linear light buffer to a displayable LDR image. It is marked [ImageEffectTransformsToLDR], signalling to the pipeline that the format switches from float16 to R8_G8_B8_A8_UNorm after this effect runs. Always place ToneMapperEffect last in the effect stack, or at minimum after all HDR-aware effects.
Stacking Multiple Effects
Effects execute in the orderGameObject.GetComponents<MonoBehaviour>() returns them, which matches the order they were added to the GameObject. A typical HDR camera stack looks like:
SSAOEffect (opaque)
Runs first, before transparency, because of
[ImageEffectOpaque]. Darkens corners and contact shadows.KawaseBloomEffect (final)
Runs after transparency. Extracts and spreads bright emissive pixels across the HDR buffer.
Writing a Custom Post-Processing Effect
UseGraphics.Blit() to apply a custom material to a fullscreen quad, or create your own CommandBuffer pipeline for more control.
Using Temporary Render Textures
For multi-pass effects that need intermediate buffers, request them from the pool:Quick Reference
Effect attribute summary
Effect attribute summary
| Attribute | Class used on | Effect on pipeline |
|---|---|---|
[ImageEffectOpaque] | SSAOEffect | Runs between opaque and transparent passes |
[ImageEffectTransformsToLDR] | ToneMapperEffect | Pipeline switches working RT format from HDR to LDR |
[ImageEffectAllowedInSceneView] | All four built-in effects | Effect also runs when the Scene View camera renders |
[RequireComponent(typeof(Camera))] | MotionBlurEffect, SSAOEffect, ToneMapperEffect | Automatically adds a Camera component if missing |
DepthTextureMode flags
DepthTextureMode flags
Effects that need auxiliary buffers must request them in
OnPreCull. The flag is cleared at end of frame.| Flag | Exposes | Used by |
|---|---|---|
DepthTextureMode.Depth | _CameraDepthTexture | SSAO, custom depth effects |
DepthTextureMode.MotionVectors | _CameraMotionVectorsTexture | Motion blur, TAA |