Hey folks! I want to do a little post-mortem / how-stuff-works post about one of the parts of my game that I thought turned out well, and hopefully encourage people to try the same kind of approach in future projects. This is what your character in Shutdown looks like:

…and this is how much code it takes to draw it:
love.graphics.draw(quadMesh)
How? Well, I lied (gasp!)—there’s more code. Everything in that animation is being drawn by a fragment shader. If you already know what that is, skip this paragraph and read on. Otherwise: a fragment shader is basically a small program that runs on the GPU for every pixel in a thing you’re drawing (in this case, a simple square). Unlike drawing libraries you might be used to, there’s nothing high-level to work with: there’s no “line here”, “circle there”, “gradient this way”; each pixel has to figure out what color it is independently. If you want half of the screen red and half of it blue, then each pixel has to do the math to figure out whether it’s on one side or the other and turn itself red or blue accordingly. This sounds complicated, but it lets you do some fantastically cool stuff—if there’s a mathematical way to express some pattern in an image, you can draw it with a fragment shader. Also, since the pixels are all independent, the GPU can do a ton of their calculations in parallel, which is way way faster than calculating each pixel in sequence.
So what’s happening in this shader is less complicated than it might seem—there’s a few basic-ish fundamental components that’re getting mixed together in a way that your eye can’t quite follow. Here’s a simplified earlier version of the thing:

A little easier to follow, right? There’s a layer of wide triangular stripes moving continuously outwards, and another layer of narrower stripes moving continuously inwards, and they’re being blended together with the mask of three equally-spaced triangles which are oscillating in and out from the center. There are reasonably straightforward mathematical ways to express all of those patterns in terms of a given pixel’s location on the screen—it involves a thing called signed-distance fields, which is a way bigger subject than I can get into here but a lot of which I learned from Íñigo Quilez’s excellent articles. Each pixel, again, is doing all of these distance calculations and deciding which part of the pattern it’s in to determine its color. The final, full-color image is made up of three layers of evaluation of the pattern, each using a different color and running at a slightly different speed, which gives the overall pattern a neat sort of ghosting / echoing effect.
One really convenient thing about having an entire image procedurally generated out of numbers is that you can poke at the numbers and get a way different image. In this case, I realized that there was nothing particularly requiring that the pattern be made out of triangles—all the math functions I was using just took a number of sides to use for their distance calculations. It was barely any additional code (albeit with a lot of fiddling with color values) to make a menagerie of other digital creatures for your character to be chasing after:

An indispensable part of this whole process was Shadertoy, which is a website that lets you edit and preview fragment shaders in your browser. There’s a community of amazing people there who’re constantly making incredible things, all of which are open-source—I highly recommend spending some time browsing through the gallery and checking out how things work. You can see the in-progress-ish version of this “creature” shader on my page over here—edit the code (the “SIDES” bit near the top, for instance) and hit the Run button to see how the result looks.
So that’s about it—I ended up with these pretty nifty-looking animated creatures without having to draw anything and with, in the end, only 69 lines of shader code. Worth trying for your next game, no?
If you’d like to see all of these effects (and more!) in their full, non-GIF-compressed glory, Shutdown is right here. Thanks for reading!
