Implementation of Conway's game of life cellular automata with a retro-style shader. Added as example on webgpgpu Github.
Sketch of WebGL implementation:
- Underlying cellular automata runs Conway's game of life
- States as game tiles: new cells: small blue; live cells: blue; died: skulls
- Life diffuses out coloring nearby areas
- A single RGBA texture stores the game state. We render to/from this texture as a framebuffer.
- Each color channel in [0,1] can be mapped to a [0,255] byte value
- The green channel stores the game of life state
- The blue channel stores the diffusing field
- The red channel outputs a tile ID value that is passed to a tile shader to render the game
The core of the code is implemented in this shader:
void main() { vec2 dx = vec2(1.0/game_size.x,0.0); vec2 dy = vec2(0.0,1.0/game_size.y); vec2 p = gl_FragCoord.xy/game_size; // Get neighborhood vec4 s00 = texture2D(game_state,p-dy-dx); vec4 s01 = texture2D(game_state,p-dy); vec4 s02 = texture2D(game_state,p-dy+dx); vec4 s10 = texture2D(game_state,p-dx); vec4 s11 = texture2D(game_state,p); vec4 s12 = texture2D(game_state,p+dx); vec4 s20 = texture2D(game_state,p+dy-dx); vec4 s21 = texture2D(game_state,p+dy); vec4 s22 = texture2D(game_state,p+dy+dx); // Current cell and neighborhood cell density count float cell = s11.g; float near = s00.g+s01.g+s02.g+s10.g+s12.g+s20.g+s21.g+s22.g; float next = (cell>0.5&&near>1.5&&near<3.5||near>2.5&&near<3.5)?1.0:0.0; // Diffusing state: average neighborhood with decay; add density if live float diffuse = (s01.b+s10.b+s11.b+s12.b+s21.b)*0.2; diffuse = max(diffuse*0.95,next); // Tile ID: int id = (cell>0.5&&next>0.5)? MATURE : (cell>0.5&&next<0.5)? DIED : (cell<0.5&&next>0.5)? NEWBORN : SHADES + int((1.0-diffuse)*16.0)+1; gl_FragColor = vec4(float(id)/256.0,next,diffuse,0.0); }
No comments:
Post a Comment