Koi Drift

How the water is drawn

30 September 2026 · 6 min read

The pond in Koi Drift is not a picture of water. It is water drawn live, sixty times a second, on whatever phone you have. This is how it is built, what it cost to make it run smoothly, and what we learned measuring it.

A painted floor under live water

Each pond has a painted floor — pebbles, sand, stone — drawn once as an image. Over it sits a layer of water rendered in WebGL, the browser’s way of talking to the graphics chip. The water layer does three things every frame. It displaces the floor slightly, so the pebbles wobble as if seen through moving water. It lays caustics across them — the bright, shifting net of light that sunlight makes on a real pond bottom. And it adds highlights, the small specular flashes on the surface where a ripple catches the light.

Ripples come from the koi. When one swims, it leaves a wake that spreads and fades; when it leaves the pond, there is a splash. These are computed as a field of disturbances that the water shader reads.

The koi

The koi are painted sprites — six varieties, each hand-finished — but they are not flat. Each is drawn on a strip mesh that bends as the fish swims, so the body flexes through a turn. The water’s caustics are also applied to the koi’s back, so a koi swimming through a bright patch of light picks up the light, which is what sells the idea that it is in the water rather than on top of it. A pale rim that once made the sprites look cut out was removed in an earlier update by blending them correctly against the water.

What made phones stutter

Getting the pond to look right was the first half of the work; getting it to run at a steady frame rate on a mid-range phone was the second, and it was done with measurement rather than guesswork. The game was played on a real device and its frames were recorded. Three things stood out.

First, dozens of small animations that had been part of the old, pre-WebGL pond were still running every frame even though nothing they animated was visible. They were removed. Second, two full-screen blur effects — a drop shadow on the pond frame and a soft glow — were being recomputed sixty times a second; both were replaced with static versions that look the same and cost nothing. Third, the water itself was being computed at the phone’s full pixel density, which on a modern phone is a great many pixels.

Two passes, not one

The obvious fix for the third problem — draw the whole pond at lower resolution and scale it up — was tried and rejected, because it blurred the floor and the koi, and a measured comparison showed the pebble detail dropping to about two thirds of what it should be. The fix that shipped splits the water into two passes. The expensive part — the light field of displacement, caustics and highlights — is computed once at reduced density into a small texture. Then a second, cheap pass composes the final image at full density, sampling the floor and the koi at their native sharpness and reading the light field from the small texture. Water light is smooth by nature, so computing it at lower density is invisible; the floor and the koi, which are not smooth, stay pixel-sharp. The difference from the full-cost image was measured at better than 50 dB, which is to say not visible.

The governor

Phones differ, and a phone that is warm or busy differs from itself. So the game watches its own frame times. If, over a second, more than about a third of the frames run long, it steps the water density down first, then the sharpness of the koi, and steps back up when the phone recovers. The order matters: the water is the cheapest thing to soften and the last thing you would notice. An earlier version of this governor did not trigger correctly; it was found by the same measurement and rebuilt.

Why bother

Koi Drift is a puzzle; it would work with flat water. But the thing the game asks of you — look before you touch — depends on the pond being worth looking at, and on it never hitching under your finger at the moment you decide to tap. The water is the reason to look, and the frame rate is the reason the look never lies.