Skip to content

feat(engine): implement motion blur via temporal supersampling#61

Merged
LeadcodeDev merged 1 commit into
mainfrom
feat/motion-blur
Jul 19, 2026
Merged

feat(engine): implement motion blur via temporal supersampling#61
LeadcodeDev merged 1 commit into
mainfrom
feat/motion-blur

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #49.

Goal: the motion_blur schema effect was a phantom (parsed in the animator, then discarded). Implemented deterministically, plus a trail effect.

  • Ghost nodes at the builder level (no full-pipeline resampling): build_child re-resolves the CSS at offset times — t − i·(shutter/fps)/samples for motion blur, t − i·spacing for trail — and emits ghost BoxNodes painted beneath the principal. New BoxKind::Ghost paints like a component but never records hits.
  • Opacity formula proven by test: ghosts at 1/(samples+1), principal at full opacity — a static component stays visually identical (the all-attenuated alternative converges to ~0.66 brightness and was rejected on evidence). Trail uses falloff^i persistence.
  • Schema additive: samples (default 6, clamped 1–16) + shutter (frame fraction, default 0.5) on MotionBlurConfig; new trail {copies, spacing, falloff} effect; BuildAnimationCtx gains fps.
  • Documented v1 limits: ghost internal animations (text reveal, draw_progress) sample frame time — invisible for displacement blur, the primary use case; container ghosts don't recurse into children.

Tests: 4 new pixel tests (broadened span + intermediate intensities mid-motion, trail band count with decaying intensity, static invariance, samples=1 degeneracy). 307 total, all green.

Verify: cargo test --workspace → 307 passed ✓ · cargo fmt --check ✓ · clippy 0 warnings ✓

MotionBlurConfig was parsed and discarded since its introduction. Both
effects now materialize as ghost BoxNodes built by build_child: css
re-resolved at offset times (shutter window for motion_blur, spacing
steps for trail), painted beneath the principal via the new
BoxKind::Ghost (excluded from the hit-map). Opacity formula proven by
the static test: ghosts at 1/(samples+1), principal at full — the
all-attenuated alternative washes static components to ~0.66.
BuildAnimationCtx gains fps (shutter is a frame fraction). Documented
v1 limits: ghost internal animations sample frame time; container
ghosts don't recurse into children.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(engine): implement motion blur via temporal supersampling

1 participant