Builtin Library
README.md
lighting
Scene-lighting base capability: ambient + directional ("sun") light and procedural-sky setup with modify-or-spawn, read-merge-write semantics, plus clear color, and the per-frame reads of the resolved lights. Identity is the component, never the entity name: the sun is the Light the renderer's snapshot names as the directional holder, the ambient is the light-role component of kind "ambient", and the sky is the entity carrying a sky-role component. Name-based lookup, word resolution, and sky-material orchestration (presets, material swap) live in the lighting toolbox.
sun and ambient configuration patch the scene's resolved sun / ambient light components, spawning a carrying entity when the scene has none. A partial update (e.g. only intensity) reads the component's current fields first and merges the given fields on top, so unspecified fields keep their authored values instead of resetting to a default. sky writes the sky entity's ProceduralSky component the same way — any of its fields, plus enabled = false to remove the sky component.
Types
SunOpts—{ direction?, color?, intensity?, castsShadows? }.AmbientOpts—{ color?, intensity? }.ProceduralSkyOpts— ProceduralSky component fields, plusenabled = falseto remove the sky.SetupOpts—{ sun?, ambient?, sky?, clearColor? }.SetupResult—{ sun?, ambient?, sky? }, the entity ids each provided section resolved to.Sun—{ direction, color, intensity, castsShadows, entityId? }.Ambient—{ color, intensity, entityId? }.LightRow— one punctual light as the renderer resolved it.
Exports
Writes — each takes the opts above and answers with the entity the light resolved to:
M.setSun(opts: SunOpts) -> string— set the scene's sun, returning its entity id.M.setAmbient(opts: AmbientOpts) -> string— set the scene's ambient term, returning its entity id.M.applySetup(opts: SetupOpts) -> SetupResult— apply a lighting setup in one call. All fields optional — only provided fields change.clearColoris{r, g, b}.M.setProbeVolume(key: string, volume)/M.removeProbeVolume(key: string)— publish or retract a baked irradiance probe volume.
Reads — each takes no arguments, and answers from the resolved lighting state at a cost independent of scene size:
M.sun() -> Sun— the sun the frame is shaded by.M.ambient() -> Ambient— the ambient term the frame is shaded by.M.lightRows() -> { LightRow }— every punctual light the renderer resolved this frame.
Identity:
M.lightKind(componentType: string, component: any?) -> string?— the kind a light-role component names.M.lightOfKind(entityId: string, kind: string) -> any— the light-role component of that kind on one entity.
Usage
local lighting = require("@builtin::modules.api.engine.lighting")
lighting.setSun({ direction = { 0.3, -1, 0.2 }, intensity = 2.0 })
lighting.setAmbient({ intensity = 0.3 })
lighting.applySetup({
sun = { direction = { 0.3, -1, 0.2 }, intensity = 2.0 },
ambient = { intensity = 0.3 },
sky = { timeOfDay = 14 },
})
local sun = lighting.sun()
print(sun.intensity, sun.entityId)
A reader takes no arguments and a setter takes the opts table, so lighting.sun(opts) is refused with the name of the call that applies it.