Devlog // Double It
Liquid numbers: building the WebGL2 metaball renderer
Every orb in DOUBLE IT is not a sprite. It is a mathematical field, and the picture you see is the shape of that field on a given frame.
When I started DOUBLE IT I had one visual promise I refused to negotiate on: the numbers had to feel liquid. Not "circles with a wobble shader" — actually liquid. Two orbs drifting into each other should visibly reach for one another, form a bridge, and become one body before the merge resolves. That promise decided the entire rendering architecture.
One draw call, one field
The whole board is rendered by a single full-screen WebGL2 pass. The
fragment shader receives every orb as data — position, radius, tint,
stretch, and a few animation scalars — and evaluates a
signed distance field (SDF) per pixel. Each orb contributes a
distance to its surface; the distances are combined with a
smooth minimum instead of a hard min().
That single change is what makes the magic: where two orbs come
close, their fields blend early, and the surface between them bulges
into the classic metaball bridge without any geometry existing at
all.
Everything else is layered on the same field. The rim light is a function of the distance gradient. The internal "plasma" texture scrolls in the orb's local space so it feels like the body has currents inside it. The glow is a second, cheaper falloff read from the same distance. There is no post-processing chain — one pass in, one image out.
Why the digits are not liquid
The first prototype drew the numbers into the field too, and it was a disaster — readable at rest, mush in motion. Numbers are the game's entire information channel; if a merged 128 is illegible for even a third of a second, the player loses the plot of their own combo. So the digits live on a separate canvas layer, positioned by the same simulation but rendered as crisp text with their own reveal animation. The liquid is emotional; the digits are informational. They only pretend to be one thing.
The simulation underneath
Orbs sit on an orbital ring and are driven by a small spring
simulation — every body has a target angle, and forces ease it there.
Stretch is not faked: when an orb accelerates, its shader receives a
stretch vector and elongates the SDF along the motion axis, which is
why absorbed orbs visibly smear toward a black hole and a
launched orb feels like a droplet leaving a tap. During special
choreographies the game marks orbs as driven and takes
direct control, but it drives the same parameters the physics uses,
so the material never changes character.
A rule I kept the whole project: the renderer has no opinions. It draws the field it is given. Every effect — merges, black holes, supernovae — is expressed as data the simulation writes, never as a special case in the shader.
What it costs, and where it pays
A per-pixel SDF over a dozen bodies is not free, and mobile GPUs are where promises go to die. The shader is written to keep the loop tight: squared distances until the last moment, no branches in the hot path, and the plasma texture sampled once. On the quality ladder (more on that in the device-adaptive graphics entry) the resolution scale and glow taps drop before anything visible breaks. The payoff is that the game's identity survives every tier: even at the lowest rung, orbs still merge like liquid — they just do it with fewer sparkles.
The renderer is the reason the game reads as alive in a two-second clip, which — as I learned later while cutting promo videos — is roughly the attention budget you get before someone scrolls. The liquid was worth it.
DOUBLE IT is playable free in the browser at doubleit.b-smart.xyz — more entries in the devlog.