Builtin Library
README.md
VolumeProbe
Defines a 3D grid of irradiance probes covering a region of world space. The baked field publishes into the renderer's irradiance-volume set: every standard-PBR fragment inside the bounds (movers, avatars, freshly spawned props) samples it — no per-entity setup.
The entity's world position is the volume centre; sizeX/Y/Z are the
extents along each axis; resX/Y/Z controls how many probes are packed
into the volume along each axis.
Fields
| Field | Default | Purpose |
|---|---|---|
sizeX/Y/Z | (10, 4, 10) | World-space size of the volume. |
resX/Y/Z | (8, 4, 8) | Probe grid resolution along each axis. |
samples | 64 | Sphere samples per probe (Hammersley sequence). |
bounces | 3 | Surface interactions each sample path follows. |
intensity | 1.0 | Multiplier on the stored radiance at sample time. |
rayMax | 100.0 | World-space max distance for sample rays. |
skyR/G/B | (0, 0, 0) | Sky radiance seen by rays that escape geometry. |
Bake bookkeeping lives in private fields, reachable through the reflection
triad (:fields() / :getField(name) / :setField(name, value)):
| Private field | Default | Purpose |
|---|---|---|
fieldId | "" | Stable publish/persist key, minted on first bake. |
lightmapData | nil | Baked-lighting container holding this volume's field entry. |
A 12×4×12 volume = 576 probes. Each probe stores 9 vec4 (36 floats) of
SH L2 coefficients = ~81 KB per volume. Bake time on the GPU scales
roughly linearly with probeCount * samples * log(triangleCount).
Persistence
A bake writes the SH field into the scene's baked-lighting container
(lightmapData asset) keyed by fieldId and points the lightmapData
ref at it. On a fresh boot, awake restores the SH buffer and republishes
the field from the container — no re-bake. baking.clear retires the
field (retract + buffer + container entry).
Usage
local VolumeProbe = require("@builtin::systems.globalIllumination.volumeProbe")
local probe = entity.spawn("level_probes")
probe.localPosition = { 0, 0, 0 }
probe.component.add("VolumeProbe", {
sizeX = 30, sizeY = 6, sizeZ = 30,
resX = 12, resY = 4, resZ = 12,
samples = 128,
})
VolumeProbe.bake(probe.id)
Re-bake whenever scene geometry or lighting changes. bakeAll()
processes every volume in the scene using a shared BVH so the
amortised cost stays low.