Core renderer overview
insomni is an opinionated 2D WebGPU renderer built on
TypeGPU. It is tuned for data-heavy
scenes: every primitive is packed into one flat typed array, uploaded in a
single batch per frame, and drawn with SDF-style pipelines. The public surface
is one barrel import:
import { initGPU, createRenderer, createLayer, rgba } from "insomni";The pack, upload, draw model
Section titled “The pack, upload, draw model”A frame moves through three stages.
- Pack (CPU). You author shapes into a
Layer. EachpushRect/pushCircle/pushSegmentcall appends one instance — a fixed 16-float (64-byte) record — into the layer’sUberPack. All shape kinds share oneArrayBuffer; adjacent instances of the same kind, opacity, and group merge into a singleDrawCommand. - Upload (GPU).
Renderer2D.render(layers)concatenates every layer’s pack into one storage buffer and uploads it once. The buffer grows power-of-2 / 1.25× and is reused frame to frame. - Draw (GPU). The renderer issues the merged draw commands in a single
render pass: opaque geometry first (depth write on), then transparent
geometry. Depth is the per-instance
orderfield, stamped in global submission order, so painter stacking is explicit — later-submitted draws land on top.
const gpu = await initGPU();const renderer = createRenderer(gpu, canvas);
const layer = createLayer();layer.pushRect({ x: 16, y: 16, width: 180, height: 72, fill: rgba(0.06, 0.09, 0.13, 1) });layer.pushCircle({ cx: 240, cy: 52, radius: 18, fill: rgba(0.2, 0.7, 1, 0.9) });
function frame() { renderer.render([layer]); requestAnimationFrame(frame);}frame();Everything drawable is a Layer
Section titled “Everything drawable is a Layer”There is no separate “background” or “overlay” type — every drawable is a
Layer (or a specialized layer the renderer treats like one). A Layer wraps
one UberPack, a coordinate space, an optional default
Group, and a handful of metadata fields
(zIndex, cache, visible, label). Text and sprites ride on the same layer
through dedicated sibling pipelines.
Source-order draw semantics
Section titled “Source-order draw semantics”render([a, b]) draws a first, then b. Layers are flat z-bands: layer b
is entirely above layer a (painter’s order), with no per-shape interleave
across layers. To interleave shapes, put them in the same layer (intra-
layer overlap resolves via transparency and depth). To
override insertion order without reordering the array, set
Layer.zIndex.
Static vs dynamic layers
Section titled “Static vs dynamic layers”By default a layer is dynamic: its pack is re-concatenated and re-uploaded every frame. For content that rarely changes, two retention tiers skip that work:
- Retained buffers —
renderer.retainLayer(layer, key)hands the layer’s pack a stable GPU buffer. Whilekey(andpack.version) are unchanged the layer draws with zero re-upload. See Packing and Renderer. - Cached RTT bakes —
renderer.cacheLayer(layer)(or thecache: "always"/"auto"hint) rasterizes the layer once into a texture and composites the snapshot instead of redrawing it.
Combined with damage-tracked partial redraw, this lets a busy scene re-rasterize only what actually moved.
Map of this section
Section titled “Map of this section”- Renderer & frame loop —
Renderer2D,createRenderer,render(layers), retention, config & timing. - Layers & groups — the universal drawable and shareable transform containers.
- Packing & buffers —
UberPack, the instance schema, strides, dynamic growth, repack helpers. - Spaces & cameras — world/ui/device spaces, camera slots,
project, camera-view helpers. - Drawing primitives — rects, circles, segments, curves, arcs, sprites.
- Text — raster (system-font) and MSDF/TTF text.
- Specialized layers — Buffer, Mirror, Navigator, Lod, LabelCuller, CustomDrawable.
- Cameras & viewport — viewports, pan/zoom/pinch.
- Interactions — hit-testing, hover, selection, tooltips, brush, menus.
- Transparency (OIT) — the default-on A-buffer.
- Damage & partial redraw — persistent backbuffer + scissored regions.
- SVG export — CPU backend over the same
Layer[]. - Math, color & animation — vectors, matrices, color spaces, RNG, easings.
- Debugging & profiling — the render-debug probe and the profiler.