Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

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

FieldDefaultPurpose
sizeX/Y/Z(10, 4, 10)World-space size of the volume.
resX/Y/Z(8, 4, 8)Probe grid resolution along each axis.
samples64Sphere samples per probe (Hammersley sequence).
bounces3Surface interactions each sample path follows.
intensity1.0Multiplier on the stored radiance at sample time.
rayMax100.0World-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 fieldDefaultPurpose
fieldId""Stable publish/persist key, minted on first bake.
lightmapDatanilBaked-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.