glre 0.46.0 → 0.48.0

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.
package/README.md CHANGED
@@ -101,88 +101,1067 @@ npm install glre
101
101
  <tbody>
102
102
  <tr>
103
103
  <td width="7500px" align="center" valign="center">
104
- glre simplifies WebGL2 / WebGPU programming via TypeScript, React, Solid and more (<a href="https://codesandbox.io/s/glre-basic-demo-ppzo3d">live demo</a>).
104
+ glre simplifies WebGL2 / WebGPU programming via TypeScript, React, Solid and more.
105
105
  </td>
106
106
  <td width="2500px" valign="top">
107
107
  <a href="https://codesandbox.io/s/glre-basic-demo-ppzo3d">
108
- <img alt="4" src="https://i.imgur.com/Lb3h9fs.jpg"></img>
108
+ <img alt="4" src="https://i.imgur.com/Lb3h9fs.jpg"></img>
109
109
  </a>
110
110
  </td>
111
111
  </tr>
112
112
  </tbody>
113
113
  </table>
114
114
 
115
+ <table>
116
+ <tr valign="top">
117
+ <td width="1000px">
118
+ <br />
119
+
120
+ **ESM**
121
+
122
+ ---
123
+
124
+ <!-- prettier-ignore -->
125
+ ```html
126
+ <script type="module">
127
+ import { createGL } from 'https://esm.sh/glre'
128
+ import { vec4, uv } from 'https://esm.sh/glre/node'
129
+ createGL({ fs: vec4(uv, 0, 1) }).mount()
130
+ </script>
131
+ ```
132
+
133
+ </td>
134
+ <td width="0px">
135
+ <details>
136
+ <summary>
137
+
138
+ React
139
+
140
+ ---
141
+
142
+ </summary>
143
+
144
+ <!-- prettier-ignore -->
115
145
  ```ts
116
146
  import { createRoot } from 'react-dom/client'
117
147
  import { useGL } from 'glre/react'
118
148
  import { vec4, uv } from 'glre/node'
149
+
119
150
  const Canvas = () => {
120
- const gl = useGL({ frag: vec4(uv, 0, 1) })
121
- return <canvas ref={gl.ref} />
151
+ const gl = useGL({ frag: vec4(uv, 0, 1) })
152
+ return <canvas ref={gl.ref} />
122
153
  }
123
154
 
124
- createRoot(document.getElementById('root')).render(<Canvas />)
155
+ const root = document.getElementById('root')
156
+ createRoot(root).render(<Canvas />)
125
157
  ```
126
158
 
159
+ </details>
160
+ </td>
161
+ <td width="0px">
127
162
  <details>
128
163
  <summary>
129
164
 
130
- react-native supported ([codesandbox demo](https://codesandbox.io/p/sandbox/glre-react-native-test-k2vfvk))
165
+ ReactNative
166
+
167
+ ---
131
168
 
132
169
  </summary>
133
170
 
171
+ <!-- prettier-ignore -->
134
172
  ```ts
135
173
  import { GLView } from 'expo-gl'
136
174
  import { registerRootComponent } from 'expo'
137
175
  import { useGL } from 'glre/native'
138
176
  import { vec4, uv } from 'glre/node'
177
+
139
178
  const Canvas = () => {
140
- const gl = useGL({ frag: vec4(uv, 0, 1) })
141
- return <GLView style={{ flex: 1 }} onContextCreate={gl.ref} />
179
+ const gl = useGL({ frag: vec4(uv, 0, 1) })
180
+ return (
181
+ <GLView
182
+ style={{ flex: 1 }}
183
+ onContextCreate={gl.ref}
184
+ />
185
+ )
142
186
  }
143
187
 
144
188
  registerRootComponent(Canvas)
145
189
  ```
146
190
 
147
191
  </details>
192
+ </td>
193
+ <td width="0px">
148
194
  <details>
149
195
  <summary>
150
196
 
151
- solid js supported ([codesandbox demo](https://codesandbox.io/p/sandbox/glre-solid-test-qgzhxh))
197
+ Solid.js
198
+
199
+ ---
152
200
 
153
201
  </summary>
154
202
 
203
+ <!-- prettier-ignore -->
155
204
  ```ts
156
205
  import { render } from 'solid-js/web'
157
206
  import { onGL } from 'glre/solid'
158
207
  import { vec4, uv } from 'glre/node'
208
+
159
209
  const Canvas = () => {
160
- const gl = onGL({ frag: vec4(uv, 0, 1) })
161
- return <canvas ref={gl.ref} />
210
+ const gl = onGL({ frag: vec4(uv, 0, 1) })
211
+ return <canvas ref={gl.ref} />
162
212
  }
163
213
 
164
214
  render(() => <Canvas />, document.getElementById('root'))
165
215
  ```
166
216
 
167
217
  </details>
218
+ </td>
219
+ </tr>
220
+ </table>
221
+
222
+ ---
223
+
224
+ <table>
225
+ <tr>
226
+ <td width="100%" colspan="3">
227
+
228
+ ### [Varying](https://glre.dev/docs#varying)
229
+
230
+ </td>
231
+ </tr>
232
+ <tr valign="top">
233
+ <td width="1000px">
234
+ <br />
235
+
236
+ **TSL**
237
+
238
+ ---
239
+
240
+ <!-- prettier-ignore -->
241
+ ```tsx
242
+ function Canvas() {
243
+ const tri = attribute([
244
+ 0, 0.73,
245
+ -1, -1,
246
+ 1, -1,
247
+ ])
248
+ const col = attribute([
249
+ 1, 0, 0,
250
+ 0, 1, 0,
251
+ 0, 0, 1,
252
+ ])
253
+ const gl = useGL({
254
+ isWebGL: true,
255
+ triangleCount: 1,
256
+ vert: vec4(tri, 0, 1),
257
+ frag: vec4(vertexStage(col), 1),
258
+ })
259
+ return <canvas ref={gl.ref} />
260
+ }
261
+ ```
262
+
263
+ </td>
264
+ <td width="0px">
265
+ <details>
266
+ <summary>
267
+
268
+ WebGL
269
+
270
+ ---
271
+
272
+ </summary>
273
+
274
+ <!-- prettier-ignore -->
275
+ ```tsx
276
+ function Canvas() {
277
+ const gl = useGL({
278
+ isWebGL: true,
279
+ triangleCount: 1,
280
+ vertex: `
281
+ #version 300 es
282
+ in vec4 tri;
283
+ in vec3 col;
284
+ out vec3 v_col;
285
+ void main() {
286
+ gl_Position = tri;
287
+ v_col = col;
288
+ }`,
289
+ fragment: `
290
+ #version 300 es
291
+ precision mediump float;
292
+ in vec3 v_col;
293
+ out vec4 fragColor;
294
+ void main() {
295
+ fragColor = vec4(v_col, 1.0);
296
+ }`,
297
+ })
298
+ gl.attribute('tri', [
299
+ 0, 0.73,
300
+ -1, -1,
301
+ 1, -1,
302
+ ])
303
+ gl.attribute('col', [
304
+ 1, 0, 0,
305
+ 0, 1, 0,
306
+ 0, 0, 1,
307
+ ])
308
+ return <canvas ref={gl.ref} />
309
+ }
310
+ ```
311
+
312
+ </details>
313
+ </td>
314
+ <td width="0px">
168
315
  <details>
169
316
  <summary>
170
317
 
171
- esm supported ([codesandbox demo](https://codesandbox.io/s/glre-basic-demo3-3bhr3y))
318
+ WebGPU
319
+
320
+ ---
172
321
 
173
322
  </summary>
174
323
 
175
- ```html
176
- <script type="module">
177
- import { createGL } from 'https://esm.sh/glre'
178
- import { vec4, uv } from 'https://esm.sh/glre/node'
179
- createGL({ fs: vec4(uv, 0, 1) }).mount()
180
- </script>
324
+ <!-- prettier-ignore -->
325
+ ```tsx
326
+ function Canvas() {
327
+ const gl = useGL({
328
+ isWebGL: false,
329
+ triangleCount: 1,
330
+ vertex: `
331
+ struct In {
332
+ @location(0) tri: vec2f,
333
+ @location(1) col: vec3f,
334
+ }
335
+ struct Out {
336
+ @builtin(position) position: vec4f,
337
+ @location(0) v_col: vec3f,
338
+ }
339
+ @vertex
340
+ fn main(in: In) -> Out {
341
+ var out: Out;
342
+ out.position = vec4f(in.tri, 0.0, 1.0);
343
+ out.v_col = in.col;
344
+ return out;
345
+ }`,
346
+ fragment: `
347
+ struct Out {
348
+ @builtin(position) position: vec4f,
349
+ @location(0) v_col: vec3f,
350
+ }
351
+ @fragment
352
+ fn main(out: Out) -> @location(0) vec4f {
353
+ return vec4f(out.v_col, 1.0);
354
+ }`,
355
+ })
356
+ gl.attribute('tri', [
357
+ 0, 0.73,
358
+ -1, -1,
359
+ 1, -1
360
+ ])
361
+ gl.attribute('col', [
362
+ 1, 0, 0,
363
+ 0, 1, 0,
364
+ 0, 0, 1
365
+ ])
366
+ return <canvas ref={gl.ref} />
367
+ }
181
368
  ```
182
369
 
183
370
  </details>
184
- </samp>
185
- </strong>
371
+ </td>
372
+ </tr>
373
+ <tr>
374
+ <td colspan="3">
375
+ <a href="https://glre.dev/docs#varying">
376
+ <img width="256px" src="./examples/docs/static/img/readme/varying.jpg" />
377
+ </a>
378
+ </td>
379
+ </tr>
380
+ </table>
381
+
382
+ ---
383
+
384
+ <table>
385
+ <tr>
386
+ <td width="100%" colspan="3">
387
+
388
+ ### [Uniforms](https://glre.dev/docs#uniforms)
389
+
390
+ </td>
391
+ </tr>
392
+ <tr valign="top">
393
+ <td width="1000px">
394
+ <br />
395
+
396
+ **TSL**
397
+
398
+ ---
399
+
400
+ <!-- prettier-ignore -->
401
+ ```tsx
402
+ function Canvas() {
403
+ const gl = useGL({
404
+ isWebGL: true,
405
+ frag: vec4(
406
+ uv.sub(iMouse).fract(),
407
+ iTime.sin().mul(0.5).add(0.5),
408
+ 1
409
+ ),
410
+ })
411
+ return <canvas ref={gl.ref} />
412
+ }
413
+ ```
414
+
415
+ </td>
416
+ <td width="0px">
417
+ <details>
418
+ <summary>
419
+
420
+ WebGL
421
+
422
+ ---
423
+
424
+ </summary>
425
+
426
+ <!-- prettier-ignore -->
427
+ ```tsx
428
+ function Canvas() {
429
+ const gl = useGL({
430
+ isWebGL: true,
431
+ fragment: `
432
+ #version 300 es
433
+ precision mediump float;
434
+ uniform vec2 iResolution;
435
+ uniform vec2 iMouse;
436
+ uniform float iTime;
437
+ out vec4 fragColor;
438
+ void main() {
439
+ vec2 uv = fract(gl_FragCoord.xy / iResolution.xy - iMouse);
440
+ fragColor = vec4(uv, sin(iTime) * 0.5 + 0.5, 1.0);
441
+ }`,
442
+ })
443
+ return <canvas ref={gl.ref} />
444
+ }
445
+ ```
446
+
447
+ </details>
448
+ </td>
449
+ <td width="0px">
450
+ <details>
451
+ <summary>
452
+
453
+ WebGPU
454
+
455
+ ---
456
+
457
+ </summary>
458
+
459
+ <!-- prettier-ignore -->
460
+ ```tsx
461
+ function Canvas() {
462
+ const gl = useGL({
463
+ isWebGL: false,
464
+ fragment: `
465
+ @group(0) @binding(0) var<uniform> iResolution: vec2f;
466
+ @group(0) @binding(1) var<uniform> iMouse: vec2f;
467
+ @group(0) @binding(2) var<uniform> iTime: f32;
468
+ @fragment
469
+ fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
470
+ let uv = fract(position.xy / iResolution - iMouse);
471
+ return vec4f(uv, sin(iTime) * 0.5 + 0.5, 1.0);
472
+ }`,
473
+ })
474
+ return <canvas ref={gl.ref} />
475
+ }
476
+ ```
477
+
478
+ </details>
479
+ </td>
480
+ </tr>
481
+ <tr>
482
+ <td colspan="3">
483
+ <a href="https://glre.dev/docs#uniforms">
484
+ <img width="256px" src="./examples/docs/static/img/readme/uniform.jpg" />
485
+ </a>
486
+ </td>
487
+ </tr>
488
+ </table>
489
+
490
+ ---
491
+
492
+ <table>
493
+ <tr>
494
+ <td width="100%" colspan="3">
495
+
496
+ ### [Attributes](https://glre.dev/docs#attributes)
497
+
498
+ </td>
499
+ </tr>
500
+ <tr valign="top">
501
+ <td width="1000px">
502
+ <br />
503
+
504
+ **TSL**
505
+
506
+ ---
507
+
508
+ <!-- prettier-ignore -->
509
+ ```tsx
510
+ function Canvas() {
511
+ const tri = attribute([
512
+ 0, 0.73,
513
+ -1, -1,
514
+ 1, -1
515
+ ])
516
+ const gl = useGL({
517
+ isWebGL: true,
518
+ triangleCount: 1,
519
+ vert: vec4(tri, 0, 1),
520
+ })
521
+ return <canvas ref={gl.ref} />
522
+ }
523
+ ```
524
+
525
+ </td>
526
+ <td width="0px">
527
+ <details>
528
+ <summary>
529
+
530
+ WebGL
531
+
532
+ ---
533
+
534
+ </summary>
535
+
536
+ <!-- prettier-ignore -->
537
+ ```tsx
538
+ function Canvas() {
539
+ const gl = useGL({
540
+ isWebGL: true,
541
+ triangleCount: 1,
542
+ vert: `
543
+ #version 300 es
544
+ in vec4 tri;
545
+ void main() {
546
+ gl_Position = tri;
547
+ }`,
548
+ })
549
+ gl.attribute('tri', [
550
+ 0, 0.73,
551
+ -1, -1,
552
+ 1, -1
553
+ ])
554
+ return <canvas ref={gl.ref} />
555
+ }
556
+ ```
557
+
558
+ </details>
559
+ </td>
560
+ <td width="0px">
561
+ <details>
562
+ <summary>
563
+
564
+ WebGPU
565
+
566
+ ---
567
+
568
+ </summary>
569
+
570
+ <!-- prettier-ignore -->
571
+ ```tsx
572
+ function Canvas() {
573
+ const gl = useGL({
574
+ isWebGL: false,
575
+ triangleCount: 1,
576
+ vertex: `
577
+ @vertex
578
+ fn main(@location(0) tri: vec2f) -> @builtin(position) vec4f {
579
+ return vec4f(tri, 0.0, 1.0);
580
+ }`,
581
+ })
582
+ gl.attribute('tri', [
583
+ 0, 0.73,
584
+ -1, -1,
585
+ 1, -1
586
+ ])
587
+ return <canvas ref={gl.ref} />
588
+ }
589
+ ```
590
+
591
+ </details>
592
+ </td>
593
+ </tr>
594
+ <tr>
595
+ <td colspan="3">
596
+ <a href="https://glre.dev/docs#attributes">
597
+ <img width="256px" src="./examples/docs/static/img/readme/attribute.jpg" />
598
+ </a>
599
+ </td>
600
+ </tr>
601
+ </table>
602
+
603
+ ---
604
+
605
+ <table>
606
+ <tr>
607
+ <td width="100%" colspan="3">
608
+
609
+ ### [Multiples](https://glre.dev/docs#multiples)
610
+
611
+ </td>
612
+ </tr>
613
+ <tr valign="top">
614
+ <td width="1000px">
615
+ <br />
616
+
617
+ **TSL**
618
+
619
+ ---
620
+
621
+ <!-- prettier-ignore -->
622
+ ```tsx
623
+ function Canvas() {
624
+ const tri = attribute([
625
+ 0, 0.37,
626
+ -0.5, -0.5,
627
+ 0.5, -0.5
628
+ ])
629
+ const gl = useGL(
630
+ {
631
+ isWebGL: true,
632
+ triangleCount: 1,
633
+ vert: vec4(vec2(-0.5, 0).add(tri), 0, 1),
634
+ },
635
+ {
636
+ triangleCount: 1,
637
+ vert: vec4(vec2(0.5, 0).add(tri), 0, 1),
638
+ }
639
+ )
640
+ return <canvas ref={gl.ref} />
641
+ }
642
+ ```
643
+
644
+ </td>
645
+ <td width="0px">
646
+ <details>
647
+ <summary>
648
+
649
+ WebGL
650
+
651
+ ---
652
+
653
+ </summary>
654
+
655
+ <!-- prettier-ignore -->
656
+ ```tsx
657
+ function Canvas() {
658
+ const gl = useGL(
659
+ {
660
+ isWebGL: true,
661
+ triangleCount: 1,
662
+ vert: `
663
+ #version 300 es
664
+ in vec2 tri;
665
+ void main() {
666
+ gl_Position = vec4((vec2(-0.5, 0.0) + tri), 0.0, 1.0);
667
+ }`,
668
+ },
669
+ {
670
+ triangleCount: 1,
671
+ vert: `
672
+ #version 300 es
673
+ in vec2 tri;
674
+ void main() {
675
+ gl_Position = vec4((vec2(0.5, 0.0) + tri), 0.0, 1.0);
676
+ }`,
677
+ }
678
+ )
679
+ gl.attribute('tri', [
680
+ 0, 0.37,
681
+ -0.5, -0.5,
682
+ 0.5, -0.5
683
+ ])
684
+ return <canvas ref={gl.ref} />
685
+ }
686
+ ```
687
+
688
+ </details>
689
+ </td>
690
+ <td width="0px">
691
+ <details>
692
+ <summary>
693
+
694
+ WebGPU
695
+
696
+ ---
697
+
698
+ </summary>
699
+
700
+ <!-- prettier-ignore -->
701
+ ```tsx
702
+ function Canvas() {
703
+ const gl = useGL(
704
+ {
705
+ isWebGL: false,
706
+ triangleCount: 1,
707
+ vert: `
708
+ struct In {
709
+ @location(0) tri: vec2f
710
+ }
711
+ struct Out {
712
+ @builtin(position) position: vec4f
713
+ }
714
+ @vertex
715
+ fn main(in: In) -> Out {
716
+ var out: Out;
717
+ out.position = vec4f((vec2f(-0.5, 0.0) + in.tri), 0.0, 1.0);
718
+ return out;
719
+ }`,
720
+ },
721
+ {
722
+ triangleCount: 1,
723
+ vert: `
724
+ struct In {
725
+ @location(0) tri: vec2f
726
+ }
727
+ struct Out {
728
+ @builtin(position) position: vec4f
729
+ }
730
+ @vertex
731
+ fn main(in: In) -> Out {
732
+ var out: Out;
733
+ out.position = vec4f((vec2f(0.5, 0.0) + in.tri), 0.0, 1.0);
734
+ return out;
735
+ }`,
736
+ }
737
+ )
738
+ gl.attribute('tri', [
739
+ 0, 0.37,
740
+ -0.5, -0.5,
741
+ 0.5, -0.5
742
+ ])
743
+ return <canvas ref={gl.ref} />
744
+ }
745
+ ```
746
+
747
+ </details>
748
+ </td>
749
+ </tr>
750
+ <tr>
751
+ <td colspan="3">
752
+ <a href="https://glre.dev/docs#multiples">
753
+ <img width="256px" src="./examples/docs/static/img/readme/multiple.jpg" />
754
+ </a>
755
+ </td>
756
+ </tr>
757
+ </table>
758
+
759
+ ---
760
+
761
+ <table>
762
+ <tr>
763
+ <td width="100%" colspan="3">
764
+
765
+ ### [Textures](https://glre.dev/docs#textures)
766
+
767
+ </td>
768
+ </tr>
769
+ <tr valign="top">
770
+ <td width="1000px">
771
+ <br />
772
+
773
+ **TSL**
774
+
775
+ ---
776
+
777
+ <!-- prettier-ignore -->
778
+ ```tsx
779
+ function Canvas() {
780
+ const iTexture = uniform('https://...')
781
+ const gl = useGL({
782
+ isWebGL: true,
783
+ frag: texture(iTexture, uv),
784
+ })
785
+ return <canvas ref={gl.ref} />
786
+ }
787
+ ```
788
+
789
+ </td>
790
+ <td width="0px">
791
+ <details>
792
+ <summary>
793
+
794
+ WebGL
795
+
796
+ ---
797
+
798
+ </summary>
799
+
800
+ <!-- prettier-ignore -->
801
+ ```tsx
802
+ function Canvas() {
803
+ const gl = useGL({
804
+ isWebGL: true,
805
+ fragment: `
806
+ #version 300 es
807
+ precision mediump float;
808
+ uniform vec2 iResolution;
809
+ uniform sampler2D iTexture;
810
+ out vec4 fragColor;
811
+ void main() {
812
+ vec2 uv = gl_FragCoord.xy / iResolution.xy;
813
+ fragColor = texture(iTexture, uv);
814
+ }`,
815
+ })
816
+ gl.texture('iTexture', 'https://...')
817
+ return <canvas ref={gl.ref} />
818
+ }
819
+ ```
820
+
821
+ </details>
822
+ </td>
823
+ <td width="0px">
824
+ <details>
825
+ <summary>
826
+
827
+ WebGPU
828
+
829
+ ---
830
+
831
+ </summary>
832
+
833
+ <!-- prettier-ignore -->
834
+ ```tsx
835
+ function Canvas() {
836
+ const gl = useGL({
837
+ isWebGL: false,
838
+ fragment: `
839
+ @group(0) @binding(0) var<uniform> iResolution: vec2f;
840
+ @group(1) @binding(0) var iSampler: sampler;
841
+ @group(1) @binding(1) var iTexture: texture_2d<f32>;
842
+ @fragment
843
+ fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
844
+ let uv = position.xy / iResolution;
845
+ return textureSample(iTexture, iSampler, uv);
846
+ }`,
847
+ })
848
+ gl.texture('iTexture', 'https://...')
849
+ return <canvas ref={gl.ref} />
850
+ }
851
+ ```
852
+
853
+ </details>
854
+ </td>
855
+ </tr>
856
+ <tr>
857
+ <td colspan="3">
858
+ <a href="https://glre.dev/docs#textures">
859
+ <img width="256px" src="./examples/docs/static/img/readme/texture.jpg" />
860
+ </a>
861
+ </td>
862
+ </tr>
863
+ </table>
864
+
865
+ ---
866
+
867
+ <table>
868
+ <tr>
869
+ <td width="100%" colspan="3">
870
+
871
+ ### [Instancing](https://glre.dev/docs#instancing)
872
+
873
+ </td>
874
+ </tr>
875
+ <tr valign="top">
876
+ <td width="1000px">
877
+ <br />
878
+
879
+ **TSL**
880
+
881
+ ---
882
+
883
+ <!-- prettier-ignore -->
884
+ ```tsx
885
+ function Canvas() {
886
+ const tri = attribute([
887
+ 0, 0.73,
888
+ -1, -1,
889
+ 1, -1
890
+ ])
891
+ const pos = instance(
892
+ Array(1000 * 2)
893
+ .fill(0)
894
+ .map(Math.random)
895
+ )
896
+ const gl = useGL({
897
+ isWebGL: true,
898
+ instanceCount: 1000,
899
+ triangleCount: 1,
900
+ vert: vec4(
901
+ tri.mul(0.05).sub(1).add(pos.mul(2)),
902
+ 0,
903
+ 1
904
+ ),
905
+ })
906
+ return <canvas ref={gl.ref} />
907
+ }
908
+ ```
909
+
910
+ </td>
911
+ <td width="0px">
912
+ <details>
913
+ <summary>
914
+
915
+ WebGL
916
+
917
+ ---
918
+
919
+ </summary>
920
+
921
+ <!-- prettier-ignore -->
922
+ ```tsx
923
+ function Canvas() {
924
+ const gl = useGL({
925
+ isWebGL: true,
926
+ instanceCount: 1000,
927
+ triangleCount: 1,
928
+ vert: `
929
+ #version 300 es
930
+ in vec2 tri;
931
+ in vec2 pos;
932
+ void main() {
933
+ gl_Position = vec4((((tri * 0.05) - 1.0) + (pos * 2.0)), 0.0, 1.0);
934
+ }`,
935
+ })
936
+ gl.attribute('tri', [
937
+ 0, 0.73,
938
+ -1, -1,
939
+ 1, -1
940
+ ])
941
+ gl.instance(
942
+ 'pos',
943
+ Array(1000 * 2)
944
+ .fill(0)
945
+ .map(Math.random)
946
+ )
947
+ return <canvas ref={gl.ref} />
948
+ }
949
+ ```
950
+
951
+ </details>
952
+ </td>
953
+ <td width="0px">
954
+ <details>
955
+ <summary>
956
+
957
+ WebGPU
958
+
959
+ ---
960
+
961
+ </summary>
962
+
963
+ <!-- prettier-ignore -->
964
+ ```tsx
965
+ function Canvas() {
966
+ const gl = useGL({
967
+ isWebGL: false,
968
+ instanceCount: 1000,
969
+ triangleCount: 1,
970
+ vert: `
971
+ struct In {
972
+ @location(0) tri: vec2f,
973
+ @location(1) pos: vec2f
974
+ }
975
+ struct Out {
976
+ @builtin(position) position: vec4f
977
+ }
978
+ @vertex
979
+ fn main(in: In) -> Out {
980
+ var out: Out;
981
+ out.position = vec4f((((in.tri * 0.05) - 1.0) + (in.pos * 2.0)), 0.0, 1.0);
982
+ return out;
983
+ }`,
984
+ })
985
+ gl.attribute('tri', [
986
+ 0, 0.73,
987
+ -1, -1,
988
+ 1, -1
989
+ ])
990
+ gl.instance(
991
+ 'pos',
992
+ Array(1000 * 2)
993
+ .fill(0)
994
+ .map(Math.random)
995
+ )
996
+ return <canvas ref={gl.ref} />
997
+ }
998
+ ```
999
+
1000
+ </details>
1001
+ </td>
1002
+ </tr>
1003
+ <tr>
1004
+ <td colspan="3">
1005
+ <a href="https://glre.dev/docs#instancing">
1006
+ <img width="256px" src="./examples/docs/static/img/readme/instancing.jpg" />
1007
+ </a>
1008
+ </td>
1009
+ </tr>
1010
+ </table>
1011
+
1012
+ ---
1013
+
1014
+ <table>
1015
+ <tr>
1016
+ <td width="100%" colspan="3">
1017
+
1018
+ ### [Computing](https://glre.dev/docs#computing)
1019
+
1020
+ </td>
1021
+ </tr>
1022
+ <tr valign="top">
1023
+ <td width="1000px">
1024
+ <br />
1025
+
1026
+ **TSL**
1027
+
1028
+ ---
1029
+
1030
+ <!-- prettier-ignore -->
1031
+ ```tsx
1032
+ function Canvas() {
1033
+ const wave = storage(float(Array(1024)), 'wave')
1034
+ const gl = useGL({
1035
+ isWebGL: true,
1036
+ compute: Scope(() => {
1037
+ If(uint(0).equal(id.x), () => {
1038
+ wave.element(id.x).assign(iMouse.x)
1039
+ }).Else(() => {
1040
+ const prev = wave.element(id.x.sub(uint(1)))
1041
+ wave.element(id.x).assign(prev)
1042
+ })
1043
+ }),
1044
+ fragment: Scope(() => {
1045
+ const x = wave
1046
+ .element(uint(uv.y.mul(1024)))
1047
+ .sub(uv.x)
1048
+ .abs()
1049
+ return vec4(
1050
+ vec3(uv.step(vec2(smoothstep(0.01, 0, x))), 0),
1051
+ 1
1052
+ )
1053
+ }),
1054
+ })
1055
+ return <canvas ref={gl.ref} />
1056
+ }
1057
+ ```
1058
+
1059
+ </td>
1060
+ <td width="0px">
1061
+ <details>
1062
+ <summary>
1063
+
1064
+ WebGL
1065
+
1066
+ ---
1067
+
1068
+ </summary>
1069
+
1070
+ <!-- prettier-ignore -->
1071
+ ```tsx
1072
+ function Canvas() {
1073
+ const wave = storage(float(Array(1024)), 'wave')
1074
+ const gl = useGL({
1075
+ isWebGL: true,
1076
+ compute: `
1077
+ #version 300 es
1078
+ precision highp float;
1079
+ uniform sampler2D wave;
1080
+ uniform vec2 iMouse;
1081
+ layout(location = 0) out vec4 _wave;
1082
+ void main() {
1083
+ if ((uint(0.0) == uvec3(uint(gl_FragCoord.y) * uint(32) + uint(gl_FragCoord.x), 0u, 0u).x)) {
1084
+ _wave = vec4(iMouse.x, 0.0, 0.0, 1.0);
1085
+ } else {
1086
+ _wave = vec4(texelFetch(wave, ivec2(int((uvec3(uint(gl_FragCoord.y) * uint(32) + uint(gl_FragCoord.x), 0u, 0u).x - uint(1.0))) % 32, int((uvec3(uint(gl_FragCoord.y) * uint(32) + uint(gl_FragCoord.x), 0u, 0u).x - uint(1.0))) / 32), 0).x, 0.0, 0.0, 1.0);
1087
+ };
1088
+ }`,
1089
+ fragment: `
1090
+ #version 300 es
1091
+ precision highp float;
1092
+ out vec4 fragColor;
1093
+ uniform vec2 iResolution;
1094
+ uniform sampler2D wave;
1095
+ void main() {
1096
+ fragColor = vec4(vec3(step((gl_FragCoord.xy / iResolution), vec2(smoothstep(0.01, 0.0, abs((texelFetch(wave, ivec2(int(uint(((gl_FragCoord.xy / iResolution).y * 1024.0))) % 32, int(uint(((gl_FragCoord.xy / iResolution).y * 1024.0))) / 32), 0).x - (gl_FragCoord.xy / iResolution).x))))), 0.0), 1.0);
1097
+ }`,
1098
+ })
1099
+ gl.storage('wave', Array(1024))
1100
+ return <canvas ref={gl.ref} />
1101
+ }
1102
+ ```
1103
+
1104
+ </details>
1105
+ </td>
1106
+ <td width="0px">
1107
+ <details>
1108
+ <summary>
1109
+
1110
+ WebGPU
1111
+
1112
+ ---
1113
+
1114
+ </summary>
1115
+
1116
+ <!-- prettier-ignore -->
1117
+ ```tsx
1118
+ function Canvas() {
1119
+ const wave = storage(float(Array(1024)), 'wave')
1120
+ const gl = useGL({
1121
+ isWebGL: false,
1122
+ compute: `
1123
+ struct In {
1124
+ @builtin(global_invocation_id) global_invocation_id: vec3u
1125
+ }
1126
+ @group(0) @binding(1) var<uniform> iMouse: vec2f;
1127
+ @group(2) @binding(0) var<storage, read_write> wave: array<f32>;
1128
+ @compute @workgroup_size(32)
1129
+ fn main(in: In) {
1130
+ if ((u32(0.0) == in.global_invocation_id.x)) {
1131
+ wave[in.global_invocation_id.x] = iMouse.x;
1132
+ } else {
1133
+ wave[in.global_invocation_id.x] = wave[in.global_invocation_id.x - u32(1.0)];
1134
+ };
1135
+ }`,
1136
+ fragment: `
1137
+ struct Out {
1138
+ @builtin(position) position: vec4f
1139
+ }
1140
+ @group(2) @binding(0) var<storage, read_write> wave: array<f32>;
1141
+ @group(0) @binding(0) var<uniform> iResolution: vec2f;
1142
+ @fragment
1143
+ fn main(out: Out) -> @location(0) vec4f {
1144
+ return vec4f(vec3f(step((out.position.xy / iResolution), vec2f(smoothstep(0.01, 0.0, abs((wave[u32(((out.position.xy / iResolution).y * 1024.0))] - (out.position.xy / iResolution).x))))), 0.0), 1.0);
1145
+ }`,
1146
+ })
1147
+ gl.storage('wave', Array(1024))
1148
+ return <canvas ref={gl.ref} />
1149
+ }
1150
+ ```
1151
+
1152
+ </details>
1153
+ </td>
1154
+ </tr>
1155
+ <tr>
1156
+ <td colspan="3">
1157
+ <a href="https://glre.dev/docs#computing">
1158
+ <img width="256px" src="./examples/docs/static/img/readme/computing.jpg" />
1159
+ </a>
1160
+ </td>
1161
+ </tr>
1162
+ </table>
1163
+
1164
+ ---
186
1165
 
187
1166
  ## Node System
188
1167
 
@@ -192,11 +1171,12 @@ Rather than traditional string-based shader composition,
192
1171
  this system materializes shaders as abstract syntax trees,
193
1172
  enabling unprecedented code mobility across WebGL2 and WebGPU architectures.
194
1173
 
1174
+ <!-- prettier-ignore -->
195
1175
  ```ts
196
1176
  // Shader logic materializes through method chaining
197
1177
  const fragment = vec4(fract(position.xy.div(iResolution)), 0, 1)
198
- .mul(uniform(brightness))
199
- .mix(texture(backgroundMap, uv()), blend)
1178
+ .mul(uniform(brightness))
1179
+ .mix(texture(backgroundMap, uv()), blend)
200
1180
  ```
201
1181
 
202
1182
  The system operates through proxy objects that capture mathematical operations
@@ -208,6 +1188,7 @@ between shader compilation and runtime execution.
208
1188
 
209
1189
  Traditional shader types dissolve into factory functions that generate node proxies:
210
1190
 
1191
+ <!-- prettier-ignore -->
211
1192
  ```ts
212
1193
  // Types emerge from function calls rather than declarations
213
1194
  const position = vec3(x, y, z) // Becomes position node
@@ -222,13 +1203,14 @@ building computation graphs that exist independently of their eventual compilati
222
1203
 
223
1204
  The `Fn` constructor dissolves function boundaries, creating reusable computation patterns:
224
1205
 
1206
+ <!-- prettier-ignore -->
225
1207
  ```ts
226
1208
  // Functions exist as first-class node compositions
227
1209
  const noise = Fn(([coord]) => {
228
- return sin(coord.x.mul(12.9898))
229
- .add(sin(coord.y.mul(78.233)))
230
- .mul(43758.5453)
231
- .fract()
1210
+ return sin(coord.x.mul(12.9898))
1211
+ .add(sin(coord.y.mul(78.233)))
1212
+ .mul(43758.5453)
1213
+ .fract()
232
1214
  })
233
1215
 
234
1216
  // Composition becomes transparent
@@ -239,17 +1221,18 @@ const surface = noise(position.xz.mul(scale)).mix(noise(position.xz.mul(scale.mu
239
1221
 
240
1222
  Traditional control structures become node compositions, eliminating imperative sequence:
241
1223
 
1224
+ <!-- prettier-ignore -->
242
1225
  ```ts
243
1226
  // Conditional logic as expression trees
244
1227
  If(height.greaterThan(waterLevel), () => {
245
- return grassTexture.sample(worldUV)
1228
+ return grassTexture.sample(worldUV)
246
1229
  }).Else(() => {
247
- return waterTexture.sample(worldUV.add(wave))
1230
+ return waterTexture.sample(worldUV.add(wave))
248
1231
  })
249
1232
 
250
1233
  // Loops decompose into iteration patterns
251
1234
  Loop(samples, ({ i }) => {
252
- accumulator.assign(accumulator.add(sample(position.add(offsets.element(i)))))
1235
+ accumulator.assign(accumulator.add(sample(position.add(offsets.element(i)))))
253
1236
  })
254
1237
  ```
255
1238
 
@@ -257,6 +1240,7 @@ Loop(samples, ({ i }) => {
257
1240
 
258
1241
  Uniforms transcend static parameter passing, becoming reactive data channels:
259
1242
 
1243
+ <!-- prettier-ignore -->
260
1244
  ```ts
261
1245
  const time = uniform(0) // Creates reactive binding
262
1246
  const amplitude = uniform(1) // Automatic GPU synchronization
@@ -272,6 +1256,7 @@ time.value = performance.now() / 1000
272
1256
 
273
1257
  Vertex attributes dissolve into data stream abstractions:
274
1258
 
1259
+ <!-- prettier-ignore -->
275
1260
  ```ts
276
1261
  // Attributes become typed data channels
277
1262
  const positions = attribute(vertexData) // Raw data binding
@@ -290,3 +1275,6 @@ const viewNormal = normals.transform(normalMatrix)
290
1275
  ## LICENSE
291
1276
 
292
1277
  ###### MIT⚾️
1278
+
1279
+ </samp>
1280
+ </strong>