shaderpad 1.0.0-beta.41 → 1.0.0-beta.42
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 +116 -56
- package/dist/chunk-5CBGNOA3.mjs +10 -0
- package/dist/chunk-5CBGNOA3.mjs.map +1 -0
- package/dist/chunk-JRSBIGBN.mjs +7 -0
- package/dist/chunk-JRSBIGBN.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/face.d.mts +1 -0
- package/dist/plugins/face.d.ts +1 -0
- package/dist/plugins/face.js +53 -76
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +51 -79
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/hands.d.mts +1 -0
- package/dist/plugins/hands.d.ts +1 -0
- package/dist/plugins/hands.js +20 -16
- package/dist/plugins/hands.js.map +1 -1
- package/dist/plugins/hands.mjs +15 -16
- package/dist/plugins/hands.mjs.map +1 -1
- package/dist/plugins/helpers.js +1 -1
- package/dist/plugins/helpers.js.map +1 -1
- package/dist/plugins/helpers.mjs +1 -1
- package/dist/plugins/helpers.mjs.map +1 -1
- package/dist/plugins/mediapipe-common.d.mts +18 -0
- package/dist/plugins/mediapipe-common.d.ts +18 -0
- package/dist/plugins/mediapipe-common.js +7 -0
- package/dist/plugins/mediapipe-common.js.map +1 -0
- package/dist/plugins/mediapipe-common.mjs +2 -0
- package/dist/plugins/mediapipe-common.mjs.map +1 -0
- package/dist/plugins/pose.d.mts +1 -0
- package/dist/plugins/pose.d.ts +1 -0
- package/dist/plugins/pose.js +54 -49
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +46 -46
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/save.d.mts +1 -1
- package/dist/plugins/save.d.ts +1 -1
- package/dist/plugins/save.js +1 -1
- package/dist/plugins/save.js.map +1 -1
- package/dist/plugins/save.mjs.map +1 -1
- package/dist/plugins/segmenter.d.mts +1 -0
- package/dist/plugins/segmenter.d.ts +1 -0
- package/dist/plugins/segmenter.js +16 -11
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +10 -10
- package/dist/plugins/segmenter.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-A3XQBYSC.mjs +0 -10
- package/dist/chunk-A3XQBYSC.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -280,7 +280,54 @@ shader.destroy(); // Clean up resources.
|
|
|
280
280
|
### Properties
|
|
281
281
|
|
|
282
282
|
- `canvas` (HTMLCanvasElement): The canvas element used for rendering
|
|
283
|
-
|
|
283
|
+
|
|
284
|
+
### Event Listeners
|
|
285
|
+
|
|
286
|
+
#### `on(event, callback)`
|
|
287
|
+
|
|
288
|
+
Register a callback for a lifecycle event.
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
shader.on('resize', (width, height) => {
|
|
292
|
+
console.log(`Canvas resized to ${width}x${height}`);
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Parameters:**
|
|
297
|
+
|
|
298
|
+
- `event` (string): The event name
|
|
299
|
+
- `callback` (Function): The callback function
|
|
300
|
+
|
|
301
|
+
#### `off(event, callback)`
|
|
302
|
+
|
|
303
|
+
Remove a previously registered callback.
|
|
304
|
+
|
|
305
|
+
**Parameters:**
|
|
306
|
+
|
|
307
|
+
- `event` (string): The event name
|
|
308
|
+
- `callback` (Function): The callback function to remove
|
|
309
|
+
|
|
310
|
+
#### Available Events
|
|
311
|
+
|
|
312
|
+
| Event | Callback Arguments | Description |
|
|
313
|
+
| ------------------- | --------------------------------------- | ------------------------------------------------ |
|
|
314
|
+
| `init` | none | Fired after initialization is complete |
|
|
315
|
+
| `resize` | `(width: number, height: number)` | Fired when the canvas element is resized |
|
|
316
|
+
| `updateResolution` | `(width: number, height: number)` | Fired when the drawing buffer resolution changes |
|
|
317
|
+
| `play` | none | Fired when the render loop starts |
|
|
318
|
+
| `pause` | none | Fired when the render loop is paused |
|
|
319
|
+
| `reset` | none | Fired when the shader is reset |
|
|
320
|
+
| `destroy` | none | Fired when the shader is destroyed |
|
|
321
|
+
| `beforeStep` | `(time: number, options?: StepOptions)` | Fired before each render step |
|
|
322
|
+
| `afterStep` | `(time: number, options?: StepOptions)` | Fired after each render step |
|
|
323
|
+
| `beforeDraw` | `(options?: StepOptions)` | Fired before each draw call |
|
|
324
|
+
| `afterDraw` | `(options?: StepOptions)` | Fired after each draw call |
|
|
325
|
+
| `initializeTexture` | `(name, source, options?)` | Fired after a texture is initialized |
|
|
326
|
+
| `initializeUniform` | `(name, type, value, options?)` | Fired after a uniform is initialized |
|
|
327
|
+
| `updateTextures` | `(updates, options?)` | Fired after textures are updated |
|
|
328
|
+
| `updateUniforms` | `(updates, options?)` | Fired after uniforms are updated |
|
|
329
|
+
|
|
330
|
+
Plugins may emit additional namespaced events (e.g., `face:ready`, `pose:results`).
|
|
284
331
|
|
|
285
332
|
## Options
|
|
286
333
|
|
|
@@ -293,10 +340,10 @@ The `canvas` option allows you to pass in an existing canvas element. If not pro
|
|
|
293
340
|
```typescript
|
|
294
341
|
const canvas = document.createElement('canvas');
|
|
295
342
|
const shader = new ShaderPad(fragmentShaderSrc, { canvas });
|
|
296
|
-
shader.
|
|
343
|
+
shader.on('resize', (width, height) => {
|
|
297
344
|
canvas.width = width;
|
|
298
345
|
canvas.height = height;
|
|
299
|
-
};
|
|
346
|
+
});
|
|
300
347
|
```
|
|
301
348
|
|
|
302
349
|
### history
|
|
@@ -352,19 +399,15 @@ const shader = new ShaderPad(fragmentShaderSrc, { debug: true });
|
|
|
352
399
|
|
|
353
400
|
### plugins
|
|
354
401
|
|
|
355
|
-
ShaderPad
|
|
402
|
+
ShaderPad adds additional functionality through plugins, which keeps bundle sizes small.
|
|
356
403
|
|
|
357
404
|
#### helpers
|
|
358
405
|
|
|
359
406
|
The `helpers` plugin provides convenience functions and constants. See [helpers.glsl](./src/plugins/helpers.glsl) for the implementation.
|
|
360
407
|
|
|
361
408
|
```typescript
|
|
362
|
-
import ShaderPad from 'shaderpad';
|
|
363
409
|
import helpers from 'shaderpad/plugins/helpers';
|
|
364
|
-
|
|
365
|
-
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
366
|
-
plugins: [helpers()],
|
|
367
|
-
});
|
|
410
|
+
const shader = new ShaderPad(fragmentShaderSrc, { plugins: [helpers()] });
|
|
368
411
|
```
|
|
369
412
|
|
|
370
413
|
**Note:** The `helpers` plugin automatically injects the `u_resolution` uniform into your shader. Do not declare it yourself.
|
|
@@ -374,9 +417,7 @@ const shader = new ShaderPad(fragmentShaderSrc, {
|
|
|
374
417
|
The `save` plugin adds a `.save()` method to the shader that saves the current frame to a PNG file. It works on desktop and mobile.
|
|
375
418
|
|
|
376
419
|
```typescript
|
|
377
|
-
import ShaderPad from 'shaderpad';
|
|
378
420
|
import save, { WithSave } from 'shaderpad/plugins/save';
|
|
379
|
-
|
|
380
421
|
const shader = new ShaderPad(fragmentShaderSrc, { plugins: [save()] }) as WithSave<ShaderPad>;
|
|
381
422
|
shader.save('filename', 'Optional mobile share text');
|
|
382
423
|
```
|
|
@@ -386,36 +427,36 @@ shader.save('filename', 'Optional mobile share text');
|
|
|
386
427
|
The `face` plugin uses [MediaPipe](https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker) to detect faces in video or image textures.
|
|
387
428
|
|
|
388
429
|
```typescript
|
|
389
|
-
import ShaderPad from 'shaderpad';
|
|
390
430
|
import face from 'shaderpad/plugins/face';
|
|
391
|
-
|
|
392
431
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
393
|
-
plugins: [
|
|
394
|
-
face({
|
|
395
|
-
textureName: 'u_webcam',
|
|
396
|
-
options: { maxFaces: 3 },
|
|
397
|
-
}),
|
|
398
|
-
],
|
|
432
|
+
plugins: [face({ textureName: 'u_webcam', options: { maxFaces: 3 } })],
|
|
399
433
|
});
|
|
400
434
|
```
|
|
401
435
|
|
|
402
436
|
**Options:**
|
|
403
437
|
|
|
404
|
-
- `
|
|
405
|
-
- `
|
|
438
|
+
- `maxFaces?: number` - Maximum faces to detect (default: 1)
|
|
439
|
+
- `history?: number` - Frames of history to store for landmarks and mask textures
|
|
440
|
+
|
|
441
|
+
**Events:**
|
|
442
|
+
|
|
443
|
+
| Event | Callback Arguments | Description |
|
|
444
|
+
| ------------- | -------------------------------- | ---------------------------------------- |
|
|
445
|
+
| `face:ready` | none | Fired when the detection model is loaded |
|
|
446
|
+
| `face:result` | `(result: FaceLandmarkerResult)` | Fired with detection results each frame |
|
|
406
447
|
|
|
407
448
|
**Uniforms:**
|
|
408
449
|
|
|
409
|
-
| Uniform | Type
|
|
410
|
-
| -------------------- |
|
|
411
|
-
| `u_maxFaces` | int
|
|
412
|
-
| `u_nFaces` | int
|
|
413
|
-
| `u_faceLandmarksTex` | sampler2D | Raw landmark data texture (use `faceLandmark()` to access) |
|
|
414
|
-
| `u_faceMask` | sampler2D | Face mask texture (R: region type, G: confidence, B: normalized face index) |
|
|
450
|
+
| Uniform | Type | Description |
|
|
451
|
+
| -------------------- | ----------------------------- | --------------------------------------------------------------------------- |
|
|
452
|
+
| `u_maxFaces` | int | Maximum number of faces to detect |
|
|
453
|
+
| `u_nFaces` | int | Current number of detected faces |
|
|
454
|
+
| `u_faceLandmarksTex` | sampler2D (or sampler2DArray) | Raw landmark data texture (use `faceLandmark()` to access) |
|
|
455
|
+
| `u_faceMask` | sampler2D (or sampler2DArray) | Face mask texture (R: region type, G: confidence, B: normalized face index) |
|
|
415
456
|
|
|
416
457
|
**Helper functions:**
|
|
417
458
|
|
|
418
|
-
All region functions return `vec2(confidence, faceIndex)`. faceIndex is 0-indexed (-1 = no face).
|
|
459
|
+
All region functions return `vec2(confidence, faceIndex)`. faceIndex is 0-indexed (-1 = no face). When `history` is enabled, all functions accept an optional `int framesAgo` parameter.
|
|
419
460
|
|
|
420
461
|
- `faceLandmark(int faceIndex, int landmarkIndex) -> vec4` - Returns landmark data as `vec4(x, y, z, visibility)`. Use `vec2(faceLandmark(...))` to get just the screen position.
|
|
421
462
|
- `leftEyebrowAt(vec2 pos) -> vec2` - Returns `vec2(1.0, faceIndex)` if position is in left eyebrow, `vec2(0.0, -1.0)` otherwise.
|
|
@@ -477,9 +518,7 @@ for (int i = 0; i < u_nFaces; ++i) {
|
|
|
477
518
|
The `pose` plugin uses [MediaPipe Pose Landmarker](https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker) to expose a flat array of 2D landmarks. Each pose contributes 39 landmarks (33 standard + 6 custom), enumerated below.
|
|
478
519
|
|
|
479
520
|
```typescript
|
|
480
|
-
import ShaderPad from 'shaderpad';
|
|
481
521
|
import pose from 'shaderpad/plugins/pose';
|
|
482
|
-
|
|
483
522
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
484
523
|
plugins: [pose({ textureName: 'u_video', options: { maxPoses: 3 } })],
|
|
485
524
|
});
|
|
@@ -487,20 +526,29 @@ const shader = new ShaderPad(fragmentShaderSrc, {
|
|
|
487
526
|
|
|
488
527
|
**Options:**
|
|
489
528
|
|
|
490
|
-
- `
|
|
491
|
-
- `
|
|
529
|
+
- `maxPoses?: number` - Maximum poses to detect (default: 1)
|
|
530
|
+
- `history?: number` - Frames of history to store for landmarks and mask textures
|
|
531
|
+
|
|
532
|
+
**Events:**
|
|
533
|
+
|
|
534
|
+
| Event | Callback Arguments | Description |
|
|
535
|
+
| ------------- | -------------------------------- | ---------------------------------------- |
|
|
536
|
+
| `pose:ready` | none | Fired when the detection model is loaded |
|
|
537
|
+
| `pose:result` | `(result: PoseLandmarkerResult)` | Fired with detection results each frame |
|
|
492
538
|
|
|
493
539
|
**Uniforms:**
|
|
494
540
|
|
|
495
|
-
| Uniform | Type
|
|
496
|
-
| -------------------- |
|
|
497
|
-
| `u_maxPoses` | int
|
|
498
|
-
| `u_nPoses` | int
|
|
499
|
-
| `u_poseLandmarksTex` | sampler2D | Raw landmark data texture (RGBA: x, y, z, visibility) |
|
|
500
|
-
| `u_poseMask` | sampler2D | Pose mask texture (R: body detected, G: confidence, B: normalized pose index) |
|
|
541
|
+
| Uniform | Type | Description |
|
|
542
|
+
| -------------------- | ----------------------------- | ----------------------------------------------------------------------------- |
|
|
543
|
+
| `u_maxPoses` | int | Maximum number of poses to track |
|
|
544
|
+
| `u_nPoses` | int | Current number of detected poses |
|
|
545
|
+
| `u_poseLandmarksTex` | sampler2D (or sampler2DArray) | Raw landmark data texture (RGBA: x, y, z, visibility) |
|
|
546
|
+
| `u_poseMask` | sampler2D (or sampler2DArray) | Pose mask texture (R: body detected, G: confidence, B: normalized pose index) |
|
|
501
547
|
|
|
502
548
|
**Helper functions:**
|
|
503
549
|
|
|
550
|
+
When `history` is enabled, all functions accept an optional `int framesAgo` parameter.
|
|
551
|
+
|
|
504
552
|
- `poseLandmark(int poseIndex, int landmarkIndex) -> vec4` - Returns landmark data as `vec4(x, y, z, visibility)`. Use `vec2(poseLandmark(...))` to get just the screen position.
|
|
505
553
|
- `poseAt(vec2 pos) -> vec2` - Returns `vec2(confidence, poseIndex)`. poseIndex is 0-indexed (-1 = no pose), confidence is the segmentation confidence.
|
|
506
554
|
- `inPose(vec2 pos) -> float` - Returns `1.0` if position is in any pose, `0.0` otherwise.
|
|
@@ -571,9 +619,7 @@ for (int i = 0; i < u_maxPoses; ++i) {
|
|
|
571
619
|
The `hands` plugin uses [MediaPipe Hand Landmarker](https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker) to expose a flat array of 2D landmarks. Each hand contributes 22 landmarks, enumerated below.
|
|
572
620
|
|
|
573
621
|
```typescript
|
|
574
|
-
import ShaderPad from 'shaderpad';
|
|
575
622
|
import hands from 'shaderpad/plugins/hands';
|
|
576
|
-
|
|
577
623
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
578
624
|
plugins: [hands({ textureName: 'u_video', options: { maxHands: 2 } })],
|
|
579
625
|
});
|
|
@@ -581,19 +627,28 @@ const shader = new ShaderPad(fragmentShaderSrc, {
|
|
|
581
627
|
|
|
582
628
|
**Options:**
|
|
583
629
|
|
|
584
|
-
- `
|
|
585
|
-
- `
|
|
630
|
+
- `maxHands?: number` - Maximum hands to detect (default: 2)
|
|
631
|
+
- `history?: number` - Frames of history to store for landmarks texture
|
|
632
|
+
|
|
633
|
+
**Events:**
|
|
634
|
+
|
|
635
|
+
| Event | Callback Arguments | Description |
|
|
636
|
+
| -------------- | -------------------------------- | ---------------------------------------- |
|
|
637
|
+
| `hands:ready` | none | Fired when the detection model is loaded |
|
|
638
|
+
| `hands:result` | `(result: HandLandmarkerResult)` | Fired with detection results each frame |
|
|
586
639
|
|
|
587
640
|
**Uniforms:**
|
|
588
641
|
|
|
589
|
-
| Uniform | Type
|
|
590
|
-
| -------------------- |
|
|
591
|
-
| `u_maxHands` | int
|
|
592
|
-
| `u_nHands` | int
|
|
593
|
-
| `u_handLandmarksTex` | sampler2D | Raw landmark data texture (RGBA: x, y, z, handedness) |
|
|
642
|
+
| Uniform | Type | Description |
|
|
643
|
+
| -------------------- | ----------------------------- | ----------------------------------------------------- |
|
|
644
|
+
| `u_maxHands` | int | Maximum number of hands to track |
|
|
645
|
+
| `u_nHands` | int | Current number of detected hands |
|
|
646
|
+
| `u_handLandmarksTex` | sampler2D (or sampler2DArray) | Raw landmark data texture (RGBA: x, y, z, handedness) |
|
|
594
647
|
|
|
595
648
|
**Helper functions:**
|
|
596
649
|
|
|
650
|
+
When `history` is enabled, all functions accept an optional `int framesAgo` parameter.
|
|
651
|
+
|
|
597
652
|
- `handLandmark(int handIndex, int landmarkIndex) -> vec4` - Returns landmark data as `vec4(x, y, z, handedness)`. Use `vec2(handLandmark(...))` to get just the screen position. Handedness: 0.0 = left hand, 1.0 = right hand.
|
|
598
653
|
- `isRightHand(int handIndex) -> float` - Returns 1.0 if the hand is a right hand, 0.0 if left.
|
|
599
654
|
- `isLeftHand(int handIndex) -> float` - Returns 1.0 if the hand is a left hand, 0.0 if right.
|
|
@@ -655,9 +710,6 @@ const shader = new ShaderPad(fragmentShaderSrc, {
|
|
|
655
710
|
modelPath:
|
|
656
711
|
'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_multiclass_256x256/float32/latest/selfie_multiclass_256x256.tflite',
|
|
657
712
|
outputCategoryMask: true,
|
|
658
|
-
onReady: () => {
|
|
659
|
-
console.log('Selfie multiclass model: loading complete');
|
|
660
|
-
},
|
|
661
713
|
},
|
|
662
714
|
}),
|
|
663
715
|
],
|
|
@@ -666,18 +718,26 @@ const shader = new ShaderPad(fragmentShaderSrc, {
|
|
|
666
718
|
|
|
667
719
|
**Options:**
|
|
668
720
|
|
|
669
|
-
- `
|
|
670
|
-
|
|
721
|
+
- `history?: number` - Frames of history to store for mask texture
|
|
722
|
+
|
|
723
|
+
**Events:**
|
|
724
|
+
|
|
725
|
+
| Event | Callback Arguments | Description |
|
|
726
|
+
| ------------------ | -------------------------------- | ------------------------------------------- |
|
|
727
|
+
| `segmenter:ready` | none | Fired when the segmentation model is loaded |
|
|
728
|
+
| `segmenter:result` | `(result: ImageSegmenterResult)` | Fired with segmentation results each frame |
|
|
671
729
|
|
|
672
730
|
**Uniforms:**
|
|
673
731
|
|
|
674
|
-
| Uniform | Type
|
|
675
|
-
| ----------------- |
|
|
676
|
-
| `u_segmentMask` | sampler2D | Segment mask texture (R: normalized category, G: confidence, B: unused) |
|
|
677
|
-
| `u_numCategories` | int
|
|
732
|
+
| Uniform | Type | Description |
|
|
733
|
+
| ----------------- | ----------------------------- | ----------------------------------------------------------------------- |
|
|
734
|
+
| `u_segmentMask` | sampler2D (or sampler2DArray) | Segment mask texture (R: normalized category, G: confidence, B: unused) |
|
|
735
|
+
| `u_numCategories` | int | Number of segmentation categories (including background) |
|
|
678
736
|
|
|
679
737
|
**Helper functions:**
|
|
680
738
|
|
|
739
|
+
When `history` is enabled, all functions accept an optional `int framesAgo` parameter.
|
|
740
|
+
|
|
681
741
|
- `segmentAt(vec2 pos) -> vec2` - Returns `vec2(confidence, categoryIndex)`. categoryIndex is 0-indexed (-1 = background). confidence is the segmentation confidence (0-1).
|
|
682
742
|
|
|
683
743
|
**Example usage:**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var F=`#version 300 es
|
|
2
|
+
in vec2 aPosition;
|
|
3
|
+
out vec2 v_uv;
|
|
4
|
+
void main() {
|
|
5
|
+
v_uv = aPosition * 0.5 + 0.5;
|
|
6
|
+
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
7
|
+
}`,w=33.333333333333336,L=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),v=Symbol("u_history"),b=Symbol("__SHADERPAD_BUFFER");function A(a,e){if(!e?.length)return a;let t=a.split(`
|
|
8
|
+
`),s=t.findLastIndex(i=>{let r=i.trimStart();return r.startsWith("precision ")||r.startsWith("#version ")})+1;return t.splice(s,0,...e),t.join(`
|
|
9
|
+
`)}function y(a){return a instanceof WebGLTexture?{width:0,height:0}:a instanceof E?{width:a.canvas.width,height:a.canvas.height}:a instanceof HTMLVideoElement?{width:a.videoWidth,height:a.videoHeight}:a instanceof HTMLImageElement?{width:a.naturalWidth??a.width,height:a.naturalHeight??a.height}:{width:a.width,height:a.height}}function x(a){return typeof a=="symbol"?a.description??"":a}var E=class a{isInternalCanvas=!1;isTouchDevice=!1;gl;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;aPositionLocation=0;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;hooks=new Map;historyDepth=0;textureOptions;debug;intermediateFbo=null;constructor(e,{canvas:t,plugins:s,history:i,debug:r,...o}={}){if(this.canvas=t||document.createElement("canvas"),!t){this.isInternalCanvas=!0;let f=this.canvas;f.style.position="fixed",f.style.inset="0",f.style.height="100dvh",f.style.width="100dvw",document.body.appendChild(f)}if(this.canvas instanceof OffscreenCanvas){let f=d=>{let g=Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype,d);Object.defineProperty(this.canvas,d,{get:()=>g.get.call(this.canvas),set:R=>{g.set.call(this.canvas,R),this.updateResolution()},configurable:g.configurable,enumerable:g.enumerable})};f("width"),f("height")}let n=this.canvas.getContext("webgl2",{antialias:!1});if(!n)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.gl=n,this.textureUnitPool={free:[],next:0,max:n.getParameter(n.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.textureOptions=o;let{internalFormat:h,type:c}=o;(c===n.FLOAT||c===n.HALF_FLOAT||h===n.RGBA16F||h===n.RGBA32F||h===n.R16F||h===n.R32F||h===n.RG16F||h===n.RG32F)&&!n.getExtension("EXT_color_buffer_float")&&(console.warn("EXT_color_buffer_float not supported, falling back to RGBA8"),delete this.textureOptions?.internalFormat,delete this.textureOptions?.format,delete this.textureOptions?.type),i&&(this.historyDepth=i),this.debug=r??(typeof process<"u"&&!1),this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let m=[];s&&s.forEach(f=>f(this,{gl:n,canvas:this.canvas,injectGLSL:d=>{m.push(d)},emitHook:this.emitHook.bind(this)}));let u=this.gl.createProgram();if(!u)throw new Error("Failed to create WebGL program");this.program=u;let p=this.createShader(this.gl.VERTEX_SHADER,F),T=this.createShader(n.FRAGMENT_SHADER,A(e,m));if(n.attachShader(u,p),n.attachShader(u,T),n.linkProgram(u),n.deleteShader(p),n.deleteShader(T),!n.getProgramParameter(u,n.LINK_STATUS))throw console.error("Program link error:",n.getProgramInfoLog(u)),n.deleteProgram(u),new Error("Failed to link WebGL program");this.aPositionLocation=n.getAttribLocation(u,"aPosition"),this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.buffer),n.bufferData(n.ARRAY_BUFFER,L,n.STATIC_DRAW),n.viewport(0,0,n.drawingBufferWidth,n.drawingBufferHeight),n.enableVertexAttribArray(this.aPositionLocation),n.vertexAttribPointer(this.aPositionLocation,2,n.FLOAT,!1,0,0),n.useProgram(u),this.canvas instanceof HTMLCanvasElement&&(this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas)),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this._initializeTexture(b,this.canvas,{...this.textureOptions}),this.intermediateFbo=n.createFramebuffer(),this.historyDepth>0&&this._initializeTexture(v,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners(),this.emitHook("init")}emitHook(e,...t){this.hooks.get(e)?.forEach(s=>s.call(this,...t))}on(e,t){this.hooks.has(e)||this.hooks.set(e,[]),this.hooks.get(e).push(t)}off(e,t){let s=this.hooks.get(e);s&&s.splice(s.indexOf(t),1)}createShader(e,t){let s=this.gl.createShader(e);if(this.gl.shaderSource(s,t),this.gl.compileShader(s),!this.gl.getShaderParameter(s,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",t),console.error(this.gl.getShaderInfoLog(s)),this.gl.deleteShader(s),new Error("Shader compilation failed");return s}throttledHandleResize(){clearTimeout(this.resizeTimeout);let e=performance.now(),t=this.lastResizeTime+w-e;t<=0?(this.lastResizeTime=e,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),t)}handleResize(){if(!(this.canvas instanceof HTMLCanvasElement))return;let e=window.devicePixelRatio||1,t=this.canvas.clientWidth*e,s=this.canvas.clientHeight*e;this.isInternalCanvas&&(this.canvas.width!==t||this.canvas.height!==s)&&(this.canvas.width=t,this.canvas.height=s),this.emitHook("resize",t,s)}addEventListeners(){let e=this.canvas,t=(i,r)=>{if(!this.uniforms.has("u_cursor"))return;let o=e.getBoundingClientRect();this.cursorPosition[0]=(i-o.left)/o.width,this.cursorPosition[1]=1-(r-o.top)/o.height,this.updateUniforms({u_cursor:this.cursorPosition})},s=(i,r,o)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let n=e.getBoundingClientRect(),h=r,c=o;this.clickPosition[0]=(h-n.left)/n.width,this.clickPosition[1]=1-(c-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let r=i;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",i=>{let r=i;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,s(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",i=>{let r=i;this.isTouchDevice||r.button===0&&s(!1)}),this.eventListeners.set("touchmove",i=>{let r=i;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let r=i;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),s(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",i=>{i.touches.length===0&&s(!1)}),this.eventListeners.forEach((i,r)=>{e.addEventListener(r,i)})}updateResolution(){let e=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...e),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:e}):this.initializeUniform("u_resolution","float",e),this.resizeTexture(b,...e),this.historyDepth>0&&this.resizeTexture(v,...e),this.emitHook("updateResolution",...e)}resizeTexture(e,t,s){let i=this.textures.get(e);if(!i||i.width===t&&i.height===s)return;this.gl.deleteTexture(i.texture),i.width=t,i.height=s;let{texture:r}=this.createTexture(e,i);i.texture=r,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(e){let t=this.textures.get(e);if(t)return t.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(e){let t=this.textures.get(e);t&&this.textureUnitPool.free.push(t.unitIndex)}resolveTextureOptions(e){let{gl:t}=this,s=e?.type??t.UNSIGNED_BYTE;return{type:s,format:e?.format??t.RGBA,internalFormat:e?.internalFormat??(s===t.FLOAT?t.RGBA32F:s===t.HALF_FLOAT?t.RGBA16F:t.RGBA8),minFilter:e?.minFilter??t.LINEAR,magFilter:e?.magFilter??t.LINEAR,wrapS:e?.wrapS??t.CLAMP_TO_EDGE,wrapT:e?.wrapT??t.CLAMP_TO_EDGE,preserveY:e?.preserveY}}getPixelArray(e,t){return e===this.gl.FLOAT?new Float32Array(t):e===this.gl.HALF_FLOAT?new Uint16Array(t):new Uint8Array(t)}clearHistoryTextureLayers(e){if(!e.history)return;let t=this.gl,{type:s,format:i}=e.options,r=this.getPixelArray(s,e.width*e.height*4);t.activeTexture(t.TEXTURE0+e.unitIndex),t.bindTexture(t.TEXTURE_2D_ARRAY,e.texture);for(let o=0;o<e.history.depth;++o)t.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,o,e.width,e.height,1,i,s,r)}initializeUniform(e,t,s,i){let r=i?.arrayLength;if(this.uniforms.has(e))throw new Error(`${e} is already initialized.`);if(t!=="float"&&t!=="int")throw new Error(`Invalid uniform type: ${t}. Expected 'float' or 'int'.`);if(r&&!(Array.isArray(s)&&s.length===r))throw new Error(`${e} array length mismatch: must initialize with ${r} elements.`);let o=this.gl.getUniformLocation(this.program,e);if(!o&&r&&(o=this.gl.getUniformLocation(this.program,`${e}[0]`)),!o){this.log(`${e} not in shader. Skipping initialization.`);return}let n=r?s[0]:s,h=Array.isArray(n)?n.length:1;this.uniforms.set(e,{type:t,length:h,location:o,arrayLength:r});try{this.updateUniforms({[e]:s})}catch(c){throw this.uniforms.delete(e),c}this.emitHook("initializeUniform",...arguments)}log(...e){this.debug&&console.debug(...e)}updateUniforms(e,t){this.gl.useProgram(this.program),Object.entries(e).forEach(([s,i])=>{let r=this.uniforms.get(s);if(!r){this.log(`${s} not in shader. Skipping update.`);return}let o=`uniform${r.length}${r.type.charAt(0)}`;if(r.arrayLength){if(!Array.isArray(i))throw new Error(`${s} is an array, but the value passed to updateUniforms is not an array.`);let n=i.length;if(!n)return;if(n>r.arrayLength)throw new Error(`${s} received ${n} values, but maximum length is ${r.arrayLength}.`);if(i.some(l=>(Array.isArray(l)?l.length:1)!==r.length))throw new Error(`Tried to update ${s} with some elements that are not length ${r.length}.`);let h=new(r.type==="float"?Float32Array:Int32Array)(i.flat()),c=r.location;if(t?.startIndex){let l=this.gl.getUniformLocation(this.program,`${s}[${t.startIndex}]`);if(!l)throw new Error(`${s}[${t.startIndex}] not in shader. Did you pass an invalid startIndex?`);c=l}this.gl[o+"v"](c,h)}else{if(Array.isArray(i)||(i=[i]),i.length!==r.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${r.length}.`);this.gl[o](r.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(e,t){let{width:s,height:i}=t,r=t.history?.depth??0,o=this.gl.createTexture();if(!o)throw new Error("Failed to create texture");let n=t.unitIndex;if(typeof n!="number")try{n=this.reserveTextureUnit(e)}catch(m){throw this.gl.deleteTexture(o),m}let h=r>0,c=h?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:l}=t;return this.gl.activeTexture(this.gl.TEXTURE0+n),this.gl.bindTexture(c,o),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_S,l.wrapS),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_T,l.wrapT),this.gl.texParameteri(c,this.gl.TEXTURE_MIN_FILTER,l.minFilter),this.gl.texParameteri(c,this.gl.TEXTURE_MAG_FILTER,l.magFilter),h?this.gl.texStorage3D(c,1,l.internalFormat,s,i,r):e===b&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,l.internalFormat,s,i,0,l.format,l.type,null),{texture:o,unitIndex:n}}_initializeTexture(e,t,s){if(this.textures.has(e))throw new Error(`Texture '${x(e)}' is already initialized.`);let{history:i=0,...r}=s??{},{width:o,height:n}=y(t);if(!o||!n)throw new Error("Texture source must have valid dimensions");let h={width:o,height:n,options:this.resolveTextureOptions(r)};i>0&&(h.history={depth:i,writeIndex:0});let{texture:c,unitIndex:l}=this.createTexture(e,h),m={texture:c,unitIndex:l,...h};i>0&&(this.initializeUniform(`${x(e)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(m)),this.textures.set(e,m),this.updateTexture(e,t);let u=this.gl.getUniformLocation(this.program,x(e));u&&this.gl.uniform1i(u,l)}initializeTexture(e,t,s){this._initializeTexture(e,t,s),this.emitHook("initializeTexture",...arguments)}updateTextures(e,t){Object.entries(e).forEach(([s,i])=>{this.updateTexture(s,i,t)}),this.emitHook("updateTextures",...arguments)}updateTexture(e,t,s){let i=this.textures.get(e);if(!i)throw new Error(`Texture '${x(e)}' is not initialized.`);if(t instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,t);return}let r=t;if(t instanceof a){let u=t.textures.get(b);if(t.gl===this.gl){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,u.texture);return}let{width:p,height:T,options:{format:f,type:d}}=u,g=this.getPixelArray(d,p*T*4);t.gl.bindFramebuffer(t.gl.FRAMEBUFFER,t.intermediateFbo),t.gl.readPixels(0,0,p,T,f,d,g),t.gl.bindFramebuffer(t.gl.FRAMEBUFFER,null),r={data:g,width:p,height:T}}let{width:o,height:n}=y(r);if(!o||!n)return;let h="isPartial"in r&&r.isPartial;h||this.resizeTexture(e,o,n);let l=!("data"in r&&r.data)&&!i.options?.preserveY,m=this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);if(i.history){if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture),!s?.skipHistoryWrite){this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l),this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,i.history.writeIndex,o,n,1,i.options.format,i.options.type,r.data??r),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,m);let u=`${x(e)}FrameOffset`;this.updateUniforms({[u]:i.history.writeIndex}),i.history.writeIndex=(i.history.writeIndex+1)%i.history.depth}}else{if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,i.texture),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l),h){let u=r;this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,u.x??0,u.y??0,o,n,i.options.format,i.options.type,u.data)}else this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,o,n,0,i.options.format,i.options.type,r.data??r);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,m)}}draw(e){this.emitHook("beforeDraw",...arguments);let t=this.gl,s=t.drawingBufferWidth,i=t.drawingBufferHeight,r=this.textures.get(b);t.bindFramebuffer(t.FRAMEBUFFER,this.intermediateFbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,r.texture,0),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.buffer),t.vertexAttribPointer(this.aPositionLocation,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(this.aPositionLocation),t.viewport(0,0,s,i),e?.skipClear||t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6);let o=this.textures.get(v);o&&!e?.skipHistoryWrite&&(t.bindTexture(t.TEXTURE_2D_ARRAY,o.texture),t.copyTexSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,o.history.writeIndex,0,0,s,i)),t.bindFramebuffer(t.READ_FRAMEBUFFER,this.intermediateFbo),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,null),t.blitFramebuffer(0,0,s,i,0,0,s,i,t.COLOR_BUFFER_BIT,t.NEAREST),t.bindFramebuffer(t.FRAMEBUFFER,null),this.emitHook("afterDraw",...arguments)}step(e,t){this.emitHook("beforeStep",...arguments);let s={};this.uniforms.has("u_time")&&(s.u_time=e),this.uniforms.has("u_frame")&&(s.u_frame=this.frame),this.updateUniforms(s),this.draw(t);let i=this.textures.get(v);if(i&&!t?.skipHistoryWrite){let{writeIndex:r,depth:o}=i.history;this.updateUniforms({[`${x(v)}FrameOffset`]:r}),i.history.writeIndex=(r+1)%o}++this.frame,this.emitHook("afterStep",...arguments)}play(e,t){this.pause();let s=i=>{i=(i-this.startTime)/1e3;let r=t?.(i,this.frame)??void 0;this.step(i,r),this.animationFrameId=requestAnimationFrame(s),e?.(i,this.frame)};this.animationFrameId=requestAnimationFrame(s),this.emitHook("play")}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.emitHook("pause")}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(e=>{e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}),this.emitHook("reset")}destroy(){this.emitHook("destroy"),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.canvas instanceof HTMLCanvasElement&&this.eventListeners.forEach((e,t)=>{this.canvas.removeEventListener(t,e)}),this.program&&this.gl.deleteProgram(this.program),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(e=>{this.gl.deleteTexture(e.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas instanceof HTMLCanvasElement&&this.canvas.remove()}},_=E;export{_ as a};
|
|
10
|
+
//# sourceMappingURL=chunk-5CBGNOA3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\nconst QUAD_VERTICES = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\nexport interface TextureOptions {\n\tinternalFormat?: number;\n\tformat?: number;\n\ttype?: number;\n\tminFilter?: number;\n\tmagFilter?: number;\n\twrapS?: number;\n\twrapT?: number;\n\tpreserveY?: boolean;\n}\ntype ResolvedTextureOptions = Required<Omit<TextureOptions, 'preserveY'>> & Pick<TextureOptions, 'preserveY'>;\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n\twidth: number;\n\theight: number;\n\thistory?: {\n\t\tdepth: number;\n\t\twriteIndex: number;\n\t};\n\toptions: ResolvedTextureOptions;\n}\n\nexport interface CustomTexture {\n\tdata: ArrayBufferView | null;\n\twidth: number;\n\theight: number;\n}\n\nexport interface PartialCustomTexture extends CustomTexture {\n\tisPartial?: boolean;\n\tx?: number;\n\ty?: number;\n}\n\nexport type TextureSource =\n\t| HTMLImageElement\n\t| HTMLVideoElement\n\t| HTMLCanvasElement\n\t| OffscreenCanvas\n\t| ImageBitmap\n\t| WebGLTexture\n\t| CustomTexture\n\t| ShaderPad;\n\n// Custom textures allow partial updates starting from (x, y).\ntype UpdateTextureSource = Exclude<TextureSource, CustomTexture> | PartialCustomTexture;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tcanvas: HTMLCanvasElement | OffscreenCanvas;\n\tinjectGLSL: (code: string) => void;\n\temitHook: (name: LifecycleMethod, ...args: any[]) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'initializeTexture'\n\t| 'initializeUniform'\n\t| 'updateTextures'\n\t| 'updateUniforms'\n\t| 'beforeStep'\n\t| 'afterStep'\n\t| 'beforeDraw'\n\t| 'afterDraw'\n\t| 'updateResolution'\n\t| 'resize'\n\t| 'play'\n\t| 'pause'\n\t| 'reset'\n\t| 'destroy'\n\t| `${string}:${string}`;\n\nexport interface Options extends Exclude<TextureOptions, 'preserveY'> {\n\tcanvas?: HTMLCanvasElement | OffscreenCanvas | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n\tdebug?: boolean;\n}\n\nexport interface StepOptions {\n\tskipClear?: boolean;\n\tskipHistoryWrite?: boolean;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\nconst INTERMEDIATE_TEXTURE_KEY = Symbol('__SHADERPAD_BUFFER');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource): { width: number; height: number } {\n\tif (source instanceof WebGLTexture) {\n\t\treturn { width: 0, height: 0 }; // Invalid - dimensions not readable.\n\t}\n\tif (source instanceof ShaderPad) {\n\t\treturn { width: source.canvas.width, height: source.canvas.height };\n\t}\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t}\n\tif (source instanceof HTMLImageElement) {\n\t\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n\t}\n\t// CustomTexture, HTMLCanvasElement, OffscreenCanvas, ImageBitmap.\n\treturn { width: source.width, height: source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate aPositionLocation = 0;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement | OffscreenCanvas;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth = 0;\n\tprivate textureOptions: TextureOptions;\n\tprivate debug: boolean;\n\t// WebGL can’t read from and write to the history texture at the same time.\n\t// We write to an intermediate texture then blit to the history texture.\n\tprivate intermediateFbo: WebGLFramebuffer | null = null;\n\n\tconstructor(fragmentShaderSrc: string, { canvas, plugins, history, debug, ...textureOptions }: Options = {}) {\n\t\tthis.canvas = canvas || document.createElement('canvas');\n\t\tif (!canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\t\thtmlCanvas.style.position = 'fixed';\n\t\t\thtmlCanvas.style.inset = '0';\n\t\t\thtmlCanvas.style.height = '100dvh';\n\t\t\thtmlCanvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(htmlCanvas);\n\t\t}\n\t\tif (this.canvas instanceof OffscreenCanvas) {\n\t\t\tconst wrapDimension = (dimension: 'width' | 'height') => {\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype, dimension)!;\n\t\t\t\tObject.defineProperty(this.canvas, dimension, {\n\t\t\t\t\tget: () => descriptor.get!.call(this.canvas),\n\t\t\t\t\tset: v => {\n\t\t\t\t\t\tdescriptor.set!.call(this.canvas, v);\n\t\t\t\t\t\tthis.updateResolution();\n\t\t\t\t\t},\n\t\t\t\t\tconfigurable: descriptor.configurable,\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t});\n\t\t\t};\n\t\t\twrapDimension('width');\n\t\t\twrapDimension('height');\n\t\t}\n\n\t\tconst gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.textureOptions = textureOptions;\n\n\t\tconst { internalFormat, type } = textureOptions;\n\t\tconst isFloatFormat =\n\t\t\ttype === gl.FLOAT ||\n\t\t\ttype === gl.HALF_FLOAT ||\n\t\t\tinternalFormat === gl.RGBA16F ||\n\t\t\tinternalFormat === gl.RGBA32F ||\n\t\t\tinternalFormat === gl.R16F ||\n\t\t\tinternalFormat === gl.R32F ||\n\t\t\tinternalFormat === gl.RG16F ||\n\t\t\tinternalFormat === gl.RG32F;\n\t\tif (isFloatFormat && !gl.getExtension('EXT_color_buffer_float')) {\n\t\t\tconsole.warn('EXT_color_buffer_float not supported, falling back to RGBA8');\n\t\t\tdelete this.textureOptions?.internalFormat;\n\t\t\tdelete this.textureOptions?.format;\n\t\t\tdelete this.textureOptions?.type;\n\t\t}\n\n\t\tif (history) this.historyDepth = history;\n\t\tthis.debug = debug ?? (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (plugins) {\n\t\t\tplugins.forEach(plugin =>\n\t\t\t\tplugin(this, {\n\t\t\t\t\tgl,\n\t\t\t\t\tcanvas: this.canvas,\n\t\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t\t},\n\t\t\t\t\temitHook: this.emitHook.bind(this),\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tconst program = this.gl.createProgram();\n\t\tif (!program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tthis.program = program;\n\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, DEFAULT_VERTEX_SHADER_SRC);\n\t\tconst fragmentShader = this.createShader(\n\t\t\tgl.FRAGMENT_SHADER,\n\t\t\tcombineShaderCode(fragmentShaderSrc, glslInjections)\n\t\t);\n\t\tgl.attachShader(program, vertexShader);\n\t\tgl.attachShader(program, fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tgl.deleteShader(vertexShader);\n\t\tgl.deleteShader(fragmentShader);\n\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', gl.getProgramInfoLog(program));\n\t\t\tgl.deleteProgram(program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tthis.aPositionLocation = gl.getAttribLocation(program, 'aPosition');\n\t\tthis.buffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW);\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.useProgram(program);\n\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\t\tthis.resizeObserver.observe(this.canvas);\n\t\t}\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\n\t\tthis._initializeTexture(INTERMEDIATE_TEXTURE_KEY, this.canvas, {\n\t\t\t...this.textureOptions,\n\t\t});\n\t\tthis.intermediateFbo = gl.createFramebuffer();\n\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, {\n\t\t\t\thistory: this.historyDepth,\n\t\t\t\t...this.textureOptions,\n\t\t\t});\n\t\t}\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t\tthis.emitHook('init');\n\t}\n\n\tprivate emitHook(name: LifecycleMethod, ...args: any[]) {\n\t\tthis.hooks.get(name)?.forEach(hook => hook.call(this, ...args));\n\t}\n\n\ton(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\toff(name: LifecycleMethod, fn: Function) {\n\t\tconst hooks = this.hooks.get(name);\n\t\tif (hooks) {\n\t\t\thooks.splice(hooks.indexOf(fn), 1);\n\t\t}\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tif (!(this.canvas instanceof HTMLCanvasElement)) return;\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.emitHook('resize', width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\thtmlCanvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.resizeTexture(INTERMEDIATE_TEXTURE_KEY, ...resolution);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis.resizeTexture(HISTORY_TEXTURE_KEY, ...resolution);\n\t\t}\n\t\tthis.emitHook('updateResolution', ...resolution);\n\t}\n\n\tprivate resizeTexture(name: string | symbol, width: number, height: number) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info || (info.width === width && info.height === height)) return;\n\n\t\tthis.gl.deleteTexture(info.texture);\n\t\tinfo.width = width;\n\t\tinfo.height = height;\n\t\tconst { texture } = this.createTexture(name, info);\n\t\tinfo.texture = texture;\n\t\tif (info.history) {\n\t\t\tinfo.history.writeIndex = 0;\n\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t}\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate resolveTextureOptions(options?: TextureOptions): ResolvedTextureOptions {\n\t\tconst { gl } = this;\n\t\tconst type = options?.type ?? gl.UNSIGNED_BYTE;\n\t\treturn {\n\t\t\ttype,\n\t\t\tformat: options?.format ?? gl.RGBA,\n\t\t\tinternalFormat:\n\t\t\t\toptions?.internalFormat ??\n\t\t\t\t(type === gl.FLOAT ? gl.RGBA32F : type === gl.HALF_FLOAT ? gl.RGBA16F : gl.RGBA8),\n\t\t\tminFilter: options?.minFilter ?? gl.LINEAR,\n\t\t\tmagFilter: options?.magFilter ?? gl.LINEAR,\n\t\t\twrapS: options?.wrapS ?? gl.CLAMP_TO_EDGE,\n\t\t\twrapT: options?.wrapT ?? gl.CLAMP_TO_EDGE,\n\t\t\tpreserveY: options?.preserveY,\n\t\t};\n\t}\n\n\tprivate getPixelArray(type: number, size: number): ArrayBufferView {\n\t\treturn type === this.gl.FLOAT\n\t\t\t? new Float32Array(size)\n\t\t\t: type === this.gl.HALF_FLOAT\n\t\t\t? new Uint16Array(size)\n\t\t\t: new Uint8Array(size);\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst gl = this.gl;\n\t\tconst { type, format } = textureInfo.options;\n\t\tconst transparent = this.getPixelArray(type, textureInfo.width * textureInfo.height * 4);\n\t\tgl.activeTexture(gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tgl.texSubImage3D(\n\t\t\t\tgl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\tformat,\n\t\t\t\ttype,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tthis.log(`${name} not in shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.emitHook('initializeUniform', ...arguments);\n\t}\n\n\tprivate log(...args: any[]) {\n\t\tif (this.debug) console.debug(...args);\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tthis.gl.useProgram(this.program);\n\t\tObject.entries(updates).forEach(([name, newValue]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tthis.log(`${name} not in shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(newValue)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = newValue.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (newValue.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(newValue.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not in shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(newValue)) newValue = [newValue];\n\t\t\t\tif (newValue.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${newValue.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...newValue);\n\t\t\t}\n\t\t});\n\t\tthis.emitHook('updateUniforms', ...arguments);\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history' | 'options'> & { unitIndex?: number }\n\t) {\n\t\tconst { width, height } = textureInfo;\n\t\tconst historyDepth = textureInfo.history?.depth ?? 0;\n\n\t\tconst texture = this.gl.createTexture();\n\t\tif (!texture) {\n\t\t\tthrow new Error('Failed to create texture');\n\t\t}\n\n\t\tlet unitIndex = textureInfo.unitIndex;\n\t\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\t\tconst { options } = textureInfo;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, options.wrapS);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, options.wrapT);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, options.minFilter);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, options.magFilter);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, options.internalFormat, width, height, historyDepth);\n\t\t} else if (name === INTERMEDIATE_TEXTURE_KEY) {\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\toptions.internalFormat,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\t0,\n\t\t\t\toptions.format,\n\t\t\t\toptions.type,\n\t\t\t\tnull\n\t\t\t);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(\n\t\tname: string | symbol,\n\t\tsource: TextureSource,\n\t\toptions?: TextureOptions & { history?: number }\n\t) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${stringFrom(name)}' is already initialized.`);\n\t\t}\n\n\t\tconst { history: historyDepth = 0, ...textureOptions } = options ?? {};\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history' | 'options'> = {\n\t\t\twidth,\n\t\t\theight,\n\t\t\toptions: this.resolveTextureOptions(textureOptions),\n\t\t};\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: TextureOptions & { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.emitHook('initializeTexture', ...arguments);\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: { skipHistoryWrite?: boolean }) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t\tthis.emitHook('updateTextures', ...arguments);\n\t}\n\n\tprivate updateTexture(\n\t\tname: string | symbol,\n\t\tsource: UpdateTextureSource,\n\t\toptions?: { skipHistoryWrite?: boolean }\n\t) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\tif (source instanceof WebGLTexture) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, source);\n\t\t\treturn;\n\t\t}\n\n\t\tlet nonShaderPadSource = source as Exclude<UpdateTextureSource, ShaderPad>;\n\t\tif (source instanceof ShaderPad) {\n\t\t\tconst sourceIntermediateInfo = source.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\n\t\t\tif (source.gl === this.gl) {\n\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, sourceIntermediateInfo.texture);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Different contexts - transfer via readPixels to preserve precision.\n\t\t\tconst {\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\toptions: { format, type },\n\t\t\t} = sourceIntermediateInfo;\n\t\t\tconst pixels = this.getPixelArray(type, width * height * 4);\n\t\t\tsource.gl.bindFramebuffer(source.gl.FRAMEBUFFER, source.intermediateFbo);\n\t\t\tsource.gl.readPixels(0, 0, width, height, format, type, pixels);\n\t\t\tsource.gl.bindFramebuffer(source.gl.FRAMEBUFFER, null);\n\t\t\tnonShaderPadSource = { data: pixels, width, height };\n\t\t}\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(nonShaderPadSource);\n\t\tif (!width || !height) return;\n\n\t\tconst isPartial = 'isPartial' in nonShaderPadSource && nonShaderPadSource.isPartial;\n\t\tif (!isPartial) {\n\t\t\tthis.resizeTexture(name, width, height);\n\t\t}\n\n\t\t// UNPACK_FLIP_Y_WEBGL only works for DOM element sources, not typed arrays.\n\t\tconst isTypedArray = 'data' in nonShaderPadSource && nonShaderPadSource.data;\n\t\tconst shouldFlipY = !isTypedArray && !info.options?.preserveY;\n\t\tconst previousFlipY = this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);\n\n\t\tif (info.history) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (!options?.skipHistoryWrite) {\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t((nonShaderPadSource as PartialCustomTexture).data ??\n\t\t\t\t\t\t(nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>)) as any\n\t\t\t\t);\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\n\t\t\tif (isPartial) {\n\t\t\t\tconst partialSource = nonShaderPadSource as PartialCustomTexture;\n\t\t\t\tthis.gl.texSubImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tpartialSource.x ?? 0,\n\t\t\t\t\tpartialSource.y ?? 0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\tpartialSource.data\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.gl.texImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.options.internalFormat,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t((nonShaderPadSource as PartialCustomTexture).data ??\n\t\t\t\t\t\t(nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>)) as any\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t}\n\t}\n\n\tdraw(options?: StepOptions) {\n\t\tthis.emitHook('beforeDraw', ...arguments);\n\t\tconst gl = this.gl;\n\t\tconst w = gl.drawingBufferWidth;\n\t\tconst h = gl.drawingBufferHeight;\n\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.intermediateFbo);\n\t\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, intermediateInfo.texture, 0);\n\n\t\tgl.useProgram(this.program);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.viewport(0, 0, w, h);\n\t\tif (!options?.skipClear) gl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\tconst historyInfo = this.textures.get(HISTORY_TEXTURE_KEY);\n\t\tif (historyInfo && !options?.skipHistoryWrite) {\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, historyInfo.texture);\n\t\t\tgl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, historyInfo.history!.writeIndex, 0, 0, w, h);\n\t\t}\n\n\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n\t\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\tthis.emitHook('afterDraw', ...arguments);\n\t}\n\n\tstep(time: number, options?: StepOptions) {\n\t\tthis.emitHook('beforeStep', ...arguments);\n\t\tconst updates: Record<string, number> = {};\n\t\tif (this.uniforms.has('u_time')) updates.u_time = time;\n\t\tif (this.uniforms.has('u_frame')) updates.u_frame = this.frame;\n\t\tthis.updateUniforms(updates);\n\t\tthis.draw(options);\n\t\tconst historyInfo = this.textures.get(HISTORY_TEXTURE_KEY);\n\t\tif (historyInfo && !options?.skipHistoryWrite) {\n\t\t\tconst { writeIndex, depth } = historyInfo.history!;\n\t\t\tthis.updateUniforms({ [`${stringFrom(HISTORY_TEXTURE_KEY)}FrameOffset`]: writeIndex });\n\t\t\thistoryInfo.history!.writeIndex = (writeIndex + 1) % depth;\n\t\t}\n\t\t++this.frame;\n\t\tthis.emitHook('afterStep', ...arguments);\n\t}\n\n\tplay(\n\t\tonStepComplete?: (time: number, frame: number) => void,\n\t\tsetStepOptions?: (time: number, frame: number) => StepOptions | void\n\t) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tconst options = setStepOptions?.(time, this.frame) ?? undefined;\n\t\t\tthis.step(time, options);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tonStepComplete?.(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\tthis.emitHook('play');\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t\tthis.emitHook('pause');\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.emitHook('reset');\n\t}\n\n\tdestroy() {\n\t\tthis.emitHook('destroy');\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t\t});\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tif (this.intermediateFbo) {\n\t\t\tthis.gl.deleteFramebuffer(this.intermediateFbo);\n\t\t\tthis.intermediateFbo = null;\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tif (this.isInternalCanvas && this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","QUAD_VERTICES","HISTORY_TEXTURE_KEY","INTERMEDIATE_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","ShaderPad","stringFrom","name","_ShaderPad","fragmentShaderSrc","canvas","plugins","history","debug","textureOptions","htmlCanvas","wrapDimension","dimension","descriptor","v","gl","internalFormat","type","glslInjections","plugin","code","program","vertexShader","fragmentShader","args","hook","fn","hooks","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","options","size","textureInfo","format","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","newValue","uniform","glFunctionName","nValues","item","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","nonShaderPadSource","sourceIntermediateInfo","pixels","isPartial","shouldFlipY","previousFlipY","frameOffsetUniformName","partialSource","w","h","intermediateInfo","historyInfo","time","writeIndex","depth","onStepComplete","setStepOptions","loop","index_default"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
var y={data:new Uint8Array(4),width:1,height:1};function h(n){return n instanceof HTMLVideoElement||n instanceof HTMLImageElement||n instanceof HTMLCanvasElement||n instanceof OffscreenCanvas}function $(n){return JSON.stringify(n,Object.keys(n).sort())}function M(n,c,a,i,t=0){let e=1/0,r=-1/0,s=1/0,o=-1/0,m=0,g=0;for(let p of a){let u=(t+c*i+p)*4,l=n[u],x=n[u+1];e=Math.min(e,l),r=Math.max(r,l),s=Math.min(s,x),o=Math.max(o,x),m+=n[u+2],g+=n[u+3]}return[(e+r)/2,(s+o)/2,m/a.length,g/a.length]}var f=null;function b(){return f||(f=import("@mediapipe/tasks-vision").then(({FilesetResolver:n})=>n.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.22-rc.20250304/wasm"))),f}function d(n){return{historyParams:n?", framesAgo":"",fn:n?(i,t,e,r)=>{let s=e.replace(/\w+ /g,""),o=e?`${e}, int framesAgo`:"int framesAgo",m=s?`${s}, 0`:"0";return`${i} ${t}(${o}) {
|
|
2
|
+
${r}
|
|
3
|
+
}
|
|
4
|
+
${i} ${t}(${e}) { return ${t}(${m}); }`}:(i,t,e,r)=>`${i} ${t}(${e}) {
|
|
5
|
+
${r}
|
|
6
|
+
}`}}export{y as a,h as b,$ as c,M as d,b as e,d as f};
|
|
7
|
+
//# sourceMappingURL=chunk-JRSBIGBN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/mediapipe-common.ts"],"sourcesContent":["import { TextureSource } from '..';\n\nexport const dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\n\nexport type MediaPipeSource = HTMLVideoElement | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas;\n\nexport function isMediaPipeSource(source: TextureSource): source is MediaPipeSource {\n\treturn (\n\t\tsource instanceof HTMLVideoElement ||\n\t\tsource instanceof HTMLImageElement ||\n\t\tsource instanceof HTMLCanvasElement ||\n\t\tsource instanceof OffscreenCanvas\n\t);\n}\n\nexport function hashOptions(options: object): string {\n\treturn JSON.stringify(options, Object.keys(options).sort());\n}\n\nexport function calculateBoundingBoxCenter(\n\tdata: Float32Array,\n\tentityIdx: number,\n\tlandmarkIndices: readonly number[] | number[],\n\tlandmarkCount: number,\n\toffset: number = 0\n): [number, number, number, number] {\n\tlet minX = Infinity,\n\t\tmaxX = -Infinity,\n\t\tminY = Infinity,\n\t\tmaxY = -Infinity,\n\t\tavgZ = 0,\n\t\tavgVisibility = 0;\n\n\tfor (const idx of landmarkIndices) {\n\t\tconst dataIdx = (offset + entityIdx * landmarkCount + idx) * 4;\n\t\tconst x = data[dataIdx];\n\t\tconst y = data[dataIdx + 1];\n\t\tminX = Math.min(minX, x);\n\t\tmaxX = Math.max(maxX, x);\n\t\tminY = Math.min(minY, y);\n\t\tmaxY = Math.max(maxY, y);\n\t\tavgZ += data[dataIdx + 2];\n\t\tavgVisibility += data[dataIdx + 3];\n\t}\n\n\treturn [\n\t\t(minX + maxX) / 2,\n\t\t(minY + maxY) / 2,\n\t\tavgZ / landmarkIndices.length,\n\t\tavgVisibility / landmarkIndices.length,\n\t];\n}\n\nlet filesetPromise: Promise<any> | null = null;\nexport function getSharedFileset(): Promise<any> {\n\tif (!filesetPromise) {\n\t\tfilesetPromise = import('@mediapipe/tasks-vision').then(({ FilesetResolver }) =>\n\t\t\tFilesetResolver.forVisionTasks(\n\t\t\t\t`https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${__MEDIAPIPE_TASKS_VISION_VERSION__}/wasm`\n\t\t\t)\n\t\t);\n\t}\n\treturn filesetPromise;\n}\n\nexport function generateGLSLFn(history: number | undefined) {\n\tconst historyParams = history ? ', framesAgo' : '';\n\tconst fn = history\n\t\t? (returnType: string, name: string, args: string, body: string) => {\n\t\t\t\tconst argsOnly = args.replace(/\\w+ /g, '');\n\t\t\t\tconst historyArgs = args ? `${args}, int framesAgo` : 'int framesAgo';\n\t\t\t\tconst callArgs = argsOnly ? `${argsOnly}, 0` : '0';\n\t\t\t\treturn `${returnType} ${name}(${historyArgs}) {\\n${body}\\n}\n${returnType} ${name}(${args}) { return ${name}(${callArgs}); }`;\n\t\t }\n\t\t: (returnType: string, name: string, args: string, body: string) =>\n\t\t\t\t`${returnType} ${name}(${args}) {\\n${body}\\n}`;\n\treturn { historyParams, fn };\n}\n"],"mappings":"AAEO,IAAMA,EAAe,CAAE,KAAM,IAAI,WAAW,CAAC,EAAG,MAAO,EAAG,OAAQ,CAAE,EAIpE,SAASC,EAAkBC,EAAkD,CACnF,OACCA,aAAkB,kBAClBA,aAAkB,kBAClBA,aAAkB,mBAClBA,aAAkB,eAEpB,CAEO,SAASC,EAAYC,EAAyB,CACpD,OAAO,KAAK,UAAUA,EAAS,OAAO,KAAKA,CAAO,EAAE,KAAK,CAAC,CAC3D,CAEO,SAASC,EACfC,EACAC,EACAC,EACAC,EACAC,EAAiB,EACkB,CACnC,IAAIC,EAAO,IACVC,EAAO,KACPC,EAAO,IACPC,EAAO,KACPC,EAAO,EACPC,EAAgB,EAEjB,QAAWC,KAAOT,EAAiB,CAClC,IAAMU,GAAWR,EAASH,EAAYE,EAAgBQ,GAAO,EACvDE,EAAIb,EAAKY,CAAO,EAChBE,EAAId,EAAKY,EAAU,CAAC,EAC1BP,EAAO,KAAK,IAAIA,EAAMQ,CAAC,EACvBP,EAAO,KAAK,IAAIA,EAAMO,CAAC,EACvBN,EAAO,KAAK,IAAIA,EAAMO,CAAC,EACvBN,EAAO,KAAK,IAAIA,EAAMM,CAAC,EACvBL,GAAQT,EAAKY,EAAU,CAAC,EACxBF,GAAiBV,EAAKY,EAAU,CAAC,CAClC,CAEA,MAAO,EACLP,EAAOC,GAAQ,GACfC,EAAOC,GAAQ,EAChBC,EAAOP,EAAgB,OACvBQ,EAAgBR,EAAgB,MACjC,CACD,CAEA,IAAIa,EAAsC,KACnC,SAASC,GAAiC,CAChD,OAAKD,IACJA,EAAiB,OAAO,yBAAyB,EAAE,KAAK,CAAC,CAAE,gBAAAE,CAAgB,IAC1EA,EAAgB,eACf,+EACD,CACD,GAEMF,CACR,CAEO,SAASG,EAAeC,EAA6B,CAY3D,MAAO,CAAE,cAXaA,EAAU,cAAgB,GAWxB,GAVbA,EACR,CAACC,EAAoBC,EAAcC,EAAcC,IAAiB,CAClE,IAAMC,EAAWF,EAAK,QAAQ,QAAS,EAAE,EACnCG,EAAcH,EAAO,GAAGA,CAAI,kBAAoB,gBAChDI,EAAWF,EAAW,GAAGA,CAAQ,MAAQ,IAC/C,MAAO,GAAGJ,CAAU,IAAIC,CAAI,IAAII,CAAW;AAAA,EAAQF,CAAI;AAAA;AAAA,EACzDH,CAAU,IAAIC,CAAI,IAAIC,CAAI,cAAcD,CAAI,IAAIK,CAAQ,MACtD,EACA,CAACN,EAAoBC,EAAcC,EAAcC,IACjD,GAAGH,CAAU,IAAIC,CAAI,IAAIC,CAAI;AAAA,EAAQC,CAAI;AAAA,EACjB,CAC5B","names":["dummyTexture","isMediaPipeSource","source","hashOptions","options","calculateBoundingBoxCenter","data","entityIdx","landmarkIndices","landmarkCount","offset","minX","maxX","minY","maxY","avgZ","avgVisibility","idx","dataIdx","x","y","filesetPromise","getSharedFileset","FilesetResolver","generateGLSLFn","history","returnType","name","args","body","argsOnly","historyArgs","callArgs"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -18,7 +18,7 @@ interface PartialCustomTexture extends CustomTexture {
|
|
|
18
18
|
x?: number;
|
|
19
19
|
y?: number;
|
|
20
20
|
}
|
|
21
|
-
type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | WebGLTexture | CustomTexture;
|
|
21
|
+
type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | WebGLTexture | CustomTexture | ShaderPad;
|
|
22
22
|
type UpdateTextureSource = Exclude<TextureSource, CustomTexture> | PartialCustomTexture;
|
|
23
23
|
interface PluginContext {
|
|
24
24
|
gl: WebGL2RenderingContext;
|
|
@@ -78,6 +78,7 @@ declare class ShaderPad {
|
|
|
78
78
|
private reserveTextureUnit;
|
|
79
79
|
private releaseTextureUnit;
|
|
80
80
|
private resolveTextureOptions;
|
|
81
|
+
private getPixelArray;
|
|
81
82
|
private clearHistoryTextureLayers;
|
|
82
83
|
initializeUniform(name: string, type: 'float' | 'int', value: number | number[] | (number | number[])[], options?: {
|
|
83
84
|
arrayLength?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ interface PartialCustomTexture extends CustomTexture {
|
|
|
18
18
|
x?: number;
|
|
19
19
|
y?: number;
|
|
20
20
|
}
|
|
21
|
-
type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | WebGLTexture | CustomTexture;
|
|
21
|
+
type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | WebGLTexture | CustomTexture | ShaderPad;
|
|
22
22
|
type UpdateTextureSource = Exclude<TextureSource, CustomTexture> | PartialCustomTexture;
|
|
23
23
|
interface PluginContext {
|
|
24
24
|
gl: WebGL2RenderingContext;
|
|
@@ -78,6 +78,7 @@ declare class ShaderPad {
|
|
|
78
78
|
private reserveTextureUnit;
|
|
79
79
|
private releaseTextureUnit;
|
|
80
80
|
private resolveTextureOptions;
|
|
81
|
+
private getPixelArray;
|
|
81
82
|
private clearHistoryTextureLayers;
|
|
82
83
|
initializeUniform(name: string, type: 'float' | 'int', value: number | number[] | (number | number[])[], options?: {
|
|
83
84
|
arrayLength?: number;
|