Post-Processing (Volume)
Awaken's render settings are an add/remove stack of optional effects - modelled on Unity's post-process Volume - where an effect that isn't in the stack simply isn't applied, so nothing leaks in behind your back.
Absent means off
In Unity's URP Volume you add a Color Adjustments or Bloom override; anything you don't add stays at the engine default. Awaken takes the same approach (RenderEffects in packages/render/src/render.ts): each effect is an optional field, and an absent effect is not applied at all - it packs neutral values, never a hidden default.
This exists for a concrete reason. Awaken used to have built-in fog and bloom always on, which meant an un-graded Unity import arrived over-exposed and fogged. With the stack, an imported scene that never set fog gets no fog effect. A blank scene starts with just Sky and Ambient present - a clean, un-graded look.
Effects are added and removed from the Render Settings panel via a + Add effect menu; each shows as a card you can tune or remove.
The effects
| Effect | Key | Applied in | What it does |
|---|---|---|---|
| Sky | sky | mesh/sky pass | Zenith / horizon / ground gradient, or a cubemap. Also carries the sky's bodies: stars, a sun and a moon with a phase terminator. Absent → neutral built-in sky |
| Ambient | ambient | mesh pass | Indirect fill: an intensity plus an equator colour, and optionally sky and ground colours blended by the surface normal (Unity's Gradient ambient). All three equal gives a flat fill. Absent → lit by direct light only |
| Fog | fog | mesh pass | Distance fog toward the fog effect's own colour, which is Unity's behaviour (linear start→end, or exp density). Absent → no fog |
| Color Adjustments | colorGrade | composite | Post-exposure (EV), contrast, saturation, hue shift, colour filter |
| Lift / Gamma / Gain | liftGammaGain | composite | Shadows / mids / highlights wheels (offset, inverse-gamma, gain) |
| Shadows / Midtones / Highlights | shadowMidHigh | composite | Tint by luminance region with smoothstep limits |
| Bloom | bloom | bright-pass + composite | Bright-pass at threshold, intensity add, scatter spread. Two modes (BloomEffect.mode): gaussian (default), a bright pass and one 5 x 5 blur at half resolution; and mipChain (Mip chain (wide)), a 13-tap Karis-weighted prefilter, a 13-tap downsample per level and a tent upsample back up (Jimenez 2014), 2 to 7 levels by frame size, with the intensity shared over the levels. With a 4 x 4 px light at 20.0 on a black 256 x 256 frame, the pixel 40 px away reads 0 of 255 with the gaussian and 17 with the mip chain (scripts/post-options-frame.ts) |
| Vignette | vignette | composite | Darken toward the edges (colour, intensity, smoothness) |
| SSAO | ssao | SSAO chain | Screen-space ambient occlusion (intensity, radius) |
Freshly-added effects use neutral defaults (they do nothing visible until you tune them), so adding a card never jolts the image.
Two base settings are not add/remove cards; they sit in Render Settings → Image:
- Tonemap (
tonemap):linear(a hard clamp),aces(the Narkowicz fit, then 1/2.2 gamma) oracesHill(Stephen Hill's RRT + ODT fit, then the piecewise sRGB curve: 0.18 grey lands at 91 of 255 against ACES's 140). It is the one tonemap in the frame, applied in the post composite to the linearrgba16floatscene. See PBR & Lighting. - Dither (
dither, off by default): adds up to one 8-bit code value of noise after the tonemap, re-rolled every frame, so dark gradients show fine grain instead of bands.
Sky, Ambient, and Fog are lit in the mesh pass
Sky, Ambient, and Fog aren't post effects - they feed the lighting directly. Sky colours and the sky's bodies travel on the camera uniform and drive the background sky pass; Ambient (its three bands) and Fog (density and colour) travel on the Lights uniform, and the fog blend happens per fragment during shading. That is why they take effect during opaque shading rather than in the composite.
How the grade is packed and applied
The five grade-affecting effects (Color Adjustments, Lift/Gamma/Gain, Shadows/Midtones/Highlights, Bloom intensity, Vignette) are packed by packGrade() (packages/render/src/grade.ts) into a single 44-float (GRADE_FLOATS) uniform - 11 vec4s. Absent effects pack neutral values, so an empty stack yields a pure pass-through (neutralGrade()).
That uniform is consumed once, in the composite pass (POST_WGSL), which runs after the scene is drawn and bloom is computed. The order inside the composite mirrors URP:
- Add bloom (
scene + bloom · intensity) - Post-exposure (
2^EV) × colour filter - Contrast about mid-grey
- Hue shift (rotation about the achromatic axis)
- Saturation (toward luma)
- Lift / gamma / gain
- Shadows / midtones / highlights by luma region
- Vignette toward its colour
- Clamp and write the swapchain
So the entire colour grade is a single fullscreen pass reading one 44-float uniform - cheap and fully deterministic.
The SSAO chain
SSAO is opt-in (add the Ambient Occlusion (SSAO) effect). When present, before the main pass the renderer runs a three-stage chain (all in packages/render/src/shader.ts):
- A prepass writes each opaque fragment's world position and true geometric normal.
- The AO pass (a fullscreen fragment pass, not a compute kernel) takes 16 hemisphere samples per pixel around the surface normal, comparing projected sample depths against the scene to estimate occlusion within
radiusmetres, with a depthbiasto avoid self-occlusion acne. - A blur denoises the randomized result.
- The mesh shader then multiplies ambient only by
visibility^intensity(Godot-style). Because visibility is in[0, 1], the exponent only shapes contrast - it can deepen contact shadows but can never drive ambient to pure black.intensityacts like Godot'sssao_power;radiusis scene-scale dependent (default0.6 m).
SSAO is gated by a camera flag (skyZenith.w), so when the effect is absent the mesh shader doesn't sample the AO texture at all - it is a true no-op, not a full-white multiply. It never affects direct/sun lighting (which keeps its own shadows).
Imported render settings
The Godot and Unreal loaders produce a flat render bag; effectsFromFlat() converts it into the stack, adding only the effects the source actually set. A project with fog off (density 0) gets no Fog effect rather than a default one - the whole point of "absent means off." See Import.

Try it
File ▾ → Render Settings…, scroll to Scene effects, and pick Vignette from + Add effect…. Drag its Intensity up and the corners darken as you go.
See also
- Render Settings - the panel that adds, removes, and tunes effects
- PBR & Lighting - sky, ambient, fog, and the tonemap mode in the lighting model
- Camera - the uniform that carries sky colours and the SSAO/tonemap flags
- Import Overview - how importer render bags become the effect stack
- Render Pipeline Overview - where the SSAO chain and composite sit in the frame