Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdf78e4f826

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.

fieldeffect
shutterAngleHow long the shutter is open, in degrees of a full rotation. 180 is the film convention. 360 never closes. 0 is off.
samplesTaps per pixel. More resolves a long smear more smoothly.
maxRadiusLongest blur allowed, in pixels, whatever the shutter says. Bounded at 32.
depthScaleHow 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.