Created
October 13, 2025 11:32
-
-
Save sbOogway/bdf4ef33ecc0afe3f6ef80ecd05e3aef to your computer and use it in GitHub Desktop.
Game of life shader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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