Building NOVASWARM: ten thousand enemies on the GPU

2026-06-07 · 3 min read · NOVASWARM Studio

NOVASWARM started as a question. How much of a real arcade game can run inside a browser tab if you stop treating the GPU as a picture frame and start treating it as a computer?

The answer, it turns out, is almost all of it. Here is how the game actually works under the hood.

WebGPU, not WebGL

For a decade the web had WebGL, which is great at drawing triangles and not much else. WebGPU is the modern replacement, and the headline feature is compute shaders: arbitrary parallel programs that run across thousands of GPU threads. That single capability is what lets NOVASWARM exist.

In NOVASWARM, your CPU does almost nothing. It reads your input, decides when to fire, and hands a tiny block of numbers to the GPU. Everything else, the swarm, the bullets, the collisions, the explosions, the warping background, happens on the graphics card.

A swarm that thinks in parallel

The enemies are not scripted paths. Each drone runs a flocking model: separation so they do not pile up, alignment so they move together, cohesion so they clump into a swarm, and a steady pull toward your ship. Naively, every agent checking every other agent is an N-squared problem that falls over fast.

So we cheat in a principled way. Each agent samples a strided subset of its neighbours every frame, reading from a previous-frame copy of the world (a classic ping-pong buffer so reads and writes never collide). The motion still looks like a coordinated swarm, but the cost stays linear. That is how thousands of independent agents can think every single frame.

Collision, also on the GPU

When you fire, the bullets live in GPU memory too. Collision is the tricky part: thousands of enemies all testing themselves against your fire at once, in true parallel, means two threads can try to claim the same bullet in the same instant.

We resolve it with an atomic compare-and-claim. The first thread to atomically flip a bullet from alive to spent wins it and dies with it; everyone else sees it is already gone and moves on. One bullet removes exactly one drone, with no double counts and no locks.

Explosions that allocate themselves

Every kill detonates into a burst of particles drawn from a fixed pool. The compute shader grabs a slice of that pool with an atomic ring cursor, writes the new particles, and lets the oldest ones recycle. The GPU spawns and retires effects entirely on its own, without ever interrupting the main thread.

Light, not textures

The neon look is real light. The scene renders into a high dynamic range float buffer where colours are allowed to go far brighter than white. Then a separable bloom pass blooms the bright bits, chromatic aberration splits the colour at the edges, an ACES curve tonemaps it back down, and a vignette and a little film grain finish it off. Nothing is a pre-baked glow sprite.

Why it matters

All of this loads like a web page because it is one. No installer, no launcher, no plugin. Open a tab, and a few milliseconds later the GPU is simulating a swarm.

This is the first thing we have shipped. It will not be the last.