Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

rt_ao

Ray-traced ambient occlusion: the settings the rt_ao render feature traces on, and the lifetime of the pass that draws it.

local rtAo = require("@builtin::modules.rt_ao")

renderer.setRaytrace(true)          -- the acceleration structure the rays walk
rtAo.set({ quality = "medium" })    -- starts the pass

rtAo.get()                          -- the settings in force
rtAo.qualityLevels()                -- rays per pixel and grid resolution per level
rtAo.stats()                        -- the grid the running pass actually built
rtAo.active()                       -- is the pass running
rtAo.clear()                        -- off, settings kept

What it costs

The rays a frame traces is rays × grid pixels, and the trace pass measures linear in that product and flat in the scene's entity count. A quality level picks both numbers:

qualityrays per pixelgrid resolutionrays per 1920×1080 frame
low3half1.6 M
medium6half3.1 M
high6full12.4 M
ultra12full24.9 M

medium is the default. high is the same estimate per texel on the frame's own grid, at four times the rays.

Occlusion is low-frequency almost everywhere, so a half-resolution grid holds the shading: a depth-aware upsample carries it back to the frame weighted by the depth of the surface each texel describes, so silhouettes survive it. What a half-resolution grid loses is the innermost pixel of a sharp crease.

The other knobs

fieldeffect
radiusWorld-space occlusion reach — how long a ray is, so how big a crease has to be to darken. Also sizes the distance the filter behind the trace stops smoothing over, so changing it rebuilds the pass.
strengthHow far the darkening goes where the hemisphere is fully closed, in [0, 1]. 0 turns occlusion off and releases the pass.

What runs

One compute pass traces the hemisphere into the grid; where the grid is coarser than the frame, a depth-aware upsample lifts it; the shared denoising filter carries the estimate across frames and smooths it across this one; a last pass multiplies the result into the scene colour, and a blit puts it on screen.

rtAo.stats().dispatches counts them, and rtAo.stats().traceTarget is the occlusion term on its own, for a readback.

Needs the deferred path for @scene.normal (the default), and renderer.setRaytrace(true) for the structure the rays walk. Runs on the hardware ray-query backend and the software one alike.