Skip to content

Instantly share code, notes, and snippets.

@sbOogway
Created October 13, 2025 11:32
Show Gist options
  • Save sbOogway/bdf4ef33ecc0afe3f6ef80ecd05e3aef to your computer and use it in GitHub Desktop.
Save sbOogway/bdf4ef33ecc0afe3f6ef80ecd05e3aef to your computer and use it in GitHub Desktop.
Game of life shader
#version 330 core
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 resolution; // screen size in pixels
uniform float time;
uniform vec2 mouse; // normalized (0‑1) mouse position
uniform sampler2D prevBuffer;
layout(location = 0) out vec4 diffuseColor;
// ------------------------------------------------------------
// Helper: simple random based on integer cell coordinates
float random (in ivec2 cell) {
// convert to float, keep the same formula as before
vec2 p = vec2(cell);
return fract(100.0 * sin(p.x + fract(100.0 * sin(p.y))));
}
// ------------------------------------------------------------
void main() {
// ----- 1. Map fragment to a cell index -----
const ivec2 GRID = ivec2(192, 108); // grid size
vec2 cellSize = resolution / vec2(GRID); // size of one cell in pixels
ivec2 cell = ivec2(floor(gl_FragCoord.xy / cellSize));
// ----- 2. Determine if this cell is alive in the previous frame -----
// Sample the previous buffer at the centre of the cell
vec2 uv = (vec2(cell) + 0.5) / vec2(GRID); // normalized coordinates (0‑1)
bool self = texture(prevBuffer, uv).g > 0.5;
// ----- 3. Count alive neighbours (Moore neighbourhood) -----
int n = 0;
for (int dx = -1; dx <= 1; ++dx) {
for (int dy = -1; dy <= 1; ++dy) {
if (dx == 0 && dy == 0) continue;
ivec2 neigh = cell + ivec2(dx, dy);
// wrap around the edges (toroidal grid)
neigh = ivec2(mod(vec2(neigh), vec2(GRID)));
vec2 nUV = (vec2(neigh) + 0.5) / vec2(GRID);
float col = texture(prevBuffer, nUV).y;
n += (col > 0.5) ? 1 : 0;
}
}
// ----- 4. Apply Conway’s Game of Life rules -----
bool alive = ((n == 2 || n == 3) && self) || (n == 3 && !self);
// ----- 5. Mouse interaction (highlight cells near the cursor) -----
// mouse is supplied in normalized coordinates (0‑1)
vec2 mouseCell = mouse * vec2(GRID);
bool nearMouse = distance(vec2(cell), mouseCell) <= 3.0; // 3‑cell radius
// ----- 6. Determine final colour -----
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 black = vec3(0.0);
vec3 color = (nearMouse || alive) ? green : black;
// ----- 7. Initial random fill (first 0.1 s) -----
if (time <= 0.1) {
color = random(cell) > 0.5 ? green : black;
}
diffuseColor = vec4(color, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment