The Game of Life
The Game of Life was devised by the mathematician John Conway. The rules are simple. At a given moment in time, a cell is either alive or dead. A cell interacts with its 8 neighbors at every time step. If a live cell has fewer than two live neighbors, it dies. If a live cell has two or three live neighbors, it survives. If it has more than three, it dies. If a dead cell has exactly three live neighbors, it comes alive.
The default board contains a single glider. You can randomize the board, or you can click a cell to switch it to/from alive from/to dead.
The randomize button will run through all the cells, turning them alive with a probability you can set with the input field. It defaults to 0.5.
The program works by rendering back and forth between two textures. Upon CPU updates, the board is buffered to the currently active framebuffer. The value in the red channel of the texture represents a cell's status. A good next step would be to utilize the other 4 channels, and try to map each quadrant of the board to a particular channel.
The fragment shader runs a 3x3 kernel over the board. The perimeter of the kernel is all 1s, and there's an 9 in the middle. The 1s count the number of surrounding alive cells, and the 9 bumps that sum if the current cell is alive. The 9 is an idea I got from Inigo Quilez. Initially, I had nested branches in the shader - one to check if the current cell was alive or dead, and then nested update rules. This is correct, but by inflating the sum for living cells, you can unambiguously map the convolution sum in a single level of branching.