@bigmistqke/view.gl 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.github/ISSUE_TEMPLATE/bug-report.yml +31 -0
  3. package/.github/ISSUE_TEMPLATE/feature-request.yml +27 -0
  4. package/.github/workflows/codeql.yml +46 -0
  5. package/.github/workflows/deploy-page.yml +38 -0
  6. package/.github/workflows/format.yml +40 -0
  7. package/README.md +92 -35
  8. package/dev/404.html +19 -0
  9. package/dev/dist/404.html +19 -0
  10. package/dev/dist/assets/bezier-DuLTb2d1.js +294 -0
  11. package/dev/dist/assets/game_of_life-D7qHdFcv.js +202 -0
  12. package/dev/dist/assets/grid-Ie22U_9K.js +173 -0
  13. package/dev/dist/assets/index-0qrXMlfv.js +109 -0
  14. package/dev/dist/assets/index-C2N3u8wj.css +12 -0
  15. package/dev/dist/assets/main-BZ1N6pp6.js +32 -0
  16. package/dev/dist/assets/overview-DAxtMIw5.js +78 -0
  17. package/dev/dist/assets/pix_sim-DIhzM_vu.js +501 -0
  18. package/dev/dist/assets/symbol-BouRL-Ni.js +65 -0
  19. package/dev/dist/assets/tag-C_bg62fD.js +516 -0
  20. package/dev/dist/assets/tetris-IMnkSi9p.js +344 -0
  21. package/dev/dist/assets/utils-CvCgsM08.js +50 -0
  22. package/dev/dist/index.html +51 -0
  23. package/dev/index.html +39 -10
  24. package/dev/{bezier.ts → src/examples/bezier.ts} +1 -1
  25. package/dev/{grid.ts → src/examples/grid.ts} +1 -1
  26. package/dev/{pix_sim.ts → src/examples/pix_sim.ts} +112 -97
  27. package/dev/src/examples/symbol.ts +79 -0
  28. package/dev/{tetris.ts → src/examples/tetris.ts} +1 -0
  29. package/dev/src/index.css +12 -0
  30. package/dev/src/index.ts +69 -0
  31. package/dev/{utils.ts → src/utils.ts} +8 -2
  32. package/dev/vite.config.ts +9 -1
  33. package/dist/index.d.mts +3 -2
  34. package/dist/index.mjs +81 -27
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/tag.d.mts +9 -9
  37. package/dist/tag.mjs +46 -17
  38. package/dist/tag.mjs.map +1 -1
  39. package/dist/{types-DxpS9Bae.d.mts → types-DoFAJoh-.d.mts} +18 -18
  40. package/package.json +20 -7
  41. package/src/index.ts +39 -17
  42. package/src/tag.ts +47 -39
  43. package/src/types.ts +24 -24
  44. package/src/{utils.ts → utils/index.ts} +39 -14
  45. package/src/utils/object.ts +27 -0
  46. package/test/index.test.ts +1017 -0
  47. package/test/mocks/webgl.ts +248 -0
  48. package/test/setup.ts +13 -0
  49. package/test/tag.test.ts +790 -0
  50. package/vitest.config.ts +15 -0
  51. /package/dev/{game_of_life.ts → src/examples/game_of_life.ts} +0 -0
  52. /package/dev/{index.ts → src/examples/overview.ts} +0 -0
@@ -0,0 +1,501 @@
1
+ import { b as createFramebuffer, a as attribute, g as glsl, u as uniform, c as compile, v as view } from './tag-C_bg62fD.js';
2
+ import { c as createElement } from './utils-CvCgsM08.js';
3
+
4
+ const MATERIALS = {
5
+ SAND: {
6
+ color: [1, 0.8, 0],
7
+ // Yellow sand
8
+ id: 1
9
+ },
10
+ WATER: {
11
+ color: [0, 0.5, 1],
12
+ // Blue water
13
+ id: 2
14
+ },
15
+ STONE: {
16
+ color: [0.5, 0.5, 0.5],
17
+ // Gray stone
18
+ id: 3
19
+ }
20
+ };
21
+ const MATERIAL_SIZE = Object.keys(MATERIALS).length;
22
+ let playing = false;
23
+ let currentMaterial = MATERIALS.SAND.id;
24
+ const container = createElement("div", {
25
+ style: "display: flex; flex-direction: column; align-items: center; gap: 10px;",
26
+ parentElement: document.body
27
+ });
28
+ const buttonContainer = createElement("div", {
29
+ style: "display: flex; gap: 10px; margin-bottom: 10px;",
30
+ parentElement: container
31
+ });
32
+ Object.entries(MATERIALS).forEach(([name, material]) => {
33
+ createElement("button", {
34
+ textContent: name.toLowerCase(),
35
+ "data-name": name,
36
+ "data-id": material.id.toString(),
37
+ style: `padding: 5px 10px;
38
+ font-size: 14px;
39
+ font-family: arial;
40
+ cursor: pointer;
41
+ color: black;
42
+ background: ${currentMaterial === material.id ? `rgb(${material.color.map((c) => Math.floor(c * 255)).join(",")})` : `rgba(${material.color.map((c) => Math.floor(c * 255)).join(",")}, 0.75)`};
43
+ border-color: ${name === "SAND" ? "black" : "white"};
44
+ border: 2px solid rgb(${material.color.map((c) => Math.floor(c * 255)).join(",")});
45
+ border-radius: 2px;
46
+ `,
47
+ onclick() {
48
+ currentMaterial = material.id;
49
+ buttonContainer.querySelectorAll("button").forEach((btn) => {
50
+ const name2 = btn.getAttribute("data-name");
51
+ const id = btn.getAttribute("data-id");
52
+ if (id === currentMaterial.toString()) {
53
+ btn.style.background = `rgb(${MATERIALS[name2].color.map((c) => Math.floor(c * 255)).join(",")})`;
54
+ } else {
55
+ btn.style.background = `rgba(${MATERIALS[name2].color.map((c) => Math.floor(c * 255)).join(",")}, 0.75)`;
56
+ }
57
+ });
58
+ },
59
+ parentElement: buttonContainer
60
+ });
61
+ });
62
+ function spray() {
63
+ return Math.floor(Math.random() * 8) * (Math.random() < 0.5 ? 1 : -1);
64
+ }
65
+ const canvas = createElement("canvas", {
66
+ parentElement: container,
67
+ onmousedown() {
68
+ const rect = canvas.getBoundingClientRect();
69
+ const controller = new AbortController();
70
+ window.addEventListener(
71
+ "mousemove",
72
+ (event) => {
73
+ const x = Math.floor((event.clientX - rect.left + spray()) * (canvas.width / rect.width));
74
+ const y = Math.floor(
75
+ (rect.bottom - event.clientY + spray()) * (canvas.height / rect.height)
76
+ );
77
+ const dimensions = [8, 8];
78
+ const data = new Uint8Array(
79
+ function* () {
80
+ for (let i = 0; i < dimensions[0] * dimensions[1]; i++) {
81
+ yield (currentMaterial & 1) * 255;
82
+ yield (currentMaterial >> 1 & 1) * 255;
83
+ yield (currentMaterial >> 2 & 1) * 255;
84
+ yield 255;
85
+ }
86
+ }()
87
+ );
88
+ gl.bindTexture(gl.TEXTURE_2D, read.texture);
89
+ gl.texSubImage2D(
90
+ gl.TEXTURE_2D,
91
+ 0,
92
+ Math.max(0, Math.min(WIDTH - dimensions[0], x)),
93
+ Math.max(0, Math.min(HEIGHT - dimensions[1], y)),
94
+ dimensions[0],
95
+ dimensions[1],
96
+ gl.RGBA,
97
+ gl.UNSIGNED_BYTE,
98
+ data
99
+ );
100
+ gl.bindTexture(gl.TEXTURE_2D, write.texture);
101
+ gl.texSubImage2D(
102
+ gl.TEXTURE_2D,
103
+ 0,
104
+ Math.max(0, Math.min(WIDTH - dimensions[0], x)),
105
+ Math.max(0, Math.min(HEIGHT - dimensions[1], y)),
106
+ dimensions[0],
107
+ dimensions[1],
108
+ gl.RGBA,
109
+ gl.UNSIGNED_BYTE,
110
+ data
111
+ );
112
+ render();
113
+ },
114
+ controller
115
+ );
116
+ window.addEventListener(
117
+ "mouseup",
118
+ () => {
119
+ controller.abort();
120
+ },
121
+ controller
122
+ );
123
+ }
124
+ });
125
+ const gl = canvas.getContext("webgl2", { antialias: false });
126
+ if (!gl) {
127
+ throw new Error("WebGL not supported");
128
+ }
129
+ canvas.width = 256 * 2;
130
+ canvas.height = 256 * 2;
131
+ const WIDTH = canvas.width;
132
+ const HEIGHT = canvas.height;
133
+ const vertex = glsl`#version 300 es
134
+ ${attribute.vec2("a_vertex")}
135
+ out vec2 v_uv;
136
+ void main() {
137
+ v_uv = a_vertex * 0.5 + 0.5;
138
+ gl_Position = vec4(a_vertex, 0, 1);
139
+ }`;
140
+ const stepFragment = glsl`#version 300 es
141
+ precision highp float;
142
+ in vec2 v_uv;
143
+ ${uniform.sampler2D("u_texture")}
144
+ ${uniform.vec2("u_texelSize")}
145
+ out vec4 fragColor;
146
+
147
+ // Material constants (like enums)
148
+ const int MAT_EMPTY = 0;
149
+ const int MAT_SAND = 1;
150
+ const int MAT_WATER = 2;
151
+ const int MAT_STONE = 3;
152
+
153
+ // Direction constants
154
+ const vec2 DIR_UP = vec2(0.0, 1.0);
155
+ const vec2 DIR_DOWN = vec2(0.0, -1.0);
156
+ const vec2 DIR_LEFT = vec2(-1.0, 0.0);
157
+ const vec2 DIR_RIGHT = vec2(1.0, 0.0);
158
+
159
+ // Helper function to decode material from RGB
160
+ int getMaterial(vec4 color) {
161
+ return int(color.r + color.g * 2.0 + color.b * 4.0);
162
+ }
163
+
164
+ // Helper function to encode material to RGB
165
+ vec4 encodeMaterial(int material) {
166
+ return vec4(
167
+ float(material & 1),
168
+ float((material >> 1) & 1),
169
+ float((material >> 2) & 1),
170
+ 1.0
171
+ );
172
+ }
173
+
174
+ void main() {
175
+ // Sample the current state
176
+ vec4 current = texture(u_texture, v_uv);
177
+
178
+ // Check boundaries
179
+ bool atBottom = v_uv.y - u_texelSize.y < 0.0;
180
+ bool atLeft = v_uv.x - u_texelSize.x < 0.0;
181
+ bool atRight = v_uv.x + u_texelSize.x > 1.0;
182
+ bool atTop = v_uv.y + u_texelSize.y > 1.0;
183
+
184
+ // Default: keep current state
185
+ fragColor = current;
186
+
187
+ int material = getMaterial(current);
188
+
189
+ int below = getMaterial(texture(u_texture, v_uv + DIR_DOWN * u_texelSize));
190
+ int above = getMaterial(texture(u_texture, v_uv + DIR_UP * u_texelSize));
191
+ int aboveLeft = getMaterial(texture(u_texture, v_uv + (DIR_UP + DIR_LEFT) * u_texelSize));
192
+ int aboveRight = getMaterial(texture(u_texture, v_uv + (DIR_UP + DIR_RIGHT) * u_texelSize));
193
+ int belowLeft = getMaterial(texture(u_texture, v_uv + (DIR_DOWN + DIR_LEFT) * u_texelSize));
194
+ int belowRight = getMaterial(texture(u_texture, v_uv + (DIR_DOWN + DIR_RIGHT) * u_texelSize));
195
+
196
+ // Physics simulation using switch
197
+ switch (material) {
198
+ case MAT_EMPTY:{
199
+ // Empty cell - check what can fall/flow into it
200
+
201
+ // Check for sand from above (highest priority - sand is denser)
202
+ bool sandDirectlyAbove = !atTop && above == MAT_SAND;
203
+ if (sandDirectlyAbove) {
204
+ fragColor = encodeMaterial(MAT_SAND);
205
+ break;
206
+ }
207
+
208
+ // Check for sand sliding from diagonal
209
+ bool sandAboveLeft = !atTop && !atRight && aboveLeft == MAT_SAND;
210
+ bool sandAboveRight = !atTop && !atLeft && aboveRight == MAT_SAND;
211
+
212
+ if (sandAboveLeft) {
213
+ vec4 left = texture(u_texture, v_uv + DIR_LEFT * u_texelSize);
214
+ bool leftBlocked = getMaterial(left) != MAT_EMPTY;
215
+ bool canSlideFromLeft = leftBlocked || atBottom;
216
+ if (canSlideFromLeft) {
217
+ fragColor = encodeMaterial(MAT_SAND);
218
+ break;
219
+ }
220
+ }
221
+
222
+ if (sandAboveRight) {
223
+ vec4 right = texture(u_texture, v_uv + DIR_RIGHT * u_texelSize);
224
+ bool rightBlocked = getMaterial(right) != MAT_EMPTY;
225
+ bool canSlideFromRight = rightBlocked || atBottom;
226
+ if (canSlideFromRight) {
227
+ fragColor = encodeMaterial(MAT_SAND);
228
+ break;
229
+ }
230
+ }
231
+
232
+ // Check for water from above
233
+ bool waterDirectlyAbove = !atTop && above == MAT_WATER;
234
+ if (waterDirectlyAbove) {
235
+ fragColor = encodeMaterial(MAT_WATER);
236
+ break;
237
+ }
238
+
239
+ // Check for water sliding from diagonal
240
+ bool waterAboveLeft = !atTop && !atRight && aboveLeft == MAT_WATER;
241
+ bool waterAboveRight = !atTop && !atLeft && aboveRight == MAT_WATER;
242
+
243
+ if (waterAboveLeft) {
244
+ vec4 left = texture(u_texture, v_uv + DIR_LEFT * u_texelSize);
245
+ bool sandToLeft = getMaterial(left) == MAT_SAND;
246
+ if (!sandToLeft) {
247
+ fragColor = encodeMaterial(MAT_WATER);
248
+ break;
249
+ }
250
+ }
251
+
252
+ if (waterAboveRight) {
253
+ vec4 right = texture(u_texture, v_uv + DIR_RIGHT * u_texelSize);
254
+ bool sandToRight = getMaterial(right) == MAT_SAND;
255
+ if (!sandToRight) {
256
+ fragColor = encodeMaterial(MAT_WATER);
257
+ break;
258
+ }
259
+ }
260
+
261
+ // Check for water flowing horizontally
262
+ vec4 left = texture(u_texture, v_uv + DIR_LEFT * u_texelSize);
263
+ vec4 right = texture(u_texture, v_uv + DIR_RIGHT * u_texelSize);
264
+ int matLeft = getMaterial(left);
265
+ int matRight = getMaterial(right);
266
+
267
+ bool waterToLeft = !atRight && matLeft == MAT_WATER;
268
+ bool waterToRight = !atLeft && matRight == MAT_WATER;
269
+
270
+ if (!waterToLeft && !waterToRight) break;
271
+
272
+ // Random choice for symmetric flow
273
+ float rand = fract(sin(dot(v_uv * 1000.0, vec2(12.9898, 78.233))) * 43758.5453);
274
+ bool preferLeft = rand < 0.5;
275
+
276
+ if (
277
+ waterToLeft && waterToRight ||
278
+ waterToLeft ||
279
+ waterToRight
280
+ ) {
281
+ fragColor = encodeMaterial(MAT_WATER);
282
+ break;
283
+ }
284
+ }
285
+
286
+ case MAT_SAND: {
287
+ // Sand particle - check if it should fall
288
+ bool canFallThrough = below == MAT_EMPTY || below == MAT_WATER;
289
+ bool canFallDown = !atBottom && canFallThrough;
290
+
291
+ if (canFallDown) {
292
+ fragColor = encodeMaterial(MAT_EMPTY);
293
+ break;
294
+ }
295
+
296
+ // Check diagonal falling
297
+ bool canFallThroughLeft = belowLeft == MAT_EMPTY || belowLeft == MAT_WATER;
298
+ bool canFallThroughRight = belowRight == MAT_EMPTY || belowRight == MAT_WATER;
299
+
300
+ bool canFallDownLeft = !atBottom && !atLeft && canFallThroughLeft;
301
+ bool canFallDownRight = !atBottom && !atRight && canFallThroughRight;
302
+
303
+ if (canFallDownLeft || canFallDownRight) {
304
+ fragColor = encodeMaterial(MAT_EMPTY);
305
+ break;
306
+ }
307
+
308
+ // Sand stays in place
309
+ break;
310
+ }
311
+
312
+ case MAT_WATER: {
313
+ // Water - check if being displaced by sand first
314
+ bool sandFallingFromAbove = !atTop && above == MAT_SAND;
315
+ if (sandFallingFromAbove) {
316
+ fragColor = encodeMaterial(MAT_SAND);
317
+ break;
318
+ }
319
+
320
+ // Check sand sliding into water from diagonals
321
+ bool sandFromAboveLeft = !atTop && !atRight && aboveLeft == MAT_SAND;
322
+ bool sandFromAboveRight = !atTop && !atLeft && aboveRight == MAT_SAND;
323
+
324
+ if (sandFromAboveLeft) {
325
+ vec4 left = texture(u_texture, v_uv + DIR_LEFT * u_texelSize);
326
+ bool leftNotEmpty = getMaterial(left) != MAT_EMPTY;
327
+ bool sandCanSlideIn = leftNotEmpty || atBottom;
328
+
329
+ if (sandCanSlideIn) {
330
+ fragColor = encodeMaterial(MAT_SAND);
331
+ break;
332
+ }
333
+ }
334
+
335
+ if (sandFromAboveRight) {
336
+ vec4 right = texture(u_texture, v_uv + DIR_RIGHT * u_texelSize);
337
+ bool rightNotEmpty = getMaterial(right) != MAT_EMPTY;
338
+ bool sandCanSlideIn = rightNotEmpty || atBottom;
339
+
340
+ if (sandCanSlideIn) {
341
+ fragColor = encodeMaterial(MAT_SAND);
342
+ break;
343
+ }
344
+ }
345
+
346
+ // Normal water physics - falling
347
+ bool canFallDown = !atBottom && below == MAT_EMPTY;
348
+ bool canFlowDownLeft = !atBottom && !atLeft && belowLeft == MAT_EMPTY;
349
+ bool canFlowDownRight = !atBottom && !atRight && belowRight == MAT_EMPTY;
350
+
351
+ if (canFallDown || canFlowDownLeft || canFlowDownRight) {
352
+ fragColor = encodeMaterial(MAT_EMPTY);
353
+ break;
354
+ }
355
+
356
+ // Horizontal spreading
357
+ vec4 left = texture(u_texture, v_uv + DIR_LEFT * u_texelSize);
358
+ vec4 right = texture(u_texture, v_uv + DIR_RIGHT * u_texelSize);
359
+ int matLeft = getMaterial(left);
360
+ int matRight = getMaterial(right);
361
+
362
+ bool canFlowLeft = !atLeft && matLeft == MAT_EMPTY;
363
+ bool canFlowRight = !atRight && matRight == MAT_EMPTY;
364
+
365
+ if (!canFlowLeft && !canFlowRight) {
366
+ break;
367
+ }
368
+
369
+ // Random horizontal movement for fluid behavior
370
+ float rand = fract(sin(dot(v_uv * 1000.0, vec2(12.9898, 78.233))) * 43758.5453);
371
+ bool preferLeft = rand < 0.5;
372
+
373
+ if (
374
+ canFlowLeft && preferLeft ||
375
+ canFlowRight && !preferLeft ||
376
+ canFlowLeft ||
377
+ canFlowDownRight
378
+ ) {
379
+ fragColor = encodeMaterial(MAT_EMPTY);
380
+ break;
381
+ }
382
+
383
+ }
384
+
385
+ case MAT_STONE:
386
+ // Stone doesn't move
387
+ break;
388
+
389
+ default:
390
+ // Unknown material - keep as is
391
+ break;
392
+ }
393
+ }`;
394
+ const renderFragment = glsl`#version 300 es
395
+ precision mediump float;
396
+ in vec2 v_uv;
397
+ ${uniform.sampler2D("u_texture")}
398
+ ${uniform.vec3("u_palette", { size: MATERIAL_SIZE })}
399
+ out vec4 fragColor;
400
+
401
+ // Material constants (must match stepFragment)
402
+ const int MAT_EMPTY = 0;
403
+ const int MAT_SAND = 1;
404
+ const int MAT_WATER = 2;
405
+ const int MAT_STONE = 3;
406
+
407
+ // Helper function to decode material from RGB
408
+ int getMaterial(vec4 color) {
409
+ return int(color.r + color.g * 2.0 + color.b * 4.0);
410
+ }
411
+
412
+ void main() {
413
+ vec4 texel = texture(u_texture, v_uv);
414
+ int material = getMaterial(texel);
415
+
416
+ if (material == MAT_EMPTY) {
417
+ fragColor = vec4(0.0, 0.0, 0.0, 1.0); // Black background
418
+ } else if (material > 0 && material <= ${MATERIAL_SIZE}) {
419
+ fragColor = vec4(u_palette[material - 1], 1.0);
420
+ } else {
421
+ fragColor = vec4(1.0, 0.0, 1.0, 1.0); // Magenta for unknown materials
422
+ }
423
+ }`;
424
+ const { program: stepProgram, schema: stepSchema } = compile(gl, vertex, stepFragment);
425
+ const stepView = view(gl, stepProgram, stepSchema);
426
+ const { program: renderProgram, schema: renderSchema } = compile(gl, vertex, renderFragment);
427
+ const renderView = view(gl, renderProgram, {
428
+ ...renderSchema,
429
+ attributes: {
430
+ ...renderSchema.attributes,
431
+ a_vertex: {
432
+ ...renderSchema.attributes.a_vertex,
433
+ buffer: stepView.attributes.a_vertex.buffer
434
+ }
435
+ }
436
+ });
437
+ gl.useProgram(renderProgram);
438
+ renderView.uniforms.u_palette.set(
439
+ new Float32Array(Object.values(MATERIALS).flatMap(({ color }) => color))
440
+ );
441
+ gl.useProgram(stepProgram);
442
+ stepView.attributes.a_vertex.set(new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]));
443
+ const framebufferOptions = {
444
+ attachment: "color",
445
+ width: WIDTH,
446
+ height: HEIGHT,
447
+ type: "UNSIGNED_BYTE",
448
+ magFilter: "NEAREST",
449
+ minFilter: "NEAREST",
450
+ internalFormat: "RGBA",
451
+ format: "RGBA"
452
+ };
453
+ let read = createFramebuffer(gl, framebufferOptions);
454
+ let write = createFramebuffer(gl, framebufferOptions);
455
+ const initData = new Uint8Array(
456
+ function* () {
457
+ for (let i = 0; i < WIDTH * HEIGHT; i++) {
458
+ yield 0;
459
+ yield 0;
460
+ yield 0;
461
+ yield 255;
462
+ }
463
+ }()
464
+ );
465
+ gl.bindTexture(gl.TEXTURE_2D, read.texture);
466
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, gl.RGBA, gl.UNSIGNED_BYTE, initData);
467
+ gl.bindTexture(gl.TEXTURE_2D, write.texture);
468
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, gl.RGBA, gl.UNSIGNED_BYTE, initData);
469
+ function step() {
470
+ gl.bindFramebuffer(gl.FRAMEBUFFER, write.framebuffer);
471
+ gl.viewport(0, 0, WIDTH, HEIGHT);
472
+ gl.useProgram(stepProgram);
473
+ gl.activeTexture(gl.TEXTURE0);
474
+ gl.bindTexture(gl.TEXTURE_2D, read.texture);
475
+ stepView.uniforms.u_texture.set(0);
476
+ stepView.uniforms.u_texelSize.set(1 / WIDTH, 1 / HEIGHT);
477
+ stepView.attributes.a_vertex.bind();
478
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
479
+ }
480
+ function render() {
481
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
482
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
483
+ gl.useProgram(renderProgram);
484
+ gl.activeTexture(gl.TEXTURE0);
485
+ gl.bindTexture(gl.TEXTURE_2D, write.texture);
486
+ renderView.uniforms.u_texture.set(0);
487
+ renderView.attributes.a_vertex.bind();
488
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
489
+ }
490
+ function animate() {
491
+ if (playing) {
492
+ step();
493
+ render();
494
+ [read, write] = [write, read];
495
+ requestAnimationFrame(animate);
496
+ }
497
+ }
498
+ playing = true;
499
+ animate();
500
+
501
+ export { MATERIALS };
@@ -0,0 +1,65 @@
1
+ import { a as attribute, u as uniform, g as glsl, c as compile, v as view } from './tag-C_bg62fD.js';
2
+ import { c as createElement } from './utils-CvCgsM08.js';
3
+
4
+ const canvas = createElement("canvas", {
5
+ width: window.innerWidth,
6
+ height: window.innerHeight,
7
+ parentElement: document.body,
8
+ style: "width: 100%; height: 100%"
9
+ });
10
+ new ResizeObserver(() => {
11
+ canvas.width = window.innerWidth;
12
+ canvas.height = window.innerHeight;
13
+ gl.viewport(0, 0, canvas.width, canvas.height);
14
+ draw(performance.now());
15
+ }).observe(canvas);
16
+ const gl = canvas.getContext("webgl2");
17
+ gl.viewport(0, 0, canvas.width, canvas.height);
18
+ const vertex = glsl`
19
+ precision mediump float;
20
+
21
+ ${attribute.vec2("a_vertex")}
22
+ ${uniform.float("u_time")}
23
+
24
+ void main() {
25
+ float s = sin(u_time);
26
+ float c = cos(u_time);
27
+ mat2 rotation = mat2(
28
+ c, -s,
29
+ s, c
30
+ );
31
+ vec2 position = a_vertex * rotation;
32
+ gl_Position = vec4(position, 0.0, 1.0);
33
+ }`;
34
+ const u_color = Symbol("color");
35
+ const fragment = glsl`
36
+ precision mediump float;
37
+
38
+ ${uniform.vec3(u_color)}
39
+
40
+ void main() {
41
+ gl_FragColor = vec4(${u_color}, 1.0);
42
+ }`;
43
+ const { program, schema } = compile(gl, vertex, fragment);
44
+ const { attributes, uniforms } = view(gl, program, schema);
45
+ gl.useProgram(program);
46
+ uniforms[u_color].set(0, 255, 0);
47
+ attributes.a_vertex.set(
48
+ new Float32Array([
49
+ // top
50
+ 0,
51
+ 1,
52
+ // bottom left
53
+ -1,
54
+ -1,
55
+ // bottom right
56
+ 1,
57
+ -1
58
+ ])
59
+ ).bind();
60
+ function draw(delta) {
61
+ requestAnimationFrame(draw);
62
+ uniforms.u_time.set(delta / 1e3);
63
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 100);
64
+ }
65
+ requestAnimationFrame(draw);