Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

decals

Registry of oriented box decal projectors. Each entry is an entity whose Transform is an oriented projection box plus the material the projector stamps. The @builtin::renderFeatures.decals render feature reads this registry every frame, groups the projectors by the material they share and packs them eight to a pass. Each pass reconstructs a covered pixel's world position from scene depth, transforms it into each projector's box space, and shades it from the material — projecting a textured material's texture (or a flat-colour material's colour) onto every surface inside the box, fading on faces turned away from the projection axis so the decal wraps the surfaces facing the projector.

A pass is enqueued per channel the material provides: base colour when the material binds a base_color_texture or states a base_color its shader does not declare, while that colour's alpha covers something; emissive when it binds an emissive_texture or states a non-black emissive. A material that provides neither stamps nothing and says so in the log.

The @builtin::components.DecalProjector component is the authoring front end; it calls into this registry. Use the module directly for code-driven projectors. A projector's entry lasts as long as its entity: when the entity is despawned, whatever despawned it, its id leaves the registry.

Surface

FunctionMeaning
set(e, opts)Register entity e (ref or id) as a projector. opts = { material, opacity? }. Re-calling updates it.
clear(e)Stop projecting from e.
clearAll()Remove every projector.
has(e)Whether e is a registered projector.
entries()The live { [id] = { material, opacity } } registry (read by the feature).

Example

local decals = require("@builtin::modules.decals")

local p = entity.spawn("splat")
p.localPosition = { 0, 3, 0 }
p.localScale = { 5, 5, 4 }
p.localRotation = { 0.70710678, 0, 0, 0.70710678 } -- project down

decals.set(p.id, { material = "@builtin::materials.decal_default", opacity = 1.0 })