I Tore Out the Renderer. Again.

Long, abandoned corridor in a decaying building, with cracked floors, peeling walls, tall windows on both sides, and a series of arches leading towards a dark doorway in the distance.

Photo by Peter Herrmann on Unsplash

In the post about my first game, Strataris, I confessed to one of those decisions that cost me weeks: I tore out a renderer I was genuinely pleased with — the old Voxel Space terrain trick — and rebuilt the entire world as a proper 3D triangle mesh, because I wanted to be able to bank and roll and fly properly. It was painful and it was right.

I’m making a second game now. And reader, I did it again.

A different shape of problem

The first game was about flying over a world. The next one is about being inside one — on foot, down through a tight, occupied place, room by room, in the dark, with something in there that wants you. A flying game wants a big open landscape. A game like this wants walls, corners, corridors, the half-second before the adversary steps into the light.

Triangle meshes would have done the job. I’ve got one, working, from last time. The sensible thing — the grown-up thing — would have been to reuse it.

I did not do the sensible thing. When will I learn?

Never, I hope — because the learning is the point. Reusing last year’s maths teaches me nothing; I only learn by building the thing I don’t yet know how to build. That means hours, days, weeks of studying other people’s source code, watching tutorials, falling down Wikipedia holes — and, these days, leaning on AI to sanity-check the maths and catch the mistakes I can’t see.

Maths instead of models

So for this new game I built the whole world out of signed distance fields, and I’ll try to explain that without turning this into a lecture, because I promised myself a long time ago these posts wouldn’t be lectures.

Here is the entire idea. Instead of describing a wall as a list of corners — a model, a mesh, a thing you’d load from a file — you write a tiny function that can answer one question for any point in space: how far are you from the nearest surface? That’s it. That’s the whole description of the world — a function that measures distance.

To draw it, the graphics card fires a ray out through every pixel and just… walks it forward. At each step it asks ‘how far is the nearest surface?’ and takes a step exactly that big, safe in the knowledge it can’t overshoot anything. A few steps later the distance drops to nothing and the ray has found a surface. Do that for a few hundred thousand pixels, sixty times a second, and you have a world.

No vertices. No meshes. No model files. A corridor is an equation. The pipework bolted along the walls is an equation. The rust is an equation. And — this is the part that sold me — so are the monsters. Horrors like the ones that stalk within this new game are not sculpted models; they are a handful of soft blobby shapes blended together with a bit of maths that melts them into one another. Distance fields love organic, wet, bio-mechanical things. They’re terrible at sharp machined edges and wonderful at things that look grown rather than built. For a game about something living in the walls, that’s exactly the right kind of wonderful.

It also means the ‘no asset files’ rule I’m so fond of doesn’t just survive — it gets easier. There’s no model to ship because there was never a model. There’s only code.1

The part where it fought back

I will not pretend this was free. It was a different kind of hard, and in some ways a nastier one.

With triangles, your mistakes are at least visible. Last time I had buildings floating serenely in the sky and, on one memorable evening, the entire planet rendered as a single spike stretching to infinity. Funny, in hindsight. But you could see what was wrong.

Distance-field bugs are sneakier. Get a single sign backwards and the world turns itself inside out — you’re suddenly inside the walls looking at the back of everything. Get the maths for a surface slightly wrong and it shimmers, flickering in and out as the ray can’t quite decide whether it’s hit anything. And there’s a performance cliff waiting the whole time: every extra creature on screen is more maths per pixel per frame, and it is entirely possible to write something correct that also turns your laptop into a small, furious heater. A good chunk of my notes from this stretch are just the word “WHY” at increasing font sizes.

Standing on shoulders of giants, again

None of this is mine. I want to be clear about that, because it matters. This technique is the beating heart of the demoscene — the people who fit entire animated worlds, with lighting and music, into programs kilobytes in size, as a sport. It’s what the wizards on Shadertoy do for fun, conjuring landscapes and creatures out of a screenful of equations. I learned it from people far cleverer than me, who did extraordinary things with it long before I came along and used it to make a monster.

I just keep finding that the harder road teaches me something. You can’t drop in a model, so you have to understand what a wall actually is. And it turns out a wall, in this game, isn’t a picture of a wall. It’s the answer to a question — how far am I from the nearest one? — asked a few hundred thousand times every frame.

I think that’s rather beautiful. I also think it cost me weeks of stress and frustration. Both things are true. That’s the deal.

Footnotes

  1. We’re not entirely asset-free in this new game — the audio came at a price