Skip to content

Commit aa09e6e

Browse files
committed
Update readme
1 parent bd48c76 commit aa09e6e

File tree

3 files changed

+158
-77
lines changed

3 files changed

+158
-77
lines changed

README.md

Lines changed: 138 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,160 @@
11
# lilgpu
22
Lil wrapper to toy with WebGPU
3+
```ts
4+
import { d, Lil, uniform } from "https://esm.sh/gh/gnlow/lilgpu/browser.ts"
5+
6+
class MyProgram extends Lil {
7+
vertShader = `... GLSL code ...`
8+
fragShader = `... GLSL code ...`
9+
10+
@uniform(d.struct({
11+
x: d.u32,
12+
y: d.u32,
13+
}))
14+
accessor span = { x: 10, y: 20 }
15+
16+
@uniform(d.f32)
17+
accessor blue = 0.5
18+
}
19+
const app = new MyProgram()
20+
const g = await app.init(document.querySelector("canvas")!)
21+
g.draw(4 /* The number of vertices */)
22+
23+
const tick = () => new Promise(requestAnimationFrame)
24+
25+
while (true) {
26+
await tick()
27+
basic.blue = Math.sin(Date.now()/1000)/2+0.5
28+
g.draw(4)
29+
}
30+
```
31+
- Tested on Chromium and Deno (+ Jupyter)
32+
- Not production-ready
33+
- Currently type checking is limited due to TypeScript not supporting decorator mutation ([microsoft/TypeScript#4881](https://github.com/microsoft/TypeScript/issues/4881))
334

435
## Usage
5-
See [examples](/example/).
36+
See [more examples](./example).
37+
Below is from [./example/browser/Basic.ts](./example/browser/Basic.ts).
38+
Run [this](https://esm.sh/gh/gnlow/lilgpu@bd48c76/example/browser/Basic.html) on your browser.
639

7-
### Browser
40+
### Import
41+
42+
#### Browser
843
```js
9-
import { initCanvas, d } from "https://esm.sh/gh/gnlow/lilgpu/browser.ts"
10-
11-
const g = await initCanvas({
12-
vertShader: `
13-
@vertex
14-
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
15-
let x = f32(i32(in_vertex_index) - 1);
16-
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
17-
return vec4<f32>(x, y, 0.0, 1.0);
18-
}
19-
`,
20-
fragShader: `
21-
@fragment
22-
fn fs_main() -> @location(0) vec4<f32> {
23-
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
24-
}
25-
`,
26-
canvas: document.querySelector("canvas"),
27-
})
28-
29-
g.draw(3)
44+
import { d, Lil, uniform } from "https://esm.sh/gh/gnlow/lilgpu/browser.ts"
3045
```
3146

32-
### Deno
33-
```ts
34-
import { initDeno } from "https://esm.sh/gh/gnlow/lilgpu/deno.ts"
35-
36-
const g = await initDeno({
37-
vertShader: `
38-
@vertex
39-
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
40-
let x = f32(i32(in_vertex_index) - 1);
41-
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
42-
return vec4<f32>(x, y, 0.0, 1.0);
43-
}
44-
`,
45-
fragShader: `
46-
@fragment
47-
fn fs_main() -> @location(0) vec4<f32> {
48-
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
49-
}
50-
`,
51-
width: 200,
52-
height: 200,
53-
})
54-
55-
g.draw(3)
56-
57-
await Deno.writeFile("./triangle.png", await g.getImage())
47+
#### Deno
48+
```js
49+
import { d, Lil, uniform } from "https://denopkg.com/gnlow/lilgpu/deno.ts"
5850
```
5951

60-
#### Jupyter
52+
### Define
53+
54+
#### Shader
55+
```js
56+
const vertShader = ` ... `
57+
const fragShader = ` ... `
58+
```
59+
60+
<details>
61+
<summary>Actual Shader code</summary>
62+
63+
```js
64+
const vertShader = `
65+
struct Output {
66+
@builtin(position) pos: vec4f,
67+
@location(0) uv: vec2f,
68+
}
69+
70+
@vertex
71+
fn main(
72+
@builtin(vertex_index) vertexIndex: u32,
73+
) -> Output {
74+
var pos = array<vec2f, 4>(
75+
vec2(1, 1), // top-right
76+
vec2(-1, 1), // top-left
77+
vec2(1, -1), // bottom-right
78+
vec2(-1, -1) // bottom-left
79+
);
80+
var uv = array<vec2f, 4>(
81+
vec2(1., 1.), // top-right
82+
vec2(0., 1.), // top-left
83+
vec2(1., 0.), // bottom-right
84+
vec2(0., 0.) // bottom-left
85+
);
86+
var out: Output;
87+
out.pos = vec4f(pos[vertexIndex], 0.0, 1.0);
88+
out.uv = uv[vertexIndex];
89+
return out;
90+
}
91+
`
92+
const fragShader = `
93+
@fragment
94+
fn main(
95+
@location(0) uv: vec2f,
96+
) -> @location(0) vec4f {
97+
let red = floor(uv.x * f32(span.x)) / f32(span.x);
98+
let green = floor(uv.y * f32(span.y)) / f32(span.y);
99+
return vec4(red, green, blue, 1.0);
100+
}
101+
`
102+
```
103+
104+
</details>
105+
106+
#### Uniform Buffer
61107
```ts
62-
await g.getImage() // Uint8Array
108+
class Basic extends Lil {
109+
vertShader = vertShader
110+
fragShader = fragShader
111+
112+
@uniform(d.struct({
113+
x: d.u32,
114+
y: d.u32,
115+
}))
116+
accessor span = { x: 10, y: 20 }
117+
118+
@uniform(d.f32)
119+
accessor blue = 0.5
120+
}
63121
```
64122

123+
### Draw
65124

66-
##
125+
#### Browser
126+
```ts
127+
const basic = new Basic()
128+
const g = await basic.init(document.querySelector("canvas")!)
67129

130+
g.draw(4)
131+
```
132+
133+
##### Browser - Animate
68134
```ts
69-
class App extends Lil {
70-
vertShader = ""
71-
fragShader = ""
135+
const tick = () => new Promise(requestAnimationFrame)
72136

73-
@uniform(d.f32) SEED = 0
74-
@uniform(d.f32) POW = 1.1
137+
while (true) {
138+
await tick()
139+
basic.blue = Math.sin(Date.now()/1000)/2+0.5
140+
g.draw(4)
75141
}
142+
```
143+
76144

77-
const app = new App()
145+
#### Deno
146+
```ts
147+
const basic = new Basic()
148+
const g = await basic.init(500, 300)
78149

79-
const g1 = await app.initCanvas(
80-
document.querySelector("canvas")
81-
)
150+
g.draw(4)
82151

83-
app.seed = 2
152+
const image = await g.getImage() // Uint8Array
153+
await Deno.writeFile("./Basic.png", image)
154+
```
84155

85-
const g2 = await app.initDeno({
86-
width: 200,
87-
height: 200,
88-
})
89-
```
156+
##### Deno - Jupyter
157+
```ts
158+
image
159+
```
160+
![](./example/deno/Basic.png)

example/deno/Basic.ipynb

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"cells": [
33
{
44
"cell_type": "code",
5-
"execution_count": 5,
5+
"execution_count": 1,
66
"metadata": {},
77
"outputs": [],
88
"source": [
@@ -38,7 +38,7 @@
3838
},
3939
{
4040
"cell_type": "code",
41-
"execution_count": 6,
41+
"execution_count": 2,
4242
"metadata": {},
4343
"outputs": [],
4444
"source": [
@@ -56,7 +56,7 @@
5656
},
5757
{
5858
"cell_type": "code",
59-
"execution_count": 7,
59+
"execution_count": 3,
6060
"metadata": {},
6161
"outputs": [
6262
{
@@ -65,7 +65,7 @@
6565
"\u001b[36m[Function (anonymous)]\u001b[39m"
6666
]
6767
},
68-
"execution_count": 7,
68+
"execution_count": 3,
6969
"metadata": {},
7070
"output_type": "execute_result"
7171
}
@@ -93,22 +93,32 @@
9393
},
9494
{
9595
"cell_type": "code",
96-
"execution_count": 8,
96+
"execution_count": 4,
97+
"metadata": {},
98+
"outputs": [],
99+
"source": [
100+
"g.draw(4)\n",
101+
"\n",
102+
"const image = await g.getImage()\n",
103+
"await Deno.writeFile(\"./Basic.png\", image)"
104+
]
105+
},
106+
{
107+
"cell_type": "code",
108+
"execution_count": 5,
97109
"metadata": {},
98110
"outputs": [
99111
{
100112
"data": {
101113
"image/png": "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"
102114
},
103-
"execution_count": 8,
115+
"execution_count": 5,
104116
"metadata": {},
105117
"output_type": "execute_result"
106118
}
107119
],
108120
"source": [
109-
"g.draw(4)\n",
110-
"\n",
111-
"await g.getImage()"
121+
"image"
112122
]
113123
}
114124
],
@@ -125,7 +135,7 @@
125135
"name": "typescript",
126136
"nbconvert_exporter": "script",
127137
"pygments_lexer": "typescript",
128-
"version": "5.6.2"
138+
"version": "5.8.3"
129139
}
130140
},
131141
"nbformat": 4,

example/deno/Basic.png

4.17 KB
Loading

0 commit comments

Comments
 (0)