Skip to content

Commit 8547e22

Browse files
committed
docs: add an example of simple particules (ping pong FBO)
1 parent babad94 commit 8547e22

File tree

6 files changed

+137
-17
lines changed

6 files changed

+137
-17
lines changed

docs/.vitepress/sidebars.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,23 @@ export const examplesSidebar = sections.map((section) => {
1616

1717
return {
1818
text: upperFirst(section),
19-
items: pages.map((page) => {
20-
const indexPath = path.join(sectionPath, page, "index.md");
21-
const { data } = matter(fs.readFileSync(indexPath, "utf8"));
22-
return {
23-
text: data.title || page,
24-
link: `/examples/${section}/${page}/`,
25-
};
26-
}),
19+
items: pages
20+
.map((page) => {
21+
const indexPath = path.join(sectionPath, page, "index.md");
22+
const { data } = matter(fs.readFileSync(indexPath, "utf8"));
23+
return {
24+
title: data.title || page,
25+
slug: page,
26+
position: data.position || 0,
27+
};
28+
})
29+
.sort((a, b) => a.position - b.position)
30+
.map((data) => {
31+
return {
32+
text: data.title,
33+
link: `/examples/${section}/${data.slug}/`,
34+
};
35+
}),
2736
};
2837
});
2938

docs/examples/gpgpu/boids/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
2-
title: ping pong FBO (Boids)
2+
title: Boids
3+
position: 2
34
---
45

56
::: example-editor {deps=tweakpane@^4.0.5}

docs/examples/gpgpu/boids/index.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ const velocities = usePingPongFBO(gl, {
2828
dataTexture: {
2929
name: "tVelocities",
3030
initialData: Array.from({ length: count }).flatMap(() => [
31-
Math.random() * 0.2 - 0.1,
32-
Math.random() * 0.2 - 0.1,
33-
0,
34-
0,
31+
/* R */ Math.random() * 0.2 - 0.1,
32+
/* G */ Math.random() * 0.2 - 0.1,
33+
/* B */ 0,
34+
/* A */ 0,
3535
]),
3636
},
3737
});
@@ -45,10 +45,10 @@ const positions = usePingPongFBO(gl, {
4545
dataTexture: {
4646
name: "tPositions",
4747
initialData: Array.from({ length: count }).flatMap(() => [
48-
Math.random() * 2 - 1,
49-
Math.random() * 2 - 1,
50-
0,
51-
0,
48+
/* R */ Math.random() * 2 - 1,
49+
/* G */ Math.random() * 2 - 1,
50+
/* B */ 0,
51+
/* A */ 0,
5252
]),
5353
},
5454
});
@@ -67,6 +67,7 @@ const renderPass = useWebGLCanvas({
6767
transparent: true,
6868
});
6969

70+
// Wait for the canvas to be resized to avoid a flash at the first renders
7071
renderPass.onCanvasReady(() => {
7172
useLoop(({ deltaTime }) => {
7273
velocities.uniforms.uDeltaTime = deltaTime / 500;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Particles
3+
position: 1
4+
---
5+
6+
::: example-editor
7+
8+
<<< ./index.ts
9+
<<< @/snippets/canvas-full/styles.css
10+
<<< @/snippets/default/index.html
11+
12+
:::
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import {
2+
useWebGLContext,
3+
useLoop,
4+
usePingPongFBO,
5+
useWebGLCanvas,
6+
createFloatDataTexture,
7+
} from "usegl";
8+
import "./styles.css";
9+
10+
const { gl, canvas } = useWebGLContext("#glCanvas");
11+
12+
const positionsFragment = /* glsl */ `
13+
uniform float uDeltaTime;
14+
uniform sampler2D tPositions;
15+
uniform sampler2D tVelocities;
16+
17+
in vec2 uv;
18+
out vec4 fragColor;
19+
20+
vec2 wrapToRange(vec2 value) {
21+
vec2 shifted = value + 1.0;
22+
vec2 wrapped = mod(mod(shifted, 2.0) + 2.0, 2.0);
23+
return wrapped - 1.0;
24+
}
25+
26+
void main() {
27+
vec2 position = texture(tPositions, uv).xy;
28+
vec2 velocity = texture(tVelocities, uv).xy;
29+
30+
fragColor = vec4(wrapToRange(position + velocity * uDeltaTime), 0.0, 0.0);
31+
}
32+
`;
33+
34+
const count = 100;
35+
36+
const positions = usePingPongFBO(gl, {
37+
fragment: positionsFragment,
38+
uniforms: {
39+
uDeltaTime: 0,
40+
tVelocities: createFloatDataTexture(
41+
Array.from({ length: count }).flatMap(() => [
42+
/* R */ Math.random() * 0.2 - 0.1,
43+
/* G */ Math.random() * 0.2 - 0.1,
44+
/* B */ 0,
45+
/* A */ 0,
46+
]),
47+
),
48+
},
49+
dataTexture: {
50+
name: "tPositions",
51+
initialData: Array.from({ length: count }).flatMap(() => [
52+
/* R */ Math.random() * 2 - 1,
53+
/* G */ Math.random() * 2 - 1,
54+
/* B */ 0,
55+
/* A */ 0,
56+
]),
57+
},
58+
});
59+
60+
const renderPass = useWebGLCanvas({
61+
canvas,
62+
vertex: `
63+
uniform sampler2D uPositions;
64+
in vec2 aCoords;
65+
66+
void main() {
67+
gl_Position = vec4(texture2D(uPositions, aCoords).xy, 0, 1);
68+
gl_PointSize = 20.0;
69+
}
70+
`,
71+
fragment: `
72+
in vec2 uv;
73+
out vec4 outColor;
74+
75+
void main() {
76+
vec2 uv = gl_PointCoord.xy;
77+
outColor = vec4(0, 1, .5, smoothstep(0.5, 0.4, length(uv - 0.5)));
78+
}
79+
`,
80+
uniforms: {
81+
uPositions: () => positions.texture,
82+
},
83+
attributes: {
84+
aCoords: positions.coords,
85+
},
86+
transparent: true,
87+
});
88+
89+
// Wait for the canvas to be resized to avoid a flash at the first renders
90+
renderPass.onCanvasReady(() => {
91+
useLoop(({ deltaTime }) => {
92+
positions.uniforms.uDeltaTime = deltaTime / 500;
93+
positions.render();
94+
renderPass.render();
95+
});
96+
});

docs/snippets/canvas-full/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ canvas {
66
width: 100svw;
77
height: 100svh;
88
display: block;
9+
background: #000;
910
}

0 commit comments

Comments
 (0)