Performance
Cost dominator: grid cells, not polygons
Section titled “Cost dominator: grid cells, not polygons”The glyphcss renderer scales with grid cells, not polygon count. A 10k-triangle
GLB and a unit cube cost the same per frame, because both rasterize into the same
cols × rows Uint8Array stamp.
Frame size:
- 80×24 grid (~tiny): ~2,000 cells, < 1ms per frame
- 160×48 grid (typical): ~7,500 cells, ~3ms per frame
- 240×72 grid (large): ~17,000 cells, ~6ms per frame
The bake (60 frames × per-frame cost) happens once at init and then again only on
drag-end / wheel-end. Steady-state animation costs zero JavaScript — the strip
is a static <pre> and the browser composites the translate3d transform on the
GPU.
When to drop hotspot count
Section titled “When to drop hotspot count”The hit layer’s per-frame cost is O(hotspots × N_frames) during the bake. For
60 hotspots and 60 frames, that’s 3,600 projections per bake. Still fast (< 5ms)
but you’ll notice if you push past ~500 hotspots in one scene.
For “highlight every vertex” UIs, consider:
- Group nearby vertices into one logical hotspot.
- Render hotspots only for the front-facing hemisphere (skip backface verts).
- Lower
N_framesto 30 — half the bake cost, slight loss of rotation smoothness.
Avoid steady-state JS
Section titled “Avoid steady-state JS”If you find yourself reaching for requestAnimationFrame to update the scene
every frame, stop. The strip flipbook is designed to make that unnecessary. Two
recipes that come up:
“I want the scene to react to scroll position”: map scroll to camera.rotY in
chunks of 2π / 60, debounce 100ms, re-bake. The user sees ~10fps of camera
updates which feels smooth enough.
“I want a continuous color pulse on a hotspot”: put the pulse on the hotspot’s
<div> directly via CSS animation. The hotspot div is real DOM — @keyframes pulse on it works the same as any other CSS animation.