Builtin Library
README.md
MotionBlur
The camera's shutter, as a component. Add it to an entity and everything in frame is sampled over an interval rather than at an instant, so what moved during that interval is drawn as the path it took.
local id = entity.spawn("motion_blur").id
entity(id).component.add("MotionBlur", {
shutterAngle = 180,
samples = 16,
})
Every field is live — editing one in the inspector changes the blur on the next
frame, and the values persist with the scene. Setting shutterAngle to 0 closes
the shutter while keeping the rest authored; removing the last one in the scene
clears it.
| field | effect |
|---|---|
shutterAngle | How long the shutter is open, in degrees of a full rotation. 180 is the film convention. 360 never closes. 0 is off. |
samples | Taps per pixel. More resolves a long smear more smoothly. |
maxRadius | Longest blur allowed, in pixels, whatever the shutter says. Bounded at 32. |
depthScale | How far apart, in world units, two surfaces must be before the filter separates them into foreground and background. |
Shutter angle is the physical control: motion vectors span one frame, so a shutter open for half a frame smears half the per-frame travel. At a fixed shutter angle, doubling the frame rate halves the blur on its own.
One shutter drives the whole camera, so one of these per scene is enough — the last one to push wins.
The work runs in shutterBlur.renderFeature; the settings live in
@builtin::systems.motionBlur.motionBlur, which is also how to drive them from
a script.