Builtin Library
README.md
PostProcess Component
Applies a stack of post-process effects to the scene, declaratively, from a
single entity. Each effect references a .shader asset (@domain: post-process)
and carries its own configurable property values — tuned like material
properties, with no shader edit required.
This is the load-time reproducer for post-processing: where an agent's live
postprocess.add(...) + postprocess.setProperty(...) calls produce effects
that vanish on reload, a PostProcess component re-registers the exact same
stack — with the exact same tuning — every time the scene loads. The persist
freeze converts live execute-origin effects into .shader assets + one entity
carrying this component, so what you see is what you get across save/reload.
Properties
| Field | Type | Description |
|---|---|---|
effects | array | The effect stack. Each entry: { shader, priority?, enabled?, layer?, values?, textures? }. |
shape | "global" | "box" | "sphere" | Where the stack applies. Default "global" (unbounded). |
extents | vec3 | Box region half-extents, world units. Default {5, 5, 5}. |
radius | number | Sphere region radius, world units. Default 5. |
falloff | number | Soft-edge distance outside the volume the stack fades over. Default 0. |
priority | number | Order of this region against other PostProcess regions, added to each effect's own priority. Default 0. |
display | struct { curve, exposure } | The display transform this region sets while it is live — curve (0 linear, 1 Reinhard, 2 ACES, 3 Khronos PBR Neutral, default 3) and exposure (multiplier on the scene's light before the curve, default 1). Takes effect only when setsDisplay is true and shape is "global". |
setsDisplay | boolean | Whether this region writes display to the chain's __display__ transform while it is live. Default false. |
Each effect entry:
| Key | Type | Description |
|---|---|---|
shader | asset reference | The .shader asset (a @domain: post-process shader) this effect runs. Builtin shaders (@builtin::shaders.post.vignette, …) or scene-authored custom shaders both work. |
priority | number | Chain order within this region — lower runs earlier. Default 100. |
enabled | boolean | Per-effect toggle. Default true. |
layer | "all" | "scene" | Which composited image this effect grades: "scene" is the rendered picture before the UI reaches it, in the scene's own light; "all" is the picture fitted to the screen with every widget on it. Left empty, the entry follows its shader's space — a light shader grades "scene", a display shader grades "all". |
values | table | Named property overrides { [prop] = value }, applied via postprocess.setProperty after the effect is added — the configurable tuning. |
textures | table | Texture bindings { [prop] = path }, applied via postprocess.setTexture after the effect is added. |
The component-level enabled flag (engine-managed, not declared here) toggles the
whole stack: disabling the component removes every effect (and restores the
chain's own display transform if this region set one); enabling it re-registers
them (onEnable / onDisable).
Usage
entity.find("fx").component.add("PostProcess", {
effects = {
{ shader = "@builtin::shaders.post.vignette", priority = 0,
values = { intensity = 0.6 } },
{ shader = "@builtin::shaders.post.grayscale", priority = 10,
values = { intensity = 1.0 } },
},
})
Setting the display transform from a global region:
entity.find("look").component.add("PostProcess", {
setsDisplay = true,
display = { curve = 2, exposure = 1.5 }, -- ACES
})
Two global regions with setsDisplay = true both write __display__ — whichever
registers last wins the frame. The regions setting it share one ordered record of
who is live, so they come off in any order: removing the newer of two leaves the
older one's display standing, removing the older leaves the newer one's, and
removing the last leaves whatever stood before any of them wrote.
The exposure package drives __display__.exposure on its own, from a GPU readback
each tick it meters. A region arriving or leaving sets the exposure and the
package's next readback sets it again, so with auto-exposure running the exposure
a region asks for holds for a frame while its curve holds for as long as the region
does.
Methods
pp:getEffectNames()— the live effect names currently registered, in stack order.pp:setProperty(index, prop, value)— tune a property of one effect at runtime (forwards topostprocess.setProperty), like editing a material property.