Capability Comparison
The capstone synthesis: the surveyed systems laid side by side across the eight axes, the cross-cutting patterns that emerge, the field's points of consensus and genuine disagreement, and a delta table mapping each modern capability onto where Sparkles stands today and which milestone would deliver it.
Last reviewed: July 11, 2026
The master matrix
Programmatic engines and declarative-diagramming systems across the dimensions that most shape a reimplementation. Building blocks (rendering backends, typesetting, encoding) are components an engine binds, not engines, and are compared within their cluster pages.
| Subject | Lang | Paradigm | Rendering | Bézier | Timing model | Math typesetting | Output | License |
|---|---|---|---|---|---|---|---|---|
| Manim CE | Python | imperative | Cairo (CPU) + GL | cubic (GL: quad) | play-loop | LaTeX→dvisvgm / Typst | PyAV mp4/webm | MIT |
| ManimGL | Python | imperative | OpenGL only | quadratic | play-loop | LaTeX→dvisvgm | ffmpeg pipe | MIT |
| Motion Canvas | TS | generator | Canvas2D (web) | cubic (Canvas) | generator/play-head | MathJax→SVG | ffmpeg plugin | MIT |
| Remotion | React | pure-frame-fn | headless Chromium | web platform | pure frame(N) | web (KaTeX/MathJax) | ffmpeg | source-available |
| Theatre.js | TS | GUI timeline | — (delegates) | — | keyframe timeline | — | — (host renders) | Apache-2.0 / AGPL |
| Javis.jl | Julia | imperative | Luxor/Cairo (CPU) | cubic | frame-function | MathJax tex2svg | ffmpeg gif/mp4 | MIT (dormant) |
| Makie.jl | Julia | reactive | Cairo/GL/WGL | cubic | Observables + record | MathTeXEngine | ffmpeg | MIT |
| nannou | Rust | immediate | wgpu (GPU) | n/a (immediate) | manual per-frame | — (RustType) | PNG seq → ffmpeg | MIT/Apache |
| MathAnimation | C++ | imperative | plutovg→GL atlas | cubic+quad | GUI timeline | MiKTeX→dvisvgm | SVT-AV1/IVF | custom EULA |
| Penrose | TS | declarative | SVG (optimized) | — | — (static) | MathJax | SVG/PNG/PDF | MIT |
| Bluefish | TS | declarative (relational) | SVG (DOM) | — | — (static) | (SVG/host) | SVG | MIT |
| TikZ/PGF | TeX | declarative | TeX driver → PDF/SVG | cubic | SVG/SMIL only | native TeX | PDF/PS/SVG | GPL/LPPL |
| Asymptote | C++-like DSL | descriptive | own VM → PS/SVG/GL | cubic (Hobby) | batched frames | LaTeX labels | EPS/PDF/SVG/3D | LGPLv3 |
| CeTZ | Typst | declarative | Typst compiler (Rust) | cubic | — (static) | native Typst math | PDF/SVG/PNG | LGPL-3.0 |
| MetaPost | DSL | declarative (equations) | own → EPS/SVG | cubic (Hobby) | — (static) | TeX btex | EPS/SVG/PNG | LGPL |
By dimension
Object & geometry model
The retained-tree model (Mobject/VMobject) is near-universal among the programmatic engines; nannou is the lone immediate-mode outlier (no retained scene, per-frame draw calls). The declarative systems replace the tree with a constraint/relation layer: Penrose optimises a numerical energy, Bluefish propagates relations locally (explicitly not a global solver — the sharpest split within the declarative camp), and the MetaPost/TikZ/Asymptote lineage solves linear equations over points.
The load-bearing geometry split is the Bézier basis: cubic wins almost everywhere (Cairo, Canvas2D, SVG, all the TeX-lineage languages), and only ManimGL and Manim-community's GL classes use quadratic — a choice that pays off only when the GPU is the sole target. A second split is data layout: ManimGL packs one interleaved structured array (GPU-upload-friendly); Manim-community-Cairo keeps points and colours in parallel arrays (better for the two independent Transform passes). The bezier-eval.d probe quantifies why cubic is the safer canonical form.
Animation & timing model
Five distinct execution models appear, and the choice is the deepest architectural fork:
- Imperative play-loop — Manim, Javis, MathAnimation:
play(Animation)calls stepped by a scene loop. The richest morph/Transformvocabulary. - Generator / play-head — Motion Canvas:
yielded generators against a moving playhead. - Pure frame function — Remotion:
frame(N)is pure; the cleanest determinism story, but no stateful morph. - Reactive / observable — Makie: mutate observables,
recordcaptures frames. A plotting model, not a morph engine. - GUI timeline — Theatre.js: keyframes on a visual timeline, driving a host renderer.
The declarative systems are mostly static — animation is a finding-of-absence (TikZ's animate is SVG/SMIL-only; Penrose/Bluefish/CeTZ/MetaPost have none). Only the retained play-loop engines implement true Transform with submobject-tree + point-count alignment; Javis reduces the same problem to a Hungarian-assignment polygon match.
Rendering & rasterization
The CPU-vector-vs-GPU tension recurs everywhere. Deterministic, reproducible output lives on CPU vector (Cairo — Manim-community default, Javis via Luxor, Makie via CairoMakie); real-time preview lives on GPU (ManimGL, Makie's GLMakie, nannou's wgpu, MathAnimation's GL atlas). Manim community's metaclass keeps both alive from one class definition. Fill strategy divides into winding fill (Cairo, ManimGL's GPU stencil) and triangulation (earcut on the GL paths, needing skia-pathops boolean pre-processing for holey shapes). The rendering-backends cluster ranks the bindable options by D-effort: Cairo/Blend2D/NanoVG (C API, easy), Vello (no C API, hardest), Skia (C++, no stable C ABI, heaviest).
Typesetting & text
Two philosophies. The shell-out camp (both Manim forks, Asymptote, MathAnimation) compiles LaTeX → dvisvgm → SVG and imports the paths — powerful but needs a TeX install and a subprocess. The native camp is the modern trend: TikZ is TeX, and CeTZ/Typst have first-class math in a self-contained compiler with a wasm build. The web engines lean on MathJax/KaTeX (HTML/SVG, not morphable outlines). For a native engine, HarfBuzz+FreeType is the best-bindable route for non-math glyph outlines.
Output & encoding
The encode integration spans the full spectrum: ffmpeg subprocess (ManimGL, Motion Canvas, Javis — zero ABI), libav in-process (Manim community's PyAV), headless-browser capture (Remotion), PNG-sequence + external tool (nannou, Asymptote via ImageMagick), and direct codec linking (MathAnimation's SVT-AV1→IVF, the far end). The video-encoding cluster recommends the subprocess-first, libav-later path for a D engine.
Determinism, caching & performance
Content-hash caching is Manim community's signature optimisation (hash each play(), reuse the cached partial movie file) — and, strikingly, almost nobody else implements it: Motion Canvas re-renders the whole range, Remotion gets determinism "for free" from pure frame functions but caches at the asset layer, ManimGL re-renders (caching only LaTeX/SVG on disk). Correct caching requires deterministic rendering, which is exactly why the CPU-vector oracle matters.
Consensus
- Vector, not raster. Every serious engine represents shapes as Bézier
VMobjects, because interpolation and morphing demand it. - Cubic is the interchange default (ManimGL's quadratic is the GPU-motivated exception).
- A retained scene graph for object-level animation; immediate mode only for procedural per-frame work.
- Rate functions + staggered composition are the shared timing primitive.
- LaTeX→SVG remains the pragmatic math path, even as native-typesetting (Typst) rises.
- CPU-vector for reproducible video, GPU for interactivity — often both.
Architectural trade-offs
| Decision | One side | The other side |
|---|---|---|
| Bézier basis | quadratic → GPU-native, one-shader fill (ManimGL) | cubic → CPU/SVG/Canvas-native, lossless (everyone else) |
| Data layout | interleaved AoS → GPU upload (ManimGL) | parallel SoA → independent lerp passes (CE-Cairo) |
| Timing model | imperative play-loop → rich morph (Manim) | pure frame-fn → trivial determinism (Remotion) |
| Renderer | CPU vector → deterministic, slow (Cairo) | GPU → fast, non-reproducible (GL) |
| Typesetting | shell out to LaTeX → powerful, heavy (Manim) | native compiler → fast, self-contained (Typst) |
| Encoding | subprocess → zero ABI, fork cost (ManimGL) | linked libav → in-process, ABI surface (PyAV) |
| Scene identity | GC/reference tree → ergonomic (Manim) | value/arena → @nogc hot loop |
The delta table
Each modern capability, where Sparkles stands today (per the baseline), and the milestone that would deliver it.
| Capability | Best-in-class exemplar | Sparkles today | Milestone |
|---|---|---|---|
| Cubic Bézier geometry + alignment | Manim CE | ✗ (only Vector) | M1–M2 |
| Retained scene graph | Manim | ✗ | M2 |
Rate functions + lag_ratio | Manim | ✗ (probe only) | M1, M4 |
Transform morph + alignment | Manim | ✗ | M4 |
| Deterministic CPU-vector backend | Cairo | ✗ (ImportC recipe ready) | M3 |
| GPU backend + frame capture | ManimGL | ◐ raylib wired | M7 |
| Video encode + content-hash cache | Manim CE | ✗ | M5 |
| LaTeX / native math typesetting | Manim / Typst | ✗ | M6 |
| Web/interactive (wasm) preview | Motion Canvas | ◐ buildDWasmModule | M8 |
Reactive ValueTracker/observables | Makie | ✗ | M9 |
| Capability-gated renderer abstraction | (novel; DbI) | ◐ idiom exists | M3, M7 |
Open questions & gaps
- Native + web from one codebase is unproven at this scale — the wasm text constraint (no HarfBuzz/FreeType in WASI) forces a split text path.
- Determinism across a CPU oracle and a GPU preview needs a perceptual-diff tolerance nobody in the survey formalises.
- A
@nogcscene graph is a road not taken by any surveyed engine (all use GC or refcounting); the payoff and cost are untested. - Declarative layout (Penrose/Bluefish) as an optional layer over an imperative engine is unexplored — a possible Sparkles differentiator.
Sources
This synthesis draws on every deep-dive and building-block page in the catalog (linked throughout), the concepts vocabulary, and the baseline audit; each claim's primary source is in the cited page's own Sources section.