Procedural Friend Generation

Snoopethduckduck
3 min readNov 15, 2022

This is an overview of how this Godot project generates sprites. Shaders do most of the work, so that’s what I’ll explain.

So many colors! So many emotions!

Viewports/Buffers

There are 2 buffers which ping-pong off each other to allow cellular automata to be used, and a 3rd buffer which reads from the 2nd and provides color.

Shader 1: Cellular Automata

This shader runs for a fixed number of frames and uses different techniques and automata depending on the frame.

Frame 0:

The red channel draws a rectangle. The green channel draws random noise. The blue channel draws a face.

RGB channels seperated, and all together

(I think medium upscaled this image to death but I’m too lazy to change it sorry)

Frames 1–9:

The green channel runs a cellular automata. Each pixel becomes the sum of it’s neighbours with the following weights:

These values were chosen by eye, not anything meaningful. This is what it looks like:

Frame 10:

Green values become thresholded.

Values below 0.1 become 1 and values above 0.1 become 0.

Left: before thresholding (notice the dark greens), Right: after

(The colors are being inverted, it probably isn’t necessary so sorry if that’s confusing.)

Frames 11–13:

Now the green values are either 0 or 1, we can detect corners and remove them. That is, if a green pixel == 1 and (left+right) * (top+bottom) == 1 then it becomes 0. It takes multiple frames to remove all the corners but that also means there are less connected lines, so it’s only done a few times.

Frames 14+:

Now we consider the red channel. Any green pixel with an adjacent or diagonal red neighbour becomes red, so the red rectangle from frame 0 “traverses” the greens until we stop.

Shader 2: Color

This shader runs on buffer 3 at the same time as the first shader, reads from buffer 2 (the other shader) and does the same thing every frame.

It does 4 things:

  • x co-ordinates are mirrored in the centre line
  • green pixels become black
  • pixels with red in them become white
  • blue pixels (the smile from frame 0), or black pixels with red above them become the 3rd color
Left: shader 1, Right: shader 2

That’s it!

Thanks for reading, I hope this made some sense.

--

--