Skip to content

Compositing, layers, and effects

Rune Engine treats compositing as snapshot metadata. The submitted root and ordinary child snapshots can isolate opacity or blur as one flattened image. A child boundary can additionally flatten into a projected 3D plane before it is drawn back into the parent.

Mental model

text
CMD_DRAW_CHILD boundary
root snapshot -> optional root opacity / root blur
child CMD_DRAW_CHILD boundary
  -> inspect child snapshot metadata
  -> choose direct replay, opacity layer, blur capture, or 3D capture
  -> draw one composed result in painter order

Responsibilities and boundaries

  • Commands decide where child content appears in painter order.
  • Snapshot metadata decides whether that child is direct, opacity-isolated, motion-blurred, or projected as Layer 3D.
  • Root metadata can isolate the complete submitted scene with group opacity or capture it for the same analytical 2D motion-blur treatment.
  • Ancestor transforms and clips stay outside the captured subtree and apply to the final composed result.

Stable current behavior

Group opacity is a boundary property

group_opacity is applied once at the child boundary, not redistributed to every descendant. Without blur, opacity below one wraps direct replay in a D2D layer. With blur or 3D capture, opacity surrounds the final DrawImage result. The submitted root follows the same one-time opacity rule around the complete root result.

Motion blur samples history analytically

For ordinary layers and the submitted root, replay resolves the same snapshot twice:

  • once at the current frame time
  • once at t - exposure

The difference between those resolved presentations produces one blur vector. Because the same snapshot is sampled analytically, blur works with retargeted animations, expression outputs, and path followers without preserving per-frame simulation state.

Layer 3D is flatten-then-project

An active 3D layer:

  1. captures its subtree into a command list,
  2. projects that flattened image with CLSID_D2D13DTransform,
  3. optionally applies post-projection directional blur, and
  4. draws the final image once in painter order.

There is no depth buffer or Z sorting. Layer 3D is still one painter-ordered image at the child boundary.

Whole-frame rendering stays explicit

On every non-skipped frame, the current backend clears the whole target and replays the whole submitted root. Layer bounds help source capture and transient allocation, but they are not a damage-tracking system.

Current limitations

  • Active root Layer 3D is unsupported and skipped.
  • An active 3D layer cannot contain another active 3D descendant or an ordinary descendant with active motion blur.
  • Motion blur uses one directional kernel, so rotations with corners moving in different directions are approximated by the strongest projected motion.
  • blend_mode and cache_hint are stored on snapshots today, but the current audited backend does not change output for them.

How the pieces connect

Compositing begins when recording publishes child boundaries and layer metadata. Commit freezes that metadata beside immutable child slots. Replay then decides at each child boundary whether to recurse directly or flatten into an image first.

Root isolation handles whole-scene opacity or blur before presentation. Child boundaries add painter-ordered isolation and optional 3D projection. Together, that arrangement lets Story layer systems, camera scenes, Layer 3D samples, and motion-blurred presentations reuse the same snapshot tree and frame clock without inventing a separate scene graph for effects.

Go deeper

Rune Project brings Rune Story authoring together with the Rune Engine rendering foundation.