Skip to content

Commit

Permalink
docs: add Conway's Game of Life example
Browse files Browse the repository at this point in the history
  • Loading branch information
jsulpis committed Mar 6, 2025
1 parent 8547e22 commit 5fbd838
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
12 changes: 12 additions & 0 deletions docs/examples/gpgpu/game-of-life/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Game of Life
position: 3
---

::: example-editor

<<< ./index.ts
<<< @/snippets/canvas-square/styles.css
<<< @/snippets/default/index.html

:::
79 changes: 79 additions & 0 deletions docs/examples/gpgpu/game-of-life/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useWebGLContext, useLoop, usePingPongFBO, useWebGLCanvas } from "usegl";
import "./styles.css";

const { gl, canvas } = useWebGLContext("#glCanvas");

const gridSize = 100;

const lifeUpdateFragment = /* glsl */ `
uniform sampler2D tCurrentState;
varying vec2 vUv;
int getCellState(vec2 coord) {
vec4 color = texture2D(tCurrentState, coord);
return color.r > 0.5 ? 1 : 0;
}
void main() {
int neighbors = 0;
float dx = 1.0 / float(${gridSize});
float dy = 1.0 / float(${gridSize});
neighbors += getCellState(vUv + vec2(-dx, -dy));
neighbors += getCellState(vUv + vec2(-dx, 0.0));
neighbors += getCellState(vUv + vec2(-dx, dy));
neighbors += getCellState(vUv + vec2(0.0, -dy));
neighbors += getCellState(vUv + vec2(0.0, dy));
neighbors += getCellState(vUv + vec2(dx, -dy));
neighbors += getCellState(vUv + vec2(dx, 0.0));
neighbors += getCellState(vUv + vec2(dx, dy));
int currentState = getCellState(vUv);
float newState = 0.0;
if (currentState == 0 && neighbors == 3) {
newState = 1.0; // Birth
} else if (currentState == 1 && (neighbors == 2 || neighbors == 3)) {
newState = 1.0; // Survival
}
gl_FragColor = vec4(newState, newState, newState, 1.0);
}
`;

const initialData = new Float32Array(gridSize * gridSize * 4);
for (let i = 0; i < gridSize * gridSize; i++) {
const alive = Math.random() < 0.5 ? 1 : 0;
initialData.set([alive, alive, alive, 1], i * 4);
}

const gameState = usePingPongFBO(gl, {
fragment: lifeUpdateFragment,
dataTexture: {
name: "tCurrentState",
initialData,
},
});

const renderPass = useWebGLCanvas({
canvas,
fragment: /* glsl */ `
uniform sampler2D tCurrentState;
attribute vec2 vUv;
void main() {
gl_FragColor = texture2D(tCurrentState, vUv);
}
`,
uniforms: {
tCurrentState: () => gameState.texture,
},
});

let lastTime = 0;
useLoop(({ elapsedTime }) => {
if (elapsedTime - lastTime < 50) return;
gameState.render();
renderPass.render();
lastTime = elapsedTime;
});

0 comments on commit 5fbd838

Please sign in to comment.