Builtin Library
README.md
LensFx
The lens the scene is photographed through, and the film behind it. Add it to an entity and bright sources throw flare, the grime on the front element varies it, and the image carries grain.
local id = entity.spawn("lens").id
entity(id).component.add("LensFx", {
flareIntensity = 1.0,
grainIntensity = 0.03,
dirtIntensity = 0.5,
})
Every field is live — editing one in the inspector changes the look on the next
frame, and the values persist with the scene. Setting flareIntensity and
grainIntensity both to 0 releases the passes while keeping the rest authored;
removing the last one in the scene clears it.
| field | effect |
|---|---|
threshold | Luminance a pixel must reach to throw a flare, with a soft knee below it. |
flareIntensity | Brightness of the whole flare. 0 is off. |
ghostCount / ghostSpacing | How many internal reflections are drawn, and their spacing along the optical axis. |
haloWidth / haloIntensity | Radius and brightness of the halo ring. |
streakIntensity / streakLength | The anamorphic streak along one axis. |
chromaShift | Channel separation inside a ghost. |
grainIntensity / grainSize | Depth of the grain, and the size of one grain in pixels. |
grainResponse | Shape of the response to luminance. Higher narrows it toward the midtones. |
dirtIntensity / dirtScale | How much grime varies the flare, and how fine the smudges are. |
The component ticks the clock the grain is drawn against, in both edit and play, so the grain is a fresh field every frame rather than a fixed screen pattern.
One lens photographs the whole scene, so one of these per scene is enough — the last one to push wins.
The work runs in lensOptics.renderFeature; the settings live in
@builtin::systems.lensFx.lensFx, which is also how to drive them from a script.