Skip to content

Commit 5fbd838

Browse files
committed
docs: add Conway's Game of Life example
1 parent 8547e22 commit 5fbd838

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Game of Life
3+
position: 3
4+
---
5+
6+
::: example-editor
7+
8+
<<< ./index.ts
9+
<<< @/snippets/canvas-square/styles.css
10+
<<< @/snippets/default/index.html
11+
12+
:::
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { useWebGLContext, useLoop, usePingPongFBO, useWebGLCanvas } from "usegl";
2+
import "./styles.css";
3+
4+
const { gl, canvas } = useWebGLContext("#glCanvas");
5+
6+
const gridSize = 100;
7+
8+
const lifeUpdateFragment = /* glsl */ `
9+
uniform sampler2D tCurrentState;
10+
varying vec2 vUv;
11+
12+
int getCellState(vec2 coord) {
13+
vec4 color = texture2D(tCurrentState, coord);
14+
return color.r > 0.5 ? 1 : 0;
15+
}
16+
17+
void main() {
18+
int neighbors = 0;
19+
float dx = 1.0 / float(${gridSize});
20+
float dy = 1.0 / float(${gridSize});
21+
22+
neighbors += getCellState(vUv + vec2(-dx, -dy));
23+
neighbors += getCellState(vUv + vec2(-dx, 0.0));
24+
neighbors += getCellState(vUv + vec2(-dx, dy));
25+
neighbors += getCellState(vUv + vec2(0.0, -dy));
26+
neighbors += getCellState(vUv + vec2(0.0, dy));
27+
neighbors += getCellState(vUv + vec2(dx, -dy));
28+
neighbors += getCellState(vUv + vec2(dx, 0.0));
29+
neighbors += getCellState(vUv + vec2(dx, dy));
30+
31+
int currentState = getCellState(vUv);
32+
float newState = 0.0;
33+
34+
if (currentState == 0 && neighbors == 3) {
35+
newState = 1.0; // Birth
36+
} else if (currentState == 1 && (neighbors == 2 || neighbors == 3)) {
37+
newState = 1.0; // Survival
38+
}
39+
40+
gl_FragColor = vec4(newState, newState, newState, 1.0);
41+
}
42+
`;
43+
44+
const initialData = new Float32Array(gridSize * gridSize * 4);
45+
for (let i = 0; i < gridSize * gridSize; i++) {
46+
const alive = Math.random() < 0.5 ? 1 : 0;
47+
initialData.set([alive, alive, alive, 1], i * 4);
48+
}
49+
50+
const gameState = usePingPongFBO(gl, {
51+
fragment: lifeUpdateFragment,
52+
dataTexture: {
53+
name: "tCurrentState",
54+
initialData,
55+
},
56+
});
57+
58+
const renderPass = useWebGLCanvas({
59+
canvas,
60+
fragment: /* glsl */ `
61+
uniform sampler2D tCurrentState;
62+
attribute vec2 vUv;
63+
64+
void main() {
65+
gl_FragColor = texture2D(tCurrentState, vUv);
66+
}
67+
`,
68+
uniforms: {
69+
tCurrentState: () => gameState.texture,
70+
},
71+
});
72+
73+
let lastTime = 0;
74+
useLoop(({ elapsedTime }) => {
75+
if (elapsedTime - lastTime < 50) return;
76+
gameState.render();
77+
renderPass.render();
78+
lastTime = elapsedTime;
79+
});

0 commit comments

Comments
 (0)