ReadonlynameHuman-readable identifier used in graph node labels and error messages.
StaticcreateUpload per-frame camera matrices used for view-space reconstruction from ctx.activeCamera.
Switch between box blur (performance) and bilateral Gaussian (quality).
Update the SSAO tuning parameters in the GPU uniform buffer.
Insert the pass into graph for one frame. Implementations call
graph.addPass(name, type, b => { ... }) exactly once and use the
supplied PassBuilder to declare reads, writes, transient
resources, and the execute callback.
Graph being built this frame.
Pass-specific dependency record (handles, scene data, etc.).
Pass-specific output record (typically a set of handles downstream passes will consume).
Release every long-lived GPU resource owned by the pass (pipelines, persistent uniform buffers, samplers, BGLs). Called by the factory or application during teardown. Default implementation is a no-op.
Screen-space ambient occlusion pass (render-graph version).
Algorithm: classic Crytek-style view-space hemisphere SSAO. Not HBAO or GTAO — no horizon traversal, no analytical integral, no temporal accumulation. Just the standard four-step pipeline:
Per-frame setup (built once in
create(), uploaded as uniforms):z >= 0), scaled by0.1 + 0.9 * (i/N)²so samples cluster near the origin. SeegenerateKernel.(cos θ, sin θ, 0, 1)) used to break up the banding from a fixed kernel. SeegenerateNoise.AO pass at half resolution (
ssao.wgsl,fs_ssao):inv_proj; transform the GBuffer world-space normal into view space.ref_z > sample_vs.z + bias(the real surface is closer to the camera than the kernel sample — i.e. the sample is inside geometry). Comparing against the sample's Z rather than the pixel's Z makes the bias slope-invariant on flat surfaces.1 - smoothstep(0, radius, |ΔZ|)so hits on geometry far from the surface don't haunt the result.clamp(1 - (occlusion/N) * strength, 0, 1)to a half-resr8unormtarget.Blur (
ssao_blur.wgsl):'quality'(default): two-pass separable bilateral Gaussian (7-tap, weights0.196, 0.175, 0.122, 0.067), with a depth-aware termexp(-|Δdepth| * 1000)that zeroes contributions across depth discontinuities (no AO bleeding across silhouettes).'performance': single-pass 4×4 unweighted box average.Output: half-res
r8unormAO factor, consumed by the deferred lighting pass (ambient term) and by composite (fog blending).Both intermediate (raw) and final (blurred) AO targets are transient per-frame resources; the persistent uniform buffer and noise texture live on the pass instance.