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.
Files changed (52) hide show
  1. package/README.md +116 -56
  2. package/dist/chunk-5CBGNOA3.mjs +10 -0
  3. package/dist/chunk-5CBGNOA3.mjs.map +1 -0
  4. package/dist/chunk-JRSBIGBN.mjs +7 -0
  5. package/dist/chunk-JRSBIGBN.mjs.map +1 -0
  6. package/dist/index.d.mts +2 -1
  7. package/dist/index.d.ts +2 -1
  8. package/dist/index.js +4 -4
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +1 -1
  11. package/dist/plugins/face.d.mts +1 -0
  12. package/dist/plugins/face.d.ts +1 -0
  13. package/dist/plugins/face.js +53 -76
  14. package/dist/plugins/face.js.map +1 -1
  15. package/dist/plugins/face.mjs +51 -79
  16. package/dist/plugins/face.mjs.map +1 -1
  17. package/dist/plugins/hands.d.mts +1 -0
  18. package/dist/plugins/hands.d.ts +1 -0
  19. package/dist/plugins/hands.js +20 -16
  20. package/dist/plugins/hands.js.map +1 -1
  21. package/dist/plugins/hands.mjs +15 -16
  22. package/dist/plugins/hands.mjs.map +1 -1
  23. package/dist/plugins/helpers.js +1 -1
  24. package/dist/plugins/helpers.js.map +1 -1
  25. package/dist/plugins/helpers.mjs +1 -1
  26. package/dist/plugins/helpers.mjs.map +1 -1
  27. package/dist/plugins/mediapipe-common.d.mts +18 -0
  28. package/dist/plugins/mediapipe-common.d.ts +18 -0
  29. package/dist/plugins/mediapipe-common.js +7 -0
  30. package/dist/plugins/mediapipe-common.js.map +1 -0
  31. package/dist/plugins/mediapipe-common.mjs +2 -0
  32. package/dist/plugins/mediapipe-common.mjs.map +1 -0
  33. package/dist/plugins/pose.d.mts +1 -0
  34. package/dist/plugins/pose.d.ts +1 -0
  35. package/dist/plugins/pose.js +54 -49
  36. package/dist/plugins/pose.js.map +1 -1
  37. package/dist/plugins/pose.mjs +46 -46
  38. package/dist/plugins/pose.mjs.map +1 -1
  39. package/dist/plugins/save.d.mts +1 -1
  40. package/dist/plugins/save.d.ts +1 -1
  41. package/dist/plugins/save.js +1 -1
  42. package/dist/plugins/save.js.map +1 -1
  43. package/dist/plugins/save.mjs.map +1 -1
  44. package/dist/plugins/segmenter.d.mts +1 -0
  45. package/dist/plugins/segmenter.d.ts +1 -0
  46. package/dist/plugins/segmenter.js +16 -11
  47. package/dist/plugins/segmenter.js.map +1 -1
  48. package/dist/plugins/segmenter.mjs +10 -10
  49. package/dist/plugins/segmenter.mjs.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/chunk-A3XQBYSC.mjs +0 -10
  52. package/dist/chunk-A3XQBYSC.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/pose.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '../index';\nimport type { PoseLandmarker, PoseLandmarkerResult, NormalizedLandmark, MPMask } from '@mediapipe/tasks-vision';\n\nexport interface PosePluginOptions {\n\tmodelPath?: string;\n\tmaxPoses?: number;\n\tminPoseDetectionConfidence?: number;\n\tminPosePresenceConfidence?: number;\n\tminTrackingConfidence?: number;\n}\n\nconst STANDARD_LANDMARK_COUNT = 33; // See https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker#pose_landmarker_model.\nconst CUSTOM_LANDMARK_COUNT = 6;\nconst LANDMARK_COUNT = STANDARD_LANDMARK_COUNT + CUSTOM_LANDMARK_COUNT;\nconst LANDMARK_INDICES = {\n\t// Standard landmarks.\n\tLEFT_EYE: 2,\n\tRIGHT_EYE: 5,\n\tLEFT_SHOULDER: 11,\n\tRIGHT_SHOULDER: 12,\n\tLEFT_ELBOW: 13,\n\tRIGHT_ELBOW: 14,\n\tLEFT_HIP: 23,\n\tRIGHT_HIP: 24,\n\tLEFT_KNEE: 25,\n\tRIGHT_KNEE: 26,\n\tLEFT_WRIST: 15,\n\tRIGHT_WRIST: 16,\n\tLEFT_PINKY: 17,\n\tRIGHT_PINKY: 18,\n\tLEFT_INDEX: 19,\n\tRIGHT_INDEX: 20,\n\tLEFT_THUMB: 21,\n\tRIGHT_THUMB: 22,\n\tLEFT_ANKLE: 27,\n\tRIGHT_ANKLE: 28,\n\tLEFT_HEEL: 29,\n\tRIGHT_HEEL: 30,\n\tLEFT_FOOT_INDEX: 31,\n\tRIGHT_FOOT_INDEX: 32,\n\t// Custom landmarks.\n\tBODY_CENTER: STANDARD_LANDMARK_COUNT,\n\tLEFT_HAND_CENTER: STANDARD_LANDMARK_COUNT + 1,\n\tRIGHT_HAND_CENTER: STANDARD_LANDMARK_COUNT + 2,\n\tLEFT_FOOT_CENTER: STANDARD_LANDMARK_COUNT + 3,\n\tRIGHT_FOOT_CENTER: STANDARD_LANDMARK_COUNT + 4,\n\tTORSO_CENTER: STANDARD_LANDMARK_COUNT + 5,\n};\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst LEFT_HAND_INDICES = [\n\tLANDMARK_INDICES.LEFT_WRIST,\n\tLANDMARK_INDICES.LEFT_PINKY,\n\tLANDMARK_INDICES.LEFT_THUMB,\n\tLANDMARK_INDICES.LEFT_INDEX,\n];\nconst RIGHT_HAND_INDICES = [\n\tLANDMARK_INDICES.RIGHT_WRIST,\n\tLANDMARK_INDICES.RIGHT_PINKY,\n\tLANDMARK_INDICES.RIGHT_THUMB,\n\tLANDMARK_INDICES.RIGHT_INDEX,\n];\nconst LEFT_FOOT_INDICES = [LANDMARK_INDICES.LEFT_ANKLE, LANDMARK_INDICES.LEFT_HEEL, LANDMARK_INDICES.LEFT_FOOT_INDEX];\nconst RIGHT_FOOT_INDICES = [\n\tLANDMARK_INDICES.RIGHT_ANKLE,\n\tLANDMARK_INDICES.RIGHT_HEEL,\n\tLANDMARK_INDICES.RIGHT_FOOT_INDEX,\n];\nconst TORSO_INDICES = [\n\tLANDMARK_INDICES.LEFT_SHOULDER,\n\tLANDMARK_INDICES.RIGHT_SHOULDER,\n\tLANDMARK_INDICES.LEFT_HIP,\n\tLANDMARK_INDICES.RIGHT_HIP,\n];\n\nconst dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\nfunction pose(config: { textureName: string; options?: PosePluginOptions }) {\n\tconst { textureName, options } = config;\n\tconst defaultModelPath =\n\t\t'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task';\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL, gl, emitHook } = context;\n\n\t\tlet poseLandmarker: PoseLandmarker | null = null;\n\t\tlet vision: any = null;\n\t\tlet lastVideoTime = -1;\n\t\tlet runningMode: 'IMAGE' | 'VIDEO' = 'VIDEO';\n\t\tconst textureSources = new Map<string, TextureSource>();\n\t\tconst maxPoses = options?.maxPoses ?? 1;\n\n\t\tconst LANDMARKS_TEXTURE_WIDTH = 512;\n\t\tlet landmarksTextureHeight = 0;\n\t\tlet landmarksDataArray: Float32Array | null = null;\n\n\t\t// Shared canvas for MediaPipe and maskShader (same WebGL context).\n\t\tconst sharedCanvas = new OffscreenCanvas(1, 1);\n\t\tlet maskShader: ShaderPad | null = null;\n\n\t\tasync function initializeMediaPipe() {\n\t\t\ttry {\n\t\t\t\tconst { FilesetResolver, PoseLandmarker } = await import('@mediapipe/tasks-vision');\n\t\t\t\tvision = await FilesetResolver.forVisionTasks(\n\t\t\t\t\t'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm'\n\t\t\t\t);\n\t\t\t\tposeLandmarker = await PoseLandmarker.createFromOptions(vision, {\n\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\tmodelAssetPath: options?.modelPath || defaultModelPath,\n\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t},\n\t\t\t\t\tcanvas: sharedCanvas,\n\t\t\t\t\trunningMode,\n\t\t\t\t\tnumPoses: options?.maxPoses ?? 1,\n\t\t\t\t\tminPoseDetectionConfidence: options?.minPoseDetectionConfidence ?? 0.5,\n\t\t\t\t\tminPosePresenceConfidence: options?.minPosePresenceConfidence ?? 0.5,\n\t\t\t\t\tminTrackingConfidence: options?.minTrackingConfidence ?? 0.5,\n\t\t\t\t\toutputSegmentationMasks: true,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Pose Plugin] Failed to initialize MediaPipe:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tconst mediaPipeInitPromise = initializeMediaPipe();\n\n\t\tfunction calculateBoundingBoxCenter(\n\t\t\tlandmarksDataArray: Float32Array,\n\t\t\tposeIdx: number,\n\t\t\tlandmarkIndices: number[]\n\t\t): [number, number, number, number] {\n\t\t\tlet minX = Infinity,\n\t\t\t\tmaxX = -Infinity,\n\t\t\t\tminY = Infinity,\n\t\t\t\tmaxY = -Infinity,\n\t\t\t\tavgZ = 0,\n\t\t\t\tavgVisibility = 0;\n\n\t\t\tfor (const idx of landmarkIndices) {\n\t\t\t\tconst dataIdx = (poseIdx * LANDMARK_COUNT + idx) * 4;\n\t\t\t\tconst x = landmarksDataArray[dataIdx];\n\t\t\t\tconst y = landmarksDataArray[dataIdx + 1];\n\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t\tavgZ += landmarksDataArray[dataIdx + 2];\n\t\t\t\tavgVisibility += landmarksDataArray[dataIdx + 3];\n\t\t\t}\n\n\t\t\tconst centerX = (minX + maxX) / 2;\n\t\t\tconst centerY = (minY + maxY) / 2;\n\t\t\tconst centerZ = avgZ / landmarkIndices.length;\n\t\t\tconst centerVisibility = avgVisibility / landmarkIndices.length;\n\t\t\treturn [centerX, centerY, centerZ, centerVisibility];\n\t\t}\n\n\t\tfunction updateMaskTexture(segmentationMasks?: MPMask[]) {\n\t\t\tif (!segmentationMasks || segmentationMasks.length === 0 || !maskShader) return;\n\t\t\tfor (let i = 0; i < segmentationMasks.length; ++i) {\n\t\t\t\tconst mask = segmentationMasks[i];\n\t\t\t\tmaskShader.updateTextures({ u_mask: mask.getAsWebGLTexture() });\n\t\t\t\tmaskShader.updateUniforms({ u_poseIndex: (i + 1) / maxPoses });\n\t\t\t\tmaskShader.draw({ skipClear: i > 0 }); // Only clear on first mask.\n\t\t\t\tmask.close();\n\t\t\t}\n\t\t\tshaderPad.updateTextures({ u_poseMask: sharedCanvas });\n\t\t}\n\n\t\tfunction updateLandmarksTexture(poses: NormalizedLandmark[][]) {\n\t\t\tif (!landmarksDataArray) return;\n\n\t\t\tconst nPoses = poses.length;\n\t\t\tconst totalLandmarks = nPoses * LANDMARK_COUNT;\n\n\t\t\tfor (let poseIdx = 0; poseIdx < nPoses; ++poseIdx) {\n\t\t\t\tconst landmarks = poses[poseIdx];\n\t\t\t\tfor (let lmIdx = 0; lmIdx < STANDARD_LANDMARK_COUNT; ++lmIdx) {\n\t\t\t\t\tconst landmark = landmarks[lmIdx];\n\t\t\t\t\tconst dataIdx = (poseIdx * LANDMARK_COUNT + lmIdx) * 4;\n\t\t\t\t\tlandmarksDataArray[dataIdx] = landmark.x;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 1] = 1 - landmark.y;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 2] = landmark.z ?? 0;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 3] = landmark.visibility ?? 1;\n\t\t\t\t}\n\n\t\t\t\tconst bodyCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, ALL_STANDARD_INDICES);\n\t\t\t\tconst bodyCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.BODY_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[bodyCenterIdx] = bodyCenter[0];\n\t\t\t\tlandmarksDataArray[bodyCenterIdx + 1] = bodyCenter[1];\n\t\t\t\tlandmarksDataArray[bodyCenterIdx + 2] = bodyCenter[2];\n\t\t\t\tlandmarksDataArray[bodyCenterIdx + 3] = bodyCenter[3];\n\n\t\t\t\tconst leftHandCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, LEFT_HAND_INDICES);\n\t\t\t\tconst leftHandCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.LEFT_HAND_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[leftHandCenterIdx] = leftHandCenter[0];\n\t\t\t\tlandmarksDataArray[leftHandCenterIdx + 1] = leftHandCenter[1];\n\t\t\t\tlandmarksDataArray[leftHandCenterIdx + 2] = leftHandCenter[2];\n\t\t\t\tlandmarksDataArray[leftHandCenterIdx + 3] = leftHandCenter[3];\n\n\t\t\t\tconst rightHandCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, RIGHT_HAND_INDICES);\n\t\t\t\tconst rightHandCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.RIGHT_HAND_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[rightHandCenterIdx] = rightHandCenter[0];\n\t\t\t\tlandmarksDataArray[rightHandCenterIdx + 1] = rightHandCenter[1];\n\t\t\t\tlandmarksDataArray[rightHandCenterIdx + 2] = rightHandCenter[2];\n\t\t\t\tlandmarksDataArray[rightHandCenterIdx + 3] = rightHandCenter[3];\n\n\t\t\t\tconst leftFootCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, LEFT_FOOT_INDICES);\n\t\t\t\tconst leftFootCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.LEFT_FOOT_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[leftFootCenterIdx] = leftFootCenter[0];\n\t\t\t\tlandmarksDataArray[leftFootCenterIdx + 1] = leftFootCenter[1];\n\t\t\t\tlandmarksDataArray[leftFootCenterIdx + 2] = leftFootCenter[2];\n\t\t\t\tlandmarksDataArray[leftFootCenterIdx + 3] = leftFootCenter[3];\n\n\t\t\t\tconst rightFootCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, RIGHT_FOOT_INDICES);\n\t\t\t\tconst rightFootCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.RIGHT_FOOT_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[rightFootCenterIdx] = rightFootCenter[0];\n\t\t\t\tlandmarksDataArray[rightFootCenterIdx + 1] = rightFootCenter[1];\n\t\t\t\tlandmarksDataArray[rightFootCenterIdx + 2] = rightFootCenter[2];\n\t\t\t\tlandmarksDataArray[rightFootCenterIdx + 3] = rightFootCenter[3];\n\n\t\t\t\tconst torsoCenter = calculateBoundingBoxCenter(landmarksDataArray, poseIdx, TORSO_INDICES);\n\t\t\t\tconst torsoCenterIdx = (poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.TORSO_CENTER) * 4;\n\t\t\t\tlandmarksDataArray[torsoCenterIdx] = torsoCenter[0];\n\t\t\t\tlandmarksDataArray[torsoCenterIdx + 1] = torsoCenter[1];\n\t\t\t\tlandmarksDataArray[torsoCenterIdx + 2] = torsoCenter[2];\n\t\t\t\tlandmarksDataArray[torsoCenterIdx + 3] = torsoCenter[3];\n\t\t\t}\n\n\t\t\tconst rowsToUpdate = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tshaderPad.updateTextures({\n\t\t\t\tu_poseLandmarksTex: {\n\t\t\t\t\tdata: landmarksDataArray,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: rowsToUpdate,\n\t\t\t\t\tisPartial: true,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tfunction processPoses(result?: PoseLandmarkerResult) {\n\t\t\tif (!result?.landmarks || !landmarksDataArray) return;\n\t\t\tupdateLandmarksTexture(result.landmarks);\n\t\t\tupdateMaskTexture(result.segmentationMasks);\n\t\t\tshaderPad.updateUniforms({ u_nPoses: result.landmarks.length });\n\t\t\temitHook('pose:result', result);\n\t\t}\n\n\t\tshaderPad.on('init', async () => {\n\t\t\tshaderPad.initializeUniform('u_maxPoses', 'int', maxPoses);\n\t\t\tshaderPad.initializeUniform('u_nPoses', 'int', 0);\n\n\t\t\tconst totalLandmarks = maxPoses * LANDMARK_COUNT;\n\t\t\tlandmarksTextureHeight = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tconst textureSize = LANDMARKS_TEXTURE_WIDTH * landmarksTextureHeight * 4;\n\t\t\tlandmarksDataArray = new Float32Array(textureSize);\n\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_poseLandmarksTex',\n\t\t\t\t{\n\t\t\t\t\tdata: landmarksDataArray,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: landmarksTextureHeight,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tinternalFormat: gl.RGBA32F,\n\t\t\t\t\ttype: gl.FLOAT,\n\t\t\t\t\tminFilter: gl.NEAREST,\n\t\t\t\t\tmagFilter: gl.NEAREST,\n\t\t\t\t}\n\t\t\t);\n\t\t\tshaderPad.initializeTexture('u_poseMask', sharedCanvas, {\n\t\t\t\tpreserveY: true,\n\t\t\t\tminFilter: gl.NEAREST,\n\t\t\t\tmagFilter: gl.NEAREST,\n\t\t\t});\n\t\t\tawait mediaPipeInitPromise;\n\t\t\tmaskShader = new ShaderPad(\n\t\t\t\t`#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nout vec4 outColor;\nuniform sampler2D u_mask;\nuniform float u_poseIndex;\nvoid main() {\n\tivec2 texCoord = ivec2(v_uv * vec2(textureSize(u_mask, 0)));\n\tfloat confidence = texelFetch(u_mask, texCoord, 0).r;\n\tif (confidence < 0.01) discard;\n\toutColor = vec4(1.0, confidence, u_poseIndex, 1.0);\n}`,\n\t\t\t\t{ canvas: sharedCanvas }\n\t\t\t);\n\t\t\tmaskShader.initializeTexture('u_mask', dummyTexture);\n\t\t\tmaskShader.initializeUniform('u_poseIndex', 'float', 0);\n\t\t\temitHook('pose:ready');\n\t\t});\n\n\t\tshaderPad.on('initializeTexture', (name: string, source: TextureSource) => {\n\t\t\tif (name === textureName) detectPoses(source);\n\t\t});\n\n\t\tshaderPad.on('updateTextures', (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (source) detectPoses(source);\n\t\t});\n\n\t\t// `detectPoses` may be called multiple times before MediaPipe is\n\t\t// initialized. This ensures we only process the last call.\n\t\tlet nDetectionCalls = 0;\n\t\tasync function detectPoses(source: TextureSource) {\n\t\t\tconst callOrder = ++nDetectionCalls;\n\t\t\tawait mediaPipeInitPromise;\n\t\t\tif (callOrder !== nDetectionCalls || !poseLandmarker) return;\n\n\t\t\tconst previousSource = textureSources.get(textureName);\n\t\t\tif (previousSource !== source) lastVideoTime = -1;\n\t\t\ttextureSources.set(textureName, source);\n\n\t\t\ttry {\n\t\t\t\tconst requiredMode = source instanceof HTMLVideoElement ? 'VIDEO' : 'IMAGE';\n\t\t\t\tif (runningMode !== requiredMode) {\n\t\t\t\t\trunningMode = requiredMode;\n\t\t\t\t\tawait poseLandmarker.setOptions({ runningMode });\n\t\t\t\t}\n\n\t\t\t\tif (source instanceof HTMLVideoElement) {\n\t\t\t\t\tif (source.videoWidth === 0 || source.videoHeight === 0 || source.readyState < 2) return;\n\t\t\t\t\tif (source.currentTime !== lastVideoTime) {\n\t\t\t\t\t\tlastVideoTime = source.currentTime;\n\t\t\t\t\t\tprocessPoses(poseLandmarker.detectForVideo(source, performance.now()));\n\t\t\t\t\t}\n\t\t\t\t} else if (source instanceof HTMLImageElement || source instanceof HTMLCanvasElement) {\n\t\t\t\t\tif (source.width === 0 || source.height === 0) return;\n\t\t\t\t\tprocessPoses(poseLandmarker.detect(source));\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Pose Plugin] Detection error:', error);\n\t\t\t}\n\t\t}\n\n\t\tshaderPad.on('destroy', () => {\n\t\t\tif (poseLandmarker) {\n\t\t\t\tposeLandmarker.close();\n\t\t\t\tposeLandmarker = null;\n\t\t\t}\n\t\t\tif (maskShader) {\n\t\t\t\tmaskShader.destroy();\n\t\t\t\tmaskShader = null;\n\t\t\t}\n\t\t\tvision = null;\n\t\t\ttextureSources.clear();\n\t\t\tlandmarksDataArray = null;\n\t\t});\n\t\tinjectGLSL(`\nuniform int u_maxPoses;\nuniform int u_nPoses;\nuniform sampler2D u_poseLandmarksTex;\nuniform sampler2D u_poseMask;\n\n#define POSE_LANDMARK_LEFT_EYE ${LANDMARK_INDICES.LEFT_EYE}\n#define POSE_LANDMARK_RIGHT_EYE ${LANDMARK_INDICES.RIGHT_EYE}\n#define POSE_LANDMARK_LEFT_SHOULDER ${LANDMARK_INDICES.LEFT_SHOULDER}\n#define POSE_LANDMARK_RIGHT_SHOULDER ${LANDMARK_INDICES.RIGHT_SHOULDER}\n#define POSE_LANDMARK_LEFT_ELBOW ${LANDMARK_INDICES.LEFT_ELBOW}\n#define POSE_LANDMARK_RIGHT_ELBOW ${LANDMARK_INDICES.RIGHT_ELBOW}\n#define POSE_LANDMARK_LEFT_HIP ${LANDMARK_INDICES.LEFT_HIP}\n#define POSE_LANDMARK_RIGHT_HIP ${LANDMARK_INDICES.RIGHT_HIP}\n#define POSE_LANDMARK_LEFT_KNEE ${LANDMARK_INDICES.LEFT_KNEE}\n#define POSE_LANDMARK_RIGHT_KNEE ${LANDMARK_INDICES.RIGHT_KNEE}\n#define POSE_LANDMARK_BODY_CENTER ${LANDMARK_INDICES.BODY_CENTER}\n#define POSE_LANDMARK_LEFT_HAND_CENTER ${LANDMARK_INDICES.LEFT_HAND_CENTER}\n#define POSE_LANDMARK_RIGHT_HAND_CENTER ${LANDMARK_INDICES.RIGHT_HAND_CENTER}\n#define POSE_LANDMARK_LEFT_FOOT_CENTER ${LANDMARK_INDICES.LEFT_FOOT_CENTER}\n#define POSE_LANDMARK_RIGHT_FOOT_CENTER ${LANDMARK_INDICES.RIGHT_FOOT_CENTER}\n#define POSE_LANDMARK_TORSO_CENTER ${LANDMARK_INDICES.TORSO_CENTER}\n\nvec4 poseLandmark(int poseIndex, int landmarkIndex) {\n\tint i = poseIndex * ${LANDMARK_COUNT} + landmarkIndex;\n\tint x = i % ${LANDMARKS_TEXTURE_WIDTH};\n\tint y = i / ${LANDMARKS_TEXTURE_WIDTH};\n\treturn texelFetch(u_poseLandmarksTex, ivec2(x, y), 0);\n}\n\nvec2 poseAt(vec2 pos) {\n\tvec4 mask = texture(u_poseMask, pos);\n\tfloat poseIndex = floor(mask.b * float(u_maxPoses) + 0.5) - 1.0;\n\treturn vec2(mask.g, poseIndex);\n}\n\t\nfloat inPose(vec2 pos) {\n\tfloat pose = poseAt(pos).x;\n\treturn step(0.0, pose);\n}`);\n\t};\n}\n\nexport default pose;\n"],"mappings":"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","names":["STANDARD_LANDMARK_COUNT","CUSTOM_LANDMARK_COUNT","LANDMARK_COUNT","LANDMARK_INDICES","ALL_STANDARD_INDICES","_","i","LEFT_HAND_INDICES","RIGHT_HAND_INDICES","LEFT_FOOT_INDICES","RIGHT_FOOT_INDICES","TORSO_INDICES","dummyTexture","pose","config","textureName","options","defaultModelPath","shaderPad","context","injectGLSL","gl","emitHook","poseLandmarker","vision","lastVideoTime","runningMode","textureSources","maxPoses","LANDMARKS_TEXTURE_WIDTH","landmarksTextureHeight","landmarksDataArray","sharedCanvas","maskShader","initializeMediaPipe","FilesetResolver","PoseLandmarker","error","mediaPipeInitPromise","calculateBoundingBoxCenter","poseIdx","landmarkIndices","minX","maxX","minY","maxY","avgZ","avgVisibility","idx","dataIdx","x","y","centerX","centerY","centerZ","centerVisibility","updateMaskTexture","segmentationMasks","mask","updateLandmarksTexture","poses","nPoses","totalLandmarks","landmarks","lmIdx","landmark","bodyCenter","bodyCenterIdx","leftHandCenter","leftHandCenterIdx","rightHandCenter","rightHandCenterIdx","leftFootCenter","leftFootCenterIdx","rightFootCenter","rightFootCenterIdx","torsoCenter","torsoCenterIdx","rowsToUpdate","processPoses","result","textureSize","index_default","name","source","detectPoses","updates","nDetectionCalls","callOrder","requiredMode","pose_default"]}
1
+ {"version":3,"sources":["../../src/plugins/pose.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '..';\nimport {\n\tcalculateBoundingBoxCenter,\n\tgenerateGLSLFn,\n\tdummyTexture,\n\tgetSharedFileset,\n\thashOptions,\n\tisMediaPipeSource,\n\tMediaPipeSource,\n} from './mediapipe-common';\nimport type { PoseLandmarker, PoseLandmarkerResult, NormalizedLandmark, MPMask } from '@mediapipe/tasks-vision';\n\nexport interface PosePluginOptions {\n\tmodelPath?: string;\n\tmaxPoses?: number;\n\tminPoseDetectionConfidence?: number;\n\tminPosePresenceConfidence?: number;\n\tminTrackingConfidence?: number;\n\thistory?: number;\n}\n\nconst STANDARD_LANDMARK_COUNT = 33; // See https://ai.google.dev/edge/mediapipe/solutions/vision/pose_landmarker#pose_landmarker_model.\nconst CUSTOM_LANDMARK_COUNT = 6;\nconst LANDMARK_COUNT = STANDARD_LANDMARK_COUNT + CUSTOM_LANDMARK_COUNT;\nconst LANDMARK_INDICES = {\n\t// Standard landmarks.\n\tLEFT_EYE: 2,\n\tRIGHT_EYE: 5,\n\tLEFT_SHOULDER: 11,\n\tRIGHT_SHOULDER: 12,\n\tLEFT_ELBOW: 13,\n\tRIGHT_ELBOW: 14,\n\tLEFT_HIP: 23,\n\tRIGHT_HIP: 24,\n\tLEFT_KNEE: 25,\n\tRIGHT_KNEE: 26,\n\tLEFT_WRIST: 15,\n\tRIGHT_WRIST: 16,\n\tLEFT_PINKY: 17,\n\tRIGHT_PINKY: 18,\n\tLEFT_INDEX: 19,\n\tRIGHT_INDEX: 20,\n\tLEFT_THUMB: 21,\n\tRIGHT_THUMB: 22,\n\tLEFT_ANKLE: 27,\n\tRIGHT_ANKLE: 28,\n\tLEFT_HEEL: 29,\n\tRIGHT_HEEL: 30,\n\tLEFT_FOOT_INDEX: 31,\n\tRIGHT_FOOT_INDEX: 32,\n\t// Custom landmarks.\n\tBODY_CENTER: STANDARD_LANDMARK_COUNT,\n\tLEFT_HAND_CENTER: STANDARD_LANDMARK_COUNT + 1,\n\tRIGHT_HAND_CENTER: STANDARD_LANDMARK_COUNT + 2,\n\tLEFT_FOOT_CENTER: STANDARD_LANDMARK_COUNT + 3,\n\tRIGHT_FOOT_CENTER: STANDARD_LANDMARK_COUNT + 4,\n\tTORSO_CENTER: STANDARD_LANDMARK_COUNT + 5,\n};\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst LEFT_HAND_INDICES = [\n\tLANDMARK_INDICES.LEFT_WRIST,\n\tLANDMARK_INDICES.LEFT_PINKY,\n\tLANDMARK_INDICES.LEFT_THUMB,\n\tLANDMARK_INDICES.LEFT_INDEX,\n];\nconst RIGHT_HAND_INDICES = [\n\tLANDMARK_INDICES.RIGHT_WRIST,\n\tLANDMARK_INDICES.RIGHT_PINKY,\n\tLANDMARK_INDICES.RIGHT_THUMB,\n\tLANDMARK_INDICES.RIGHT_INDEX,\n];\nconst LEFT_FOOT_INDICES = [LANDMARK_INDICES.LEFT_ANKLE, LANDMARK_INDICES.LEFT_HEEL, LANDMARK_INDICES.LEFT_FOOT_INDEX];\nconst RIGHT_FOOT_INDICES = [\n\tLANDMARK_INDICES.RIGHT_ANKLE,\n\tLANDMARK_INDICES.RIGHT_HEEL,\n\tLANDMARK_INDICES.RIGHT_FOOT_INDEX,\n];\nconst TORSO_INDICES = [\n\tLANDMARK_INDICES.LEFT_SHOULDER,\n\tLANDMARK_INDICES.RIGHT_SHOULDER,\n\tLANDMARK_INDICES.LEFT_HIP,\n\tLANDMARK_INDICES.RIGHT_HIP,\n];\n\nconst LANDMARKS_TEXTURE_WIDTH = 512;\nconst N_LANDMARK_METADATA_SLOTS = 1;\n\nconst DEFAULT_POSE_OPTIONS: Required<Omit<PosePluginOptions, 'history'>> = {\n\tmodelPath:\n\t\t'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task',\n\tmaxPoses: 1,\n\tminPoseDetectionConfidence: 0.5,\n\tminPosePresenceConfidence: 0.5,\n\tminTrackingConfidence: 0.5,\n};\n\ninterface Detector {\n\tlandmarker: PoseLandmarker;\n\tcanvas: OffscreenCanvas;\n\tsubscribers: Map<() => void, boolean>;\n\tmaxPoses: number;\n\tstate: {\n\t\trunningMode: 'IMAGE' | 'VIDEO';\n\t\tsource: MediaPipeSource | null;\n\t\tvideoTime: number;\n\t\tresultTimestamp: number;\n\t\tresult: PoseLandmarkerResult | null;\n\t\tpending: Promise<void>;\n\t\tnPoses: number;\n\t};\n\tlandmarks: {\n\t\tdata: Float32Array;\n\t\ttextureHeight: number;\n\t};\n\tmask: {\n\t\tshader: ShaderPad;\n\t};\n}\nconst sharedDetectors = new Map<string, Detector>();\n\nfunction updateLandmarksData(detector: Detector, poses: NormalizedLandmark[][]) {\n\tconst data = detector.landmarks.data;\n\tconst nPoses = poses.length;\n\n\tdata[0] = nPoses;\n\n\tfor (let poseIdx = 0; poseIdx < nPoses; ++poseIdx) {\n\t\tconst landmarks = poses[poseIdx];\n\t\tfor (let lmIdx = 0; lmIdx < STANDARD_LANDMARK_COUNT; ++lmIdx) {\n\t\t\tconst landmark = landmarks[lmIdx];\n\t\t\tconst dataIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + lmIdx) * 4;\n\t\t\tdata[dataIdx] = landmark.x;\n\t\t\tdata[dataIdx + 1] = 1 - landmark.y;\n\t\t\tdata[dataIdx + 2] = landmark.z ?? 0;\n\t\t\tdata[dataIdx + 3] = landmark.visibility ?? 1;\n\t\t}\n\n\t\tconst bodyCenter = calculateBoundingBoxCenter(data, poseIdx, ALL_STANDARD_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst bodyCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.BODY_CENTER) * 4;\n\t\tdata[bodyCenterIdx] = bodyCenter[0];\n\t\tdata[bodyCenterIdx + 1] = bodyCenter[1];\n\t\tdata[bodyCenterIdx + 2] = bodyCenter[2];\n\t\tdata[bodyCenterIdx + 3] = bodyCenter[3];\n\n\t\tconst leftHandCenter = calculateBoundingBoxCenter(data, poseIdx, LEFT_HAND_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst leftHandCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.LEFT_HAND_CENTER) * 4;\n\t\tdata[leftHandCenterIdx] = leftHandCenter[0];\n\t\tdata[leftHandCenterIdx + 1] = leftHandCenter[1];\n\t\tdata[leftHandCenterIdx + 2] = leftHandCenter[2];\n\t\tdata[leftHandCenterIdx + 3] = leftHandCenter[3];\n\n\t\tconst rightHandCenter = calculateBoundingBoxCenter(data, poseIdx, RIGHT_HAND_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst rightHandCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.RIGHT_HAND_CENTER) * 4;\n\t\tdata[rightHandCenterIdx] = rightHandCenter[0];\n\t\tdata[rightHandCenterIdx + 1] = rightHandCenter[1];\n\t\tdata[rightHandCenterIdx + 2] = rightHandCenter[2];\n\t\tdata[rightHandCenterIdx + 3] = rightHandCenter[3];\n\n\t\tconst leftFootCenter = calculateBoundingBoxCenter(data, poseIdx, LEFT_FOOT_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst leftFootCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.LEFT_FOOT_CENTER) * 4;\n\t\tdata[leftFootCenterIdx] = leftFootCenter[0];\n\t\tdata[leftFootCenterIdx + 1] = leftFootCenter[1];\n\t\tdata[leftFootCenterIdx + 2] = leftFootCenter[2];\n\t\tdata[leftFootCenterIdx + 3] = leftFootCenter[3];\n\n\t\tconst rightFootCenter = calculateBoundingBoxCenter(data, poseIdx, RIGHT_FOOT_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst rightFootCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.RIGHT_FOOT_CENTER) * 4;\n\t\tdata[rightFootCenterIdx] = rightFootCenter[0];\n\t\tdata[rightFootCenterIdx + 1] = rightFootCenter[1];\n\t\tdata[rightFootCenterIdx + 2] = rightFootCenter[2];\n\t\tdata[rightFootCenterIdx + 3] = rightFootCenter[3];\n\n\t\tconst torsoCenter = calculateBoundingBoxCenter(data, poseIdx, TORSO_INDICES, LANDMARK_COUNT, N_LANDMARK_METADATA_SLOTS);\n\t\tconst torsoCenterIdx = (N_LANDMARK_METADATA_SLOTS + poseIdx * LANDMARK_COUNT + LANDMARK_INDICES.TORSO_CENTER) * 4;\n\t\tdata[torsoCenterIdx] = torsoCenter[0];\n\t\tdata[torsoCenterIdx + 1] = torsoCenter[1];\n\t\tdata[torsoCenterIdx + 2] = torsoCenter[2];\n\t\tdata[torsoCenterIdx + 3] = torsoCenter[3];\n\t}\n\n\tdetector.state.nPoses = nPoses;\n}\n\nfunction updateMaskCanvas(detector: Detector, segmentationMasks?: MPMask[]) {\n\tif (!segmentationMasks || segmentationMasks.length === 0) return;\n\tconst {\n\t\tmask: { shader },\n\t\tmaxPoses,\n\t} = detector;\n\n\tfor (let i = 0; i < segmentationMasks.length; ++i) {\n\t\tconst segMask = segmentationMasks[i];\n\t\tshader.updateTextures({ u_mask: segMask.getAsWebGLTexture() });\n\t\tshader.updateUniforms({ u_poseIndex: (i + 1) / maxPoses });\n\t\tshader.draw({ skipClear: i > 0 });\n\t\tsegMask.close();\n\t}\n}\n\nfunction pose(config: { textureName: string; options?: PosePluginOptions }) {\n\tconst { textureName, options: { history, ...mediapipeOptions } = {} } = config;\n\tconst options = { ...DEFAULT_POSE_OPTIONS, ...mediapipeOptions };\n\tconst optionsKey = hashOptions({ ...options, textureName });\n\n\tconst nLandmarksMax = options.maxPoses * LANDMARK_COUNT + N_LANDMARK_METADATA_SLOTS;\n\tconst textureHeight = Math.ceil(nLandmarksMax / LANDMARKS_TEXTURE_WIDTH);\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL, gl, emitHook } = context;\n\n\t\tconst existingDetector = sharedDetectors.get(optionsKey);\n\t\tconst landmarksData =\n\t\t\texistingDetector?.landmarks.data ?? new Float32Array(LANDMARKS_TEXTURE_WIDTH * textureHeight * 4);\n\t\tconst sharedCanvas = existingDetector?.canvas ?? new OffscreenCanvas(1, 1);\n\t\tlet detector: Detector | null = null;\n\t\tlet skipHistoryWrite = false;\n\n\t\tfunction onResult() {\n\t\t\tif (!detector) return;\n\t\t\tconst { nPoses } = detector.state;\n\t\t\tconst nSlots = nPoses * LANDMARK_COUNT + N_LANDMARK_METADATA_SLOTS;\n\t\t\tconst rowsToUpdate = Math.ceil(nSlots / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tshaderPad.updateTextures(\n\t\t\t\t{\n\t\t\t\t\tu_poseLandmarksTex: {\n\t\t\t\t\t\tdata: detector.landmarks.data,\n\t\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\t\theight: rowsToUpdate,\n\t\t\t\t\t\tisPartial: true,\n\t\t\t\t\t},\n\t\t\t\t\tu_poseMask: detector.canvas,\n\t\t\t\t},\n\t\t\t\t{ skipHistoryWrite }\n\t\t\t);\n\t\t\tshaderPad.updateUniforms({ u_nPoses: nPoses });\n\t\t\temitHook('pose:result', detector.state.result);\n\t\t}\n\n\t\tasync function initializeDetector() {\n\t\t\tif (sharedDetectors.has(optionsKey)) {\n\t\t\t\tdetector = sharedDetectors.get(optionsKey)!;\n\t\t\t} else {\n\t\t\t\tconst [mediaPipe, { PoseLandmarker }] = await Promise.all([\n\t\t\t\t\tgetSharedFileset(),\n\t\t\t\t\timport('@mediapipe/tasks-vision'),\n\t\t\t\t]);\n\t\t\t\tconst poseLandmarker = await PoseLandmarker.createFromOptions(mediaPipe, {\n\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\tmodelAssetPath: options.modelPath,\n\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t},\n\t\t\t\t\tcanvas: sharedCanvas,\n\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\tnumPoses: options.maxPoses,\n\t\t\t\t\tminPoseDetectionConfidence: options.minPoseDetectionConfidence,\n\t\t\t\t\tminPosePresenceConfidence: options.minPosePresenceConfidence,\n\t\t\t\t\tminTrackingConfidence: options.minTrackingConfidence,\n\t\t\t\t\toutputSegmentationMasks: true,\n\t\t\t\t});\n\n\t\t\t\tconst maskShader = new ShaderPad(\n\t\t\t\t\t`#version 300 es\n\tprecision mediump float;\n\tin vec2 v_uv;\n\tout vec4 outColor;\n\tuniform sampler2D u_mask;\n\tuniform float u_poseIndex;\n\tvoid main() {\n\t\tivec2 texCoord = ivec2(v_uv * vec2(textureSize(u_mask, 0)));\n\t\tfloat confidence = texelFetch(u_mask, texCoord, 0).r;\n\t\tif (confidence < 0.01) discard;\n\t\toutColor = vec4(1.0, confidence, u_poseIndex, 1.0);\n\t}`,\n\t\t\t\t\t{ canvas: sharedCanvas }\n\t\t\t\t);\n\t\t\t\tmaskShader.initializeTexture('u_mask', dummyTexture);\n\t\t\t\tmaskShader.initializeUniform('u_poseIndex', 'float', 0);\n\n\t\t\t\tdetector = {\n\t\t\t\t\tlandmarker: poseLandmarker,\n\t\t\t\t\tcanvas: sharedCanvas,\n\t\t\t\t\tsubscribers: new Map(),\n\t\t\t\t\tmaxPoses: options.maxPoses,\n\t\t\t\t\tstate: {\n\t\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\t\tsource: null,\n\t\t\t\t\t\tvideoTime: -1,\n\t\t\t\t\t\tresultTimestamp: 0,\n\t\t\t\t\t\tresult: null,\n\t\t\t\t\t\tpending: Promise.resolve(),\n\t\t\t\t\t\tnPoses: 0,\n\t\t\t\t\t},\n\t\t\t\t\tlandmarks: {\n\t\t\t\t\t\tdata: landmarksData,\n\t\t\t\t\t\ttextureHeight,\n\t\t\t\t\t},\n\t\t\t\t\tmask: {\n\t\t\t\t\t\tshader: maskShader,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tsharedDetectors.set(optionsKey, detector);\n\t\t\t}\n\n\t\t\tdetector.subscribers.set(onResult, false);\n\t\t}\n\t\tconst initPromise = initializeDetector();\n\n\t\tshaderPad.on('init', () => {\n\t\t\tshaderPad.initializeUniform('u_maxPoses', 'int', options.maxPoses);\n\t\t\tshaderPad.initializeUniform('u_nPoses', 'int', 0);\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_poseLandmarksTex',\n\t\t\t\t{ data: landmarksData, width: LANDMARKS_TEXTURE_WIDTH, height: textureHeight },\n\t\t\t\t{ internalFormat: gl.RGBA32F, type: gl.FLOAT, minFilter: gl.NEAREST, magFilter: gl.NEAREST, history }\n\t\t\t);\n\t\t\tshaderPad.initializeTexture('u_poseMask', sharedCanvas, {\n\t\t\t\tpreserveY: true,\n\t\t\t\tminFilter: gl.NEAREST,\n\t\t\t\tmagFilter: gl.NEAREST,\n\t\t\t\thistory,\n\t\t\t});\n\t\t\tinitPromise.then(() => emitHook('pose:ready'));\n\t\t});\n\n\t\tshaderPad.on('initializeTexture', (name: string, source: TextureSource) => {\n\t\t\tif (name === textureName && isMediaPipeSource(source)) detectPoses(source);\n\t\t});\n\n\t\tshaderPad.on(\n\t\t\t'updateTextures',\n\t\t\t(updates: Record<string, TextureSource>, options?: { skipHistoryWrite?: boolean }) => {\n\t\t\t\tconst source = updates[textureName];\n\t\t\t\tif (isMediaPipeSource(source)) {\n\t\t\t\t\tskipHistoryWrite = options?.skipHistoryWrite ?? false;\n\t\t\t\t\tdetectPoses(source);\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tlet nDetectionCalls = 0;\n\t\tasync function detectPoses(source: MediaPipeSource) {\n\t\t\tconst now = performance.now();\n\t\t\tconst callOrder = ++nDetectionCalls;\n\n\t\t\tawait initPromise;\n\t\t\tif (!detector) return;\n\n\t\t\tdetector.state.pending = detector.state.pending.then(async () => {\n\t\t\t\tif (callOrder !== nDetectionCalls || !detector) return;\n\n\t\t\t\tconst requiredMode = source instanceof HTMLVideoElement ? 'VIDEO' : 'IMAGE';\n\t\t\t\tif (detector.state.runningMode !== requiredMode) {\n\t\t\t\t\tdetector.state.runningMode = requiredMode;\n\t\t\t\t\tawait detector.landmarker.setOptions({ runningMode: requiredMode });\n\t\t\t\t}\n\n\t\t\t\tlet shouldDetect = false;\n\n\t\t\t\tif (source !== detector.state.source) {\n\t\t\t\t\tdetector.state.source = source;\n\t\t\t\t\tdetector.state.videoTime = -1;\n\t\t\t\t\tshouldDetect = true;\n\t\t\t\t} else if (source instanceof HTMLVideoElement) {\n\t\t\t\t\tif (source.currentTime !== detector.state.videoTime) {\n\t\t\t\t\t\tdetector.state.videoTime = source.currentTime;\n\t\t\t\t\t\tshouldDetect = true;\n\t\t\t\t\t}\n\t\t\t\t} else if (!(source instanceof HTMLImageElement)) {\n\t\t\t\t\tif (now - detector.state.resultTimestamp > 2) {\n\t\t\t\t\t\tshouldDetect = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (shouldDetect) {\n\t\t\t\t\tlet result: PoseLandmarkerResult | undefined;\n\t\t\t\t\tif (source instanceof HTMLVideoElement) {\n\t\t\t\t\t\tif (source.videoWidth === 0 || source.videoHeight === 0 || source.readyState < 2) return;\n\t\t\t\t\t\tresult = detector.landmarker.detectForVideo(source, now);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (source.width === 0 || source.height === 0) return;\n\t\t\t\t\t\tresult = detector.landmarker.detect(source);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\tdetector.state.resultTimestamp = now;\n\t\t\t\t\t\tdetector.state.result = result;\n\t\t\t\t\t\tupdateLandmarksData(detector, result.landmarks);\n\t\t\t\t\t\tupdateMaskCanvas(detector, result.segmentationMasks);\n\t\t\t\t\t\tfor (const cb of detector.subscribers.keys()) {\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t\tdetector.subscribers.set(cb, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (detector.state.result && !detector.subscribers.get(onResult)) {\n\t\t\t\t\tonResult();\n\t\t\t\t\tdetector.subscribers.set(onResult, true);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tawait detector.state.pending;\n\t\t}\n\n\t\tshaderPad.on('destroy', () => {\n\t\t\tif (detector) {\n\t\t\t\tdetector.subscribers.delete(onResult);\n\t\t\t\tif (detector.subscribers.size === 0) {\n\t\t\t\t\tdetector.landmarker.close();\n\t\t\t\t\tdetector.mask.shader?.destroy();\n\t\t\t\t\tsharedDetectors.delete(optionsKey);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdetector = null;\n\t\t});\n\n\t\tconst { fn, historyParams } = generateGLSLFn(history);\n\t\tconst sampleMask = history\n\t\t\t? `int layer = (u_poseMaskFrameOffset - framesAgo + ${history}) % ${history};\n\tvec4 mask = texture(u_poseMask, vec3(pos, float(layer)));`\n\t\t\t: `vec4 mask = texture(u_poseMask, pos);`;\n\n\t\tinjectGLSL(`\nuniform int u_maxPoses;\nuniform int u_nPoses;\nuniform highp sampler2D${history ? 'Array' : ''} u_poseLandmarksTex;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_poseLandmarksTexFrameOffset;`\n\t\t\t\t: ''\n\t\t}\nuniform sampler2D${history ? 'Array' : ''} u_poseMask;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_poseMaskFrameOffset;`\n\t\t\t\t: ''\n\t\t}\n\n#define POSE_LANDMARK_LEFT_EYE ${LANDMARK_INDICES.LEFT_EYE}\n#define POSE_LANDMARK_RIGHT_EYE ${LANDMARK_INDICES.RIGHT_EYE}\n#define POSE_LANDMARK_LEFT_SHOULDER ${LANDMARK_INDICES.LEFT_SHOULDER}\n#define POSE_LANDMARK_RIGHT_SHOULDER ${LANDMARK_INDICES.RIGHT_SHOULDER}\n#define POSE_LANDMARK_LEFT_ELBOW ${LANDMARK_INDICES.LEFT_ELBOW}\n#define POSE_LANDMARK_RIGHT_ELBOW ${LANDMARK_INDICES.RIGHT_ELBOW}\n#define POSE_LANDMARK_LEFT_HIP ${LANDMARK_INDICES.LEFT_HIP}\n#define POSE_LANDMARK_RIGHT_HIP ${LANDMARK_INDICES.RIGHT_HIP}\n#define POSE_LANDMARK_LEFT_KNEE ${LANDMARK_INDICES.LEFT_KNEE}\n#define POSE_LANDMARK_RIGHT_KNEE ${LANDMARK_INDICES.RIGHT_KNEE}\n#define POSE_LANDMARK_BODY_CENTER ${LANDMARK_INDICES.BODY_CENTER}\n#define POSE_LANDMARK_LEFT_HAND_CENTER ${LANDMARK_INDICES.LEFT_HAND_CENTER}\n#define POSE_LANDMARK_RIGHT_HAND_CENTER ${LANDMARK_INDICES.RIGHT_HAND_CENTER}\n#define POSE_LANDMARK_LEFT_FOOT_CENTER ${LANDMARK_INDICES.LEFT_FOOT_CENTER}\n#define POSE_LANDMARK_RIGHT_FOOT_CENTER ${LANDMARK_INDICES.RIGHT_FOOT_CENTER}\n#define POSE_LANDMARK_TORSO_CENTER ${LANDMARK_INDICES.TORSO_CENTER}\n\n${fn(\n\t'int',\n\t'nPosesAt',\n\t'',\n\thistory\n\t\t? `\n\tint layer = (u_poseLandmarksTexFrameOffset - framesAgo + ${history}) % ${history};\n\treturn int(texelFetch(u_poseLandmarksTex, ivec3(0, 0, layer), 0).r + 0.5);`\n\t\t: `\n\treturn int(texelFetch(u_poseLandmarksTex, ivec2(0, 0), 0).r + 0.5);`\n)}\n${fn(\n\t'vec4',\n\t'poseLandmark',\n\t'int poseIndex, int landmarkIndex',\n\t`int i = ${N_LANDMARK_METADATA_SLOTS} + poseIndex * ${LANDMARK_COUNT} + landmarkIndex;\n\tint x = i % ${LANDMARKS_TEXTURE_WIDTH};\n\tint y = i / ${LANDMARKS_TEXTURE_WIDTH};${\n\t\thistory\n\t\t\t? `\n\tint layer = (u_poseLandmarksTexFrameOffset - framesAgo + ${history}) % ${history};\n\treturn texelFetch(u_poseLandmarksTex, ivec3(x, y, layer), 0);`\n\t\t\t: `\n\treturn texelFetch(u_poseLandmarksTex, ivec2(x, y), 0);`\n\t}`\n)}\n${fn(\n\t'vec2',\n\t'poseAt',\n\t'vec2 pos',\n\t`${sampleMask}\n\tfloat poseIndex = floor(mask.b * float(u_maxPoses) + 0.5) - 1.0;\n\treturn vec2(mask.g, poseIndex);`\n)}\n${fn('float', 'inPose', 'vec2 pos', `return step(0.0, poseAt(pos${historyParams}).x);`)}`);\n\t};\n}\n\nexport default pose;\n"],"mappings":"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","names":["STANDARD_LANDMARK_COUNT","CUSTOM_LANDMARK_COUNT","LANDMARK_COUNT","LANDMARK_INDICES","ALL_STANDARD_INDICES","_","i","LEFT_HAND_INDICES","RIGHT_HAND_INDICES","LEFT_FOOT_INDICES","RIGHT_FOOT_INDICES","TORSO_INDICES","LANDMARKS_TEXTURE_WIDTH","N_LANDMARK_METADATA_SLOTS","DEFAULT_POSE_OPTIONS","sharedDetectors","updateLandmarksData","detector","poses","data","nPoses","poseIdx","landmarks","lmIdx","landmark","dataIdx","bodyCenter","calculateBoundingBoxCenter","bodyCenterIdx","leftHandCenter","leftHandCenterIdx","rightHandCenter","rightHandCenterIdx","leftFootCenter","leftFootCenterIdx","rightFootCenter","rightFootCenterIdx","torsoCenter","torsoCenterIdx","updateMaskCanvas","segmentationMasks","shader","maxPoses","segMask","pose","config","textureName","history","mediapipeOptions","options","optionsKey","hashOptions","nLandmarksMax","textureHeight","shaderPad","context","injectGLSL","gl","emitHook","existingDetector","landmarksData","sharedCanvas","skipHistoryWrite","onResult","nSlots","rowsToUpdate","initializeDetector","mediaPipe","PoseLandmarker","getSharedFileset","poseLandmarker","maskShader","index_default","dummyTexture","initPromise","name","source","isMediaPipeSource","detectPoses","updates","nDetectionCalls","now","callOrder","requiredMode","shouldDetect","result","cb","fn","historyParams","generateGLSLFn","sampleMask","pose_default"]}
@@ -1,6 +1,6 @@
1
1
  import ShaderPad, { PluginContext } from '../index.mjs';
2
2
 
3
- declare module '../index' {
3
+ declare module '..' {
4
4
  interface ShaderPad {
5
5
  save(filename: string, text?: string): Promise<void>;
6
6
  }
@@ -1,6 +1,6 @@
1
1
  import ShaderPad, { PluginContext } from '../index.js';
2
2
 
3
- declare module '../index' {
3
+ declare module '..' {
4
4
  interface ShaderPad {
5
5
  save(filename: string, text?: string): Promise<void>;
6
6
  }
@@ -1,2 +1,2 @@
1
- "use strict";var c=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var v=(a,e)=>{for(var r in e)c(a,r,{get:e[r],enumerable:!0})},f=(a,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of h(e))!p.call(a,t)&&t!==r&&c(a,t,{get:()=>e[t],enumerable:!(o=g(e,t))||o.enumerable});return a};var u=a=>f(c({},"__esModule",{value:!0}),a);var x={};v(x,{default:()=>b});module.exports=u(x);function w(){return function(a,e){let{gl:r,canvas:o}=e,t=document.createElement("a");a.save=async function(n,d){r.clear(r.COLOR_BUFFER_BIT),r.drawArrays(r.TRIANGLES,0,6),n&&!`${n}`.toLowerCase().endsWith(".png")&&(n=`${n}.png`),n=n||"export.png";let s=await(o instanceof HTMLCanvasElement?new Promise(i=>o.toBlob(i,"image/png")):o.convertToBlob({type:"image/png"}));if(navigator.share)try{let l={files:[new File([s],n,{type:s.type})]};d&&(l.text=d),await navigator.share(l);return}catch{}t.download=n,t.href=URL.createObjectURL(s),t.click(),URL.revokeObjectURL(t.href)}}}var b=w;
1
+ "use strict";var c=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var v=(a,e)=>{for(var r in e)c(a,r,{get:e[r],enumerable:!0})},f=(a,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of h(e))!p.call(a,t)&&t!==r&&c(a,t,{get:()=>e[t],enumerable:!(o=g(e,t))||o.enumerable});return a};var u=a=>f(c({},"__esModule",{value:!0}),a);var L={};v(L,{default:()=>b});module.exports=u(L);function w(){return function(a,e){let{gl:r,canvas:o}=e,t=document.createElement("a");a.save=async function(n,d){r.clear(r.COLOR_BUFFER_BIT),r.drawArrays(r.TRIANGLES,0,6),n&&!`${n}`.toLowerCase().endsWith(".png")&&(n=`${n}.png`),n=n||"export.png";let s=await(o instanceof HTMLCanvasElement?new Promise(i=>o.toBlob(i,"image/png")):o.convertToBlob({type:"image/png"}));if(navigator.share)try{let l={files:[new File([s],n,{type:s.type})]};d&&(l.text=d),await navigator.share(l);return}catch{}t.download=n,t.href=URL.createObjectURL(s),t.click(),URL.revokeObjectURL(t.href)}}}var b=w;
2
2
  //# sourceMappingURL=save.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/save.ts"],"sourcesContent":["import ShaderPad, { PluginContext } from '../index';\n\ndeclare module '../index' {\n\tinterface ShaderPad {\n\t\tsave(filename: string, text?: string): Promise<void>;\n\t}\n}\n\nfunction save() {\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { gl, canvas } = context;\n\t\tconst downloadLink = document.createElement('a');\n\n\t\t(shaderPad as any).save = async function (filename: string, text?: string) {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\t\tfilename = `${filename}.png`;\n\t\t\t}\n\t\t\tfilename = filename || 'export.png';\n\n\t\t\tconst blob: Blob = await (canvas instanceof HTMLCanvasElement\n\t\t\t\t? new Promise(resolve => canvas.toBlob(resolve as BlobCallback, 'image/png'))\n\t\t\t\t: canvas.convertToBlob({ type: 'image/png' }));\n\n\t\t\tif (navigator.share) {\n\t\t\t\ttry {\n\t\t\t\t\tconst file = new File([blob], filename, { type: blob.type });\n\t\t\t\t\tconst shareData: ShareData = { files: [file] };\n\t\t\t\t\tif (text) shareData.text = text;\n\t\t\t\t\tawait navigator.share(shareData);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (_swallowedError) {}\n\t\t\t}\n\n\t\t\tdownloadLink.download = filename;\n\t\t\tdownloadLink.href = URL.createObjectURL(blob);\n\t\t\tdownloadLink.click();\n\t\t\tURL.revokeObjectURL(downloadLink.href);\n\t\t};\n\t};\n}\n\nexport type WithSave<T extends ShaderPad> = T & {\n\tsave(filename: string, text?: string): Promise<void>;\n};\n\nexport default save;\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAQA,SAASI,GAAO,CACf,OAAO,SAAUC,EAAsBC,EAAwB,CAC9D,GAAM,CAAE,GAAAC,EAAI,OAAAC,CAAO,EAAIF,EACjBG,EAAe,SAAS,cAAc,GAAG,EAE9CJ,EAAkB,KAAO,eAAgBK,EAAkBC,EAAe,CAC1EJ,EAAG,MAAMA,EAAG,gBAAgB,EAC5BA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,EAE5BG,GAAY,CAAC,GAAGA,CAAQ,GAAG,YAAY,EAAE,SAAS,MAAM,IAC3DA,EAAW,GAAGA,CAAQ,QAEvBA,EAAWA,GAAY,aAEvB,IAAME,EAAa,MAAOJ,aAAkB,kBACzC,IAAI,QAAQK,GAAWL,EAAO,OAAOK,EAAyB,WAAW,CAAC,EAC1EL,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,GAE7C,GAAI,UAAU,MACb,GAAI,CAEH,IAAMM,EAAuB,CAAE,MAAO,CADzB,IAAI,KAAK,CAACF,CAAI,EAAGF,EAAU,CAAE,KAAME,EAAK,IAAK,CAAC,CAChB,CAAE,EACzCD,IAAMG,EAAU,KAAOH,GAC3B,MAAM,UAAU,MAAMG,CAAS,EAC/B,MACD,MAA0B,CAAC,CAG5BL,EAAa,SAAWC,EACxBD,EAAa,KAAO,IAAI,gBAAgBG,CAAI,EAC5CH,EAAa,MAAM,EACnB,IAAI,gBAAgBA,EAAa,IAAI,CACtC,CACD,CACD,CAMA,IAAOP,EAAQE","names":["save_exports","__export","save_default","__toCommonJS","save","shaderPad","context","gl","canvas","downloadLink","filename","text","blob","resolve","shareData"]}
1
+ {"version":3,"sources":["../../src/plugins/save.ts"],"sourcesContent":["import ShaderPad, { PluginContext } from '..';\n\ndeclare module '..' {\n\tinterface ShaderPad {\n\t\tsave(filename: string, text?: string): Promise<void>;\n\t}\n}\n\nfunction save() {\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { gl, canvas } = context;\n\t\tconst downloadLink = document.createElement('a');\n\n\t\t(shaderPad as any).save = async function (filename: string, text?: string) {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\t\tfilename = `${filename}.png`;\n\t\t\t}\n\t\t\tfilename = filename || 'export.png';\n\n\t\t\tconst blob: Blob = await (canvas instanceof HTMLCanvasElement\n\t\t\t\t? new Promise(resolve => canvas.toBlob(resolve as BlobCallback, 'image/png'))\n\t\t\t\t: canvas.convertToBlob({ type: 'image/png' }));\n\n\t\t\tif (navigator.share) {\n\t\t\t\ttry {\n\t\t\t\t\tconst file = new File([blob], filename, { type: blob.type });\n\t\t\t\t\tconst shareData: ShareData = { files: [file] };\n\t\t\t\t\tif (text) shareData.text = text;\n\t\t\t\t\tawait navigator.share(shareData);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (_swallowedError) {}\n\t\t\t}\n\n\t\t\tdownloadLink.download = filename;\n\t\t\tdownloadLink.href = URL.createObjectURL(blob);\n\t\t\tdownloadLink.click();\n\t\t\tURL.revokeObjectURL(downloadLink.href);\n\t\t};\n\t};\n}\n\nexport type WithSave<T extends ShaderPad> = T & {\n\tsave(filename: string, text?: string): Promise<void>;\n};\n\nexport default save;\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAQA,SAASI,GAAO,CACf,OAAO,SAAUC,EAAsBC,EAAwB,CAC9D,GAAM,CAAE,GAAAC,EAAI,OAAAC,CAAO,EAAIF,EACjBG,EAAe,SAAS,cAAc,GAAG,EAE9CJ,EAAkB,KAAO,eAAgBK,EAAkBC,EAAe,CAC1EJ,EAAG,MAAMA,EAAG,gBAAgB,EAC5BA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,EAE5BG,GAAY,CAAC,GAAGA,CAAQ,GAAG,YAAY,EAAE,SAAS,MAAM,IAC3DA,EAAW,GAAGA,CAAQ,QAEvBA,EAAWA,GAAY,aAEvB,IAAME,EAAa,MAAOJ,aAAkB,kBACzC,IAAI,QAAQK,GAAWL,EAAO,OAAOK,EAAyB,WAAW,CAAC,EAC1EL,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,GAE7C,GAAI,UAAU,MACb,GAAI,CAEH,IAAMM,EAAuB,CAAE,MAAO,CADzB,IAAI,KAAK,CAACF,CAAI,EAAGF,EAAU,CAAE,KAAME,EAAK,IAAK,CAAC,CAChB,CAAE,EACzCD,IAAMG,EAAU,KAAOH,GAC3B,MAAM,UAAU,MAAMG,CAAS,EAC/B,MACD,MAA0B,CAAC,CAG5BL,EAAa,SAAWC,EACxBD,EAAa,KAAO,IAAI,gBAAgBG,CAAI,EAC5CH,EAAa,MAAM,EACnB,IAAI,gBAAgBA,EAAa,IAAI,CACtC,CACD,CACD,CAMA,IAAOP,EAAQE","names":["save_exports","__export","save_default","__toCommonJS","save","shaderPad","context","gl","canvas","downloadLink","filename","text","blob","resolve","shareData"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/save.ts"],"sourcesContent":["import ShaderPad, { PluginContext } from '../index';\n\ndeclare module '../index' {\n\tinterface ShaderPad {\n\t\tsave(filename: string, text?: string): Promise<void>;\n\t}\n}\n\nfunction save() {\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { gl, canvas } = context;\n\t\tconst downloadLink = document.createElement('a');\n\n\t\t(shaderPad as any).save = async function (filename: string, text?: string) {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\t\tfilename = `${filename}.png`;\n\t\t\t}\n\t\t\tfilename = filename || 'export.png';\n\n\t\t\tconst blob: Blob = await (canvas instanceof HTMLCanvasElement\n\t\t\t\t? new Promise(resolve => canvas.toBlob(resolve as BlobCallback, 'image/png'))\n\t\t\t\t: canvas.convertToBlob({ type: 'image/png' }));\n\n\t\t\tif (navigator.share) {\n\t\t\t\ttry {\n\t\t\t\t\tconst file = new File([blob], filename, { type: blob.type });\n\t\t\t\t\tconst shareData: ShareData = { files: [file] };\n\t\t\t\t\tif (text) shareData.text = text;\n\t\t\t\t\tawait navigator.share(shareData);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (_swallowedError) {}\n\t\t\t}\n\n\t\t\tdownloadLink.download = filename;\n\t\t\tdownloadLink.href = URL.createObjectURL(blob);\n\t\t\tdownloadLink.click();\n\t\t\tURL.revokeObjectURL(downloadLink.href);\n\t\t};\n\t};\n}\n\nexport type WithSave<T extends ShaderPad> = T & {\n\tsave(filename: string, text?: string): Promise<void>;\n};\n\nexport default save;\n"],"mappings":"AAQA,SAASA,GAAO,CACf,OAAO,SAAUC,EAAsBC,EAAwB,CAC9D,GAAM,CAAE,GAAAC,EAAI,OAAAC,CAAO,EAAIF,EACjBG,EAAe,SAAS,cAAc,GAAG,EAE9CJ,EAAkB,KAAO,eAAgBK,EAAkBC,EAAe,CAC1EJ,EAAG,MAAMA,EAAG,gBAAgB,EAC5BA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,EAE5BG,GAAY,CAAC,GAAGA,CAAQ,GAAG,YAAY,EAAE,SAAS,MAAM,IAC3DA,EAAW,GAAGA,CAAQ,QAEvBA,EAAWA,GAAY,aAEvB,IAAME,EAAa,MAAOJ,aAAkB,kBACzC,IAAI,QAAQK,GAAWL,EAAO,OAAOK,EAAyB,WAAW,CAAC,EAC1EL,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,GAE7C,GAAI,UAAU,MACb,GAAI,CAEH,IAAMM,EAAuB,CAAE,MAAO,CADzB,IAAI,KAAK,CAACF,CAAI,EAAGF,EAAU,CAAE,KAAME,EAAK,IAAK,CAAC,CAChB,CAAE,EACzCD,IAAMG,EAAU,KAAOH,GAC3B,MAAM,UAAU,MAAMG,CAAS,EAC/B,MACD,MAA0B,CAAC,CAG5BL,EAAa,SAAWC,EACxBD,EAAa,KAAO,IAAI,gBAAgBG,CAAI,EAC5CH,EAAa,MAAM,EACnB,IAAI,gBAAgBA,EAAa,IAAI,CACtC,CACD,CACD,CAMA,IAAOM,EAAQX","names":["save","shaderPad","context","gl","canvas","downloadLink","filename","text","blob","resolve","shareData","save_default"]}
1
+ {"version":3,"sources":["../../src/plugins/save.ts"],"sourcesContent":["import ShaderPad, { PluginContext } from '..';\n\ndeclare module '..' {\n\tinterface ShaderPad {\n\t\tsave(filename: string, text?: string): Promise<void>;\n\t}\n}\n\nfunction save() {\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { gl, canvas } = context;\n\t\tconst downloadLink = document.createElement('a');\n\n\t\t(shaderPad as any).save = async function (filename: string, text?: string) {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\t\tfilename = `${filename}.png`;\n\t\t\t}\n\t\t\tfilename = filename || 'export.png';\n\n\t\t\tconst blob: Blob = await (canvas instanceof HTMLCanvasElement\n\t\t\t\t? new Promise(resolve => canvas.toBlob(resolve as BlobCallback, 'image/png'))\n\t\t\t\t: canvas.convertToBlob({ type: 'image/png' }));\n\n\t\t\tif (navigator.share) {\n\t\t\t\ttry {\n\t\t\t\t\tconst file = new File([blob], filename, { type: blob.type });\n\t\t\t\t\tconst shareData: ShareData = { files: [file] };\n\t\t\t\t\tif (text) shareData.text = text;\n\t\t\t\t\tawait navigator.share(shareData);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (_swallowedError) {}\n\t\t\t}\n\n\t\t\tdownloadLink.download = filename;\n\t\t\tdownloadLink.href = URL.createObjectURL(blob);\n\t\t\tdownloadLink.click();\n\t\t\tURL.revokeObjectURL(downloadLink.href);\n\t\t};\n\t};\n}\n\nexport type WithSave<T extends ShaderPad> = T & {\n\tsave(filename: string, text?: string): Promise<void>;\n};\n\nexport default save;\n"],"mappings":"AAQA,SAASA,GAAO,CACf,OAAO,SAAUC,EAAsBC,EAAwB,CAC9D,GAAM,CAAE,GAAAC,EAAI,OAAAC,CAAO,EAAIF,EACjBG,EAAe,SAAS,cAAc,GAAG,EAE9CJ,EAAkB,KAAO,eAAgBK,EAAkBC,EAAe,CAC1EJ,EAAG,MAAMA,EAAG,gBAAgB,EAC5BA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,EAE5BG,GAAY,CAAC,GAAGA,CAAQ,GAAG,YAAY,EAAE,SAAS,MAAM,IAC3DA,EAAW,GAAGA,CAAQ,QAEvBA,EAAWA,GAAY,aAEvB,IAAME,EAAa,MAAOJ,aAAkB,kBACzC,IAAI,QAAQK,GAAWL,EAAO,OAAOK,EAAyB,WAAW,CAAC,EAC1EL,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,GAE7C,GAAI,UAAU,MACb,GAAI,CAEH,IAAMM,EAAuB,CAAE,MAAO,CADzB,IAAI,KAAK,CAACF,CAAI,EAAGF,EAAU,CAAE,KAAME,EAAK,IAAK,CAAC,CAChB,CAAE,EACzCD,IAAMG,EAAU,KAAOH,GAC3B,MAAM,UAAU,MAAMG,CAAS,EAC/B,MACD,MAA0B,CAAC,CAG5BL,EAAa,SAAWC,EACxBD,EAAa,KAAO,IAAI,gBAAgBG,CAAI,EAC5CH,EAAa,MAAM,EACnB,IAAI,gBAAgBA,EAAa,IAAI,CACtC,CACD,CACD,CAMA,IAAOM,EAAQX","names":["save","shaderPad","context","gl","canvas","downloadLink","filename","text","blob","resolve","shareData","save_default"]}
@@ -3,6 +3,7 @@ import ShaderPad, { PluginContext } from '../index.mjs';
3
3
  interface SegmenterPluginOptions {
4
4
  modelPath?: string;
5
5
  outputCategoryMask?: boolean;
6
+ history?: number;
6
7
  }
7
8
  declare function segmenter(config: {
8
9
  textureName: string;
@@ -3,6 +3,7 @@ import ShaderPad, { PluginContext } from '../index.js';
3
3
  interface SegmenterPluginOptions {
4
4
  modelPath?: string;
5
5
  outputCategoryMask?: boolean;
6
+ history?: number;
6
7
  }
7
8
  declare function segmenter(config: {
8
9
  textureName: string;
@@ -1,13 +1,18 @@
1
- "use strict";var k=Object.create;var R=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var B=(o,t)=>{for(var e in t)R(o,e,{get:t[e],enumerable:!0})},I=(o,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of D(t))!G.call(o,i)&&i!==e&&R(o,i,{get:()=>t[i],enumerable:!(r=H(t,i))||r.enumerable});return o};var W=(o,t,e)=>(e=o!=null?k(z(o)):{},I(t||!o||!o.__esModule?R(e,"default",{value:o,enumerable:!0}):e,o)),$=o=>I(R({},"__esModule",{value:!0}),o);var Z={};B(Z,{default:()=>q});module.exports=$(Z);var X=`#version 300 es
1
+ "use strict";var Y=Object.create;var P=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var q=(o,t)=>{for(var e in t)P(o,e,{get:t[e],enumerable:!0})},C=(o,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of V(t))!K.call(o,i)&&i!==e&&P(o,i,{get:()=>t[i],enumerable:!(s=N(t,i))||s.enumerable});return o};var k=(o,t,e)=>(e=o!=null?Y(j(o)):{},C(t||!o||!o.__esModule?P(e,"default",{value:o,enumerable:!0}):e,o)),Z=o=>C(P({},"__esModule",{value:!0}),o);var ae={};q(ae,{default:()=>oe});module.exports=Z(ae);var J=`#version 300 es
2
2
  in vec2 aPosition;
3
3
  out vec2 v_uv;
4
4
  void main() {
5
5
  v_uv = aPosition * 0.5 + 0.5;
6
6
  gl_Position = vec4(aPosition, 0.0, 1.0);
7
- }`,Y=33.333333333333336,b=Symbol("u_history"),w=Symbol("__SHADERPAD_BUFFER");function N(o,t){if(!t?.length)return o;let e=o.split(`
8
- `),r=e.findLastIndex(i=>{let n=i.trimStart();return n.startsWith("precision ")||n.startsWith("#version ")})+1;return e.splice(r,0,...t),e.join(`
9
- `)}function C(o){return o instanceof WebGLTexture?{width:0,height:0}:o instanceof HTMLVideoElement?{width:o.videoWidth,height:o.videoHeight}:o instanceof HTMLImageElement?{width:o.naturalWidth??o.width,height:o.naturalHeight??o.height}:{width:o.width,height:o.height}}function E(o){return typeof o=="symbol"?o.description??"":o}var L=class{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(t,{canvas:e,plugins:r,history:i,debug:n,...a}={}){if(this.canvas=e||document.createElement("canvas"),!e){this.isInternalCanvas=!0;let d=this.canvas;d.style.position="fixed",d.style.inset="0",d.style.height="100dvh",d.style.width="100dvw",document.body.appendChild(d)}let s=this.canvas.getContext("webgl2",{antialias:!1});if(!s)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.gl=s,this.textureUnitPool={free:[],next:0,max:s.getParameter(s.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.textureOptions=a;let{internalFormat:m,type:u}=a;(u===s.FLOAT||u===s.HALF_FLOAT||m===s.RGBA16F||m===s.RGBA32F||m===s.R16F||m===s.R32F||m===s.RG16F||m===s.RG32F)&&!s.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=n??(typeof process<"u"&&!1),this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let g=[];r&&r.forEach(d=>d(this,{gl:s,canvas:this.canvas,injectGLSL:_=>{g.push(_)},emitHook:this.emitHook.bind(this)}));let f=this.gl.createProgram();if(!f)throw new Error("Failed to create WebGL program");this.program=f;let T=this.createShader(this.gl.VERTEX_SHADER,X),p=this.createShader(s.FRAGMENT_SHADER,N(t,g));if(s.attachShader(f,T),s.attachShader(f,p),s.linkProgram(f),s.deleteShader(T),s.deleteShader(p),!s.getProgramParameter(f,s.LINK_STATUS))throw console.error("Program link error:",s.getProgramInfoLog(f)),s.deleteProgram(f),new Error("Failed to link WebGL program");this.aPositionLocation=s.getAttribLocation(f,"aPosition");let v=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=s.createBuffer(),s.bindBuffer(s.ARRAY_BUFFER,this.buffer),s.bufferData(s.ARRAY_BUFFER,v,s.STATIC_DRAW),s.viewport(0,0,s.drawingBufferWidth,s.drawingBufferHeight),s.enableVertexAttribArray(this.aPositionLocation),s.vertexAttribPointer(this.aPositionLocation,2,s.FLOAT,!1,0,0),s.useProgram(f),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.historyDepth>0&&(this._initializeTexture(w,this.canvas,{...this.textureOptions}),this._initializeTexture(b,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.intermediateFbo=s.createFramebuffer()),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners(),this.emitHook("init")}emitHook(t,...e){this.hooks.get(t)?.forEach(r=>r.call(this,...e))}on(t,e){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(e)}off(t,e){let r=this.hooks.get(t);r&&r.splice(r.indexOf(e),1)}createShader(t,e){let r=this.gl.createShader(t);if(this.gl.shaderSource(r,e),this.gl.compileShader(r),!this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",e),console.error(this.gl.getShaderInfoLog(r)),this.gl.deleteShader(r),new Error("Shader compilation failed");return r}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),e=this.lastResizeTime+Y-t;e<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),e)}handleResize(){if(!(this.canvas instanceof HTMLCanvasElement))return;let t=window.devicePixelRatio||1,e=this.canvas.clientWidth*t,r=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==e||this.canvas.height!==r)&&(this.canvas.width=e,this.canvas.height=r),this.emitHook("resize",e,r)}addEventListeners(){let t=this.canvas,e=(i,n)=>{if(!this.uniforms.has("u_cursor"))return;let a=t.getBoundingClientRect();this.cursorPosition[0]=(i-a.left)/a.width,this.cursorPosition[1]=1-(n-a.top)/a.height,this.updateUniforms({u_cursor:this.cursorPosition})},r=(i,n,a)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let s=t.getBoundingClientRect(),m=n,u=a;this.clickPosition[0]=(m-s.left)/s.width,this.clickPosition[1]=1-(u-s.top)/s.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let n=i;this.isTouchDevice||e(n.clientX,n.clientY)}),this.eventListeners.set("mousedown",i=>{let n=i;this.isTouchDevice||n.button===0&&(this.isMouseDown=!0,r(!0,n.clientX,n.clientY))}),this.eventListeners.set("mouseup",i=>{let n=i;this.isTouchDevice||n.button===0&&r(!1)}),this.eventListeners.set("touchmove",i=>{let n=i;n.touches.length>0&&e(n.touches[0].clientX,n.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let n=i;this.isTouchDevice=!0,n.touches.length>0&&(e(n.touches[0].clientX,n.touches[0].clientY),r(!0,n.touches[0].clientX,n.touches[0].clientY))}),this.eventListeners.set("touchend",i=>{i.touches.length===0&&r(!1)}),this.eventListeners.forEach((i,n)=>{t.addEventListener(n,i)})}updateResolution(){let t=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...t),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:t}):this.initializeUniform("u_resolution","float",t),this.historyDepth>0&&(this.resizeTexture(b,...t),this.resizeTexture(w,...t)),this.emitHook("updateResolution",...t)}resizeTexture(t,e,r){let i=this.textures.get(t);if(!i||i.width===e&&i.height===r)return;this.gl.deleteTexture(i.texture),i.width=e,i.height=r;let{texture:n}=this.createTexture(t,i);i.texture=n,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(t){let e=this.textures.get(t);if(e)return e.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(t){let e=this.textures.get(t);e&&this.textureUnitPool.free.push(e.unitIndex)}resolveTextureOptions(t){let{gl:e}=this,r=t?.type??e.UNSIGNED_BYTE;return{type:r,format:t?.format??e.RGBA,internalFormat:t?.internalFormat??(r===e.FLOAT?e.RGBA32F:r===e.HALF_FLOAT?e.RGBA16F:e.RGBA8),minFilter:t?.minFilter??e.LINEAR,magFilter:t?.magFilter??e.LINEAR,wrapS:t?.wrapS??e.CLAMP_TO_EDGE,wrapT:t?.wrapT??e.CLAMP_TO_EDGE,preserveY:t?.preserveY}}clearHistoryTextureLayers(t){if(!t.history)return;let e=this.gl,{type:r,format:i}=t.options,n=t.width*t.height*4,a=r===e.FLOAT?new Float32Array(n):r===e.HALF_FLOAT?new Uint16Array(n):new Uint8Array(n);e.activeTexture(e.TEXTURE0+t.unitIndex),e.bindTexture(e.TEXTURE_2D_ARRAY,t.texture);for(let s=0;s<t.history.depth;++s)e.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,s,t.width,t.height,1,i,r,a)}initializeUniform(t,e,r,i){let n=i?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(e!=="float"&&e!=="int")throw new Error(`Invalid uniform type: ${e}. Expected 'float' or 'int'.`);if(n&&!(Array.isArray(r)&&r.length===n))throw new Error(`${t} array length mismatch: must initialize with ${n} elements.`);let a=this.gl.getUniformLocation(this.program,t);if(!a&&n&&(a=this.gl.getUniformLocation(this.program,`${t}[0]`)),!a){this.log(`${t} not in shader. Skipping initialization.`);return}let s=n?r[0]:r,m=Array.isArray(s)?s.length:1;this.uniforms.set(t,{type:e,length:m,location:a,arrayLength:n});try{this.updateUniforms({[t]:r})}catch(u){throw this.uniforms.delete(t),u}this.emitHook("initializeUniform",...arguments)}log(...t){this.debug&&console.debug(...t)}updateUniforms(t,e){this.gl.useProgram(this.program),Object.entries(t).forEach(([r,i])=>{let n=this.uniforms.get(r);if(!n){this.log(`${r} not in shader. Skipping update.`);return}let a=`uniform${n.length}${n.type.charAt(0)}`;if(n.arrayLength){if(!Array.isArray(i))throw new Error(`${r} is an array, but the value passed to updateUniforms is not an array.`);let s=i.length;if(!s)return;if(s>n.arrayLength)throw new Error(`${r} received ${s} values, but maximum length is ${n.arrayLength}.`);if(i.some(l=>(Array.isArray(l)?l.length:1)!==n.length))throw new Error(`Tried to update ${r} with some elements that are not length ${n.length}.`);let m=new(n.type==="float"?Float32Array:Int32Array)(i.flat()),u=n.location;if(e?.startIndex){let l=this.gl.getUniformLocation(this.program,`${r}[${e.startIndex}]`);if(!l)throw new Error(`${r}[${e.startIndex}] not in shader. Did you pass an invalid startIndex?`);u=l}this.gl[a+"v"](u,m)}else{if(Array.isArray(i)||(i=[i]),i.length!==n.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${n.length}.`);this.gl[a](n.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(t,e){let{width:r,height:i}=e,n=e.history?.depth??0,a=this.gl.createTexture();if(!a)throw new Error("Failed to create texture");let s=e.unitIndex;if(typeof s!="number")try{s=this.reserveTextureUnit(t)}catch(g){throw this.gl.deleteTexture(a),g}let m=n>0,u=m?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:l}=e;return this.gl.activeTexture(this.gl.TEXTURE0+s),this.gl.bindTexture(u,a),this.gl.texParameteri(u,this.gl.TEXTURE_WRAP_S,l.wrapS),this.gl.texParameteri(u,this.gl.TEXTURE_WRAP_T,l.wrapT),this.gl.texParameteri(u,this.gl.TEXTURE_MIN_FILTER,l.minFilter),this.gl.texParameteri(u,this.gl.TEXTURE_MAG_FILTER,l.magFilter),m?this.gl.texStorage3D(u,1,l.internalFormat,r,i,n):t===w&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,l.internalFormat,r,i,0,l.format,l.type,null),{texture:a,unitIndex:s}}_initializeTexture(t,e,r){if(this.textures.has(t))throw new Error(`Texture '${E(t)}' is already initialized.`);let{history:i=0,...n}=r??{},{width:a,height:s}=C(e);if(!a||!s)throw new Error("Texture source must have valid dimensions");let m={width:a,height:s,options:this.resolveTextureOptions(n)};i>0&&(m.history={depth:i,writeIndex:0});let{texture:u,unitIndex:l}=this.createTexture(t,m),g={texture:u,unitIndex:l,...m};i>0&&(this.initializeUniform(`${E(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(g)),this.textures.set(t,g),this.updateTexture(t,e);let f=this.gl.getUniformLocation(this.program,E(t));f&&this.gl.uniform1i(f,l)}initializeTexture(t,e,r){this._initializeTexture(t,e,r),this.emitHook("initializeTexture",...arguments)}updateTextures(t,e){Object.entries(t).forEach(([r,i])=>{this.updateTexture(r,i,e)}),this.emitHook("updateTextures",...arguments)}updateTexture(t,e,r){let i=this.textures.get(t);if(!i)throw new Error(`Texture '${E(t)}' is not initialized.`);if(e instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e);return}let{width:n,height:a}=C(e);if(!n||!a)return;let s="isPartial"in e&&e.isPartial;s||this.resizeTexture(t,n,a);let u=!("data"in e&&e.data)&&!i.options?.preserveY,l=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),!r?.skipHistoryWrite){this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,u),this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,i.history.writeIndex,n,a,1,i.options.format,i.options.type,e.data??e),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l);let g=`${E(t)}FrameOffset`;this.updateUniforms({[g]:i.history.writeIndex}),i.history.writeIndex=(i.history.writeIndex+1)%i.history.depth}}else 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,u),s?this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,e.x??0,e.y??0,n,a,i.options.format,i.options.type,e.data):this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,n,a,0,i.options.format,i.options.type,e.data??e),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l)}draw(t){this.emitHook("beforeDraw",...arguments);let e=this.gl,r=e.drawingBufferWidth,i=e.drawingBufferHeight,n=this.textures.get(b),a=this.textures.get(w),s=n&&!t?.skipHistoryWrite;s&&(e.bindFramebuffer(e.FRAMEBUFFER,this.intermediateFbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,a.texture,0)),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.buffer),e.vertexAttribPointer(this.aPositionLocation,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(this.aPositionLocation),e.viewport(0,0,r,i),t?.skipClear||e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLES,0,6),s&&(e.bindTexture(e.TEXTURE_2D_ARRAY,n.texture),e.copyTexSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,n.history.writeIndex,0,0,r,i),e.bindFramebuffer(e.READ_FRAMEBUFFER,this.intermediateFbo),e.bindFramebuffer(e.DRAW_FRAMEBUFFER,null),e.blitFramebuffer(0,0,r,i,0,0,r,i,e.COLOR_BUFFER_BIT,e.NEAREST),e.bindFramebuffer(e.FRAMEBUFFER,null)),this.emitHook("afterDraw",...arguments)}step(t,e){this.emitHook("beforeStep",...arguments);let r={};this.uniforms.has("u_time")&&(r.u_time=t),this.uniforms.has("u_frame")&&(r.u_frame=this.frame),this.updateUniforms(r),this.draw(e);let i=this.textures.get(b);if(i&&!e?.skipHistoryWrite){let{writeIndex:n,depth:a}=i.history;this.updateUniforms({[`${E(b)}FrameOffset`]:n}),i.history.writeIndex=(n+1)%a}++this.frame,this.emitHook("afterStep",...arguments)}play(t,e){this.pause();let r=i=>{i=(i-this.startTime)/1e3;let n=e?.(i,this.frame)??void 0;this.step(i,n),this.animationFrameId=requestAnimationFrame(r),t?.(i,this.frame)};this.animationFrameId=requestAnimationFrame(r),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(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),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((t,e)=>{this.canvas.removeEventListener(e,t)}),this.program&&this.gl.deleteProgram(this.program),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(t=>{this.gl.deleteTexture(t.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()}},M=L;var V={data:new Uint8Array(4),width:1,height:1};function j(o){let t=Array.from({length:o},(r,i)=>`uniform sampler2D u_confidenceMask${i};`).join(`
10
- `),e=Array.from({length:o},(r,i)=>` ${i>0?"else ":""}if (i == ${i}) c = texelFetch(u_confidenceMask${i}, texCoord, 0).r;`).join(`
7
+ }`,Q=33.333333333333336,ee=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),w=Symbol("u_history"),A=Symbol("__SHADERPAD_BUFFER");function te(o,t){if(!t?.length)return o;let e=o.split(`
8
+ `),s=e.findLastIndex(i=>{let r=i.trimStart();return r.startsWith("precision ")||r.startsWith("#version ")})+1;return e.splice(s,0,...t),e.join(`
9
+ `)}function D(o){return o instanceof WebGLTexture?{width:0,height:0}:o instanceof M?{width:o.canvas.width,height:o.canvas.height}:o instanceof HTMLVideoElement?{width:o.videoWidth,height:o.videoHeight}:o instanceof HTMLImageElement?{width:o.naturalWidth??o.width,height:o.naturalHeight??o.height}:{width:o.width,height:o.height}}function F(o){return typeof o=="symbol"?o.description??"":o}var M=class o{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(t,{canvas:e,plugins:s,history:i,debug:r,...a}={}){if(this.canvas=e||document.createElement("canvas"),!e){this.isInternalCanvas=!0;let g=this.canvas;g.style.position="fixed",g.style.inset="0",g.style.height="100dvh",g.style.width="100dvw",document.body.appendChild(g)}if(this.canvas instanceof OffscreenCanvas){let g=v=>{let p=Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype,v);Object.defineProperty(this.canvas,v,{get:()=>p.get.call(this.canvas),set:S=>{p.set.call(this.canvas,S),this.updateResolution()},configurable:p.configurable,enumerable:p.enumerable})};g("width"),g("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=a;let{internalFormat:l,type:m}=a;(m===n.FLOAT||m===n.HALF_FLOAT||l===n.RGBA16F||l===n.RGBA32F||l===n.R16F||l===n.R32F||l===n.RG16F||l===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 d=[];s&&s.forEach(g=>g(this,{gl:n,canvas:this.canvas,injectGLSL:v=>{d.push(v)},emitHook:this.emitHook.bind(this)}));let h=this.gl.createProgram();if(!h)throw new Error("Failed to create WebGL program");this.program=h;let u=this.createShader(this.gl.VERTEX_SHADER,J),T=this.createShader(n.FRAGMENT_SHADER,te(t,d));if(n.attachShader(h,u),n.attachShader(h,T),n.linkProgram(h),n.deleteShader(u),n.deleteShader(T),!n.getProgramParameter(h,n.LINK_STATUS))throw console.error("Program link error:",n.getProgramInfoLog(h)),n.deleteProgram(h),new Error("Failed to link WebGL program");this.aPositionLocation=n.getAttribLocation(h,"aPosition"),this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.buffer),n.bufferData(n.ARRAY_BUFFER,ee,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(h),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(A,this.canvas,{...this.textureOptions}),this.intermediateFbo=n.createFramebuffer(),this.historyDepth>0&&this._initializeTexture(w,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners(),this.emitHook("init")}emitHook(t,...e){this.hooks.get(t)?.forEach(s=>s.call(this,...e))}on(t,e){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(e)}off(t,e){let s=this.hooks.get(t);s&&s.splice(s.indexOf(e),1)}createShader(t,e){let s=this.gl.createShader(t);if(this.gl.shaderSource(s,e),this.gl.compileShader(s),!this.gl.getShaderParameter(s,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",e),console.error(this.gl.getShaderInfoLog(s)),this.gl.deleteShader(s),new Error("Shader compilation failed");return s}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),e=this.lastResizeTime+Q-t;e<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),e)}handleResize(){if(!(this.canvas instanceof HTMLCanvasElement))return;let t=window.devicePixelRatio||1,e=this.canvas.clientWidth*t,s=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==e||this.canvas.height!==s)&&(this.canvas.width=e,this.canvas.height=s),this.emitHook("resize",e,s)}addEventListeners(){let t=this.canvas,e=(i,r)=>{if(!this.uniforms.has("u_cursor"))return;let a=t.getBoundingClientRect();this.cursorPosition[0]=(i-a.left)/a.width,this.cursorPosition[1]=1-(r-a.top)/a.height,this.updateUniforms({u_cursor:this.cursorPosition})},s=(i,r,a)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let n=t.getBoundingClientRect(),l=r,m=a;this.clickPosition[0]=(l-n.left)/n.width,this.clickPosition[1]=1-(m-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let r=i;this.isTouchDevice||e(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&&e(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let r=i;this.isTouchDevice=!0,r.touches.length>0&&(e(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)=>{t.addEventListener(r,i)})}updateResolution(){let t=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...t),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:t}):this.initializeUniform("u_resolution","float",t),this.resizeTexture(A,...t),this.historyDepth>0&&this.resizeTexture(w,...t),this.emitHook("updateResolution",...t)}resizeTexture(t,e,s){let i=this.textures.get(t);if(!i||i.width===e&&i.height===s)return;this.gl.deleteTexture(i.texture),i.width=e,i.height=s;let{texture:r}=this.createTexture(t,i);i.texture=r,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(t){let e=this.textures.get(t);if(e)return e.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(t){let e=this.textures.get(t);e&&this.textureUnitPool.free.push(e.unitIndex)}resolveTextureOptions(t){let{gl:e}=this,s=t?.type??e.UNSIGNED_BYTE;return{type:s,format:t?.format??e.RGBA,internalFormat:t?.internalFormat??(s===e.FLOAT?e.RGBA32F:s===e.HALF_FLOAT?e.RGBA16F:e.RGBA8),minFilter:t?.minFilter??e.LINEAR,magFilter:t?.magFilter??e.LINEAR,wrapS:t?.wrapS??e.CLAMP_TO_EDGE,wrapT:t?.wrapT??e.CLAMP_TO_EDGE,preserveY:t?.preserveY}}getPixelArray(t,e){return t===this.gl.FLOAT?new Float32Array(e):t===this.gl.HALF_FLOAT?new Uint16Array(e):new Uint8Array(e)}clearHistoryTextureLayers(t){if(!t.history)return;let e=this.gl,{type:s,format:i}=t.options,r=this.getPixelArray(s,t.width*t.height*4);e.activeTexture(e.TEXTURE0+t.unitIndex),e.bindTexture(e.TEXTURE_2D_ARRAY,t.texture);for(let a=0;a<t.history.depth;++a)e.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,a,t.width,t.height,1,i,s,r)}initializeUniform(t,e,s,i){let r=i?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(e!=="float"&&e!=="int")throw new Error(`Invalid uniform type: ${e}. Expected 'float' or 'int'.`);if(r&&!(Array.isArray(s)&&s.length===r))throw new Error(`${t} array length mismatch: must initialize with ${r} elements.`);let a=this.gl.getUniformLocation(this.program,t);if(!a&&r&&(a=this.gl.getUniformLocation(this.program,`${t}[0]`)),!a){this.log(`${t} not in shader. Skipping initialization.`);return}let n=r?s[0]:s,l=Array.isArray(n)?n.length:1;this.uniforms.set(t,{type:e,length:l,location:a,arrayLength:r});try{this.updateUniforms({[t]:s})}catch(m){throw this.uniforms.delete(t),m}this.emitHook("initializeUniform",...arguments)}log(...t){this.debug&&console.debug(...t)}updateUniforms(t,e){this.gl.useProgram(this.program),Object.entries(t).forEach(([s,i])=>{let r=this.uniforms.get(s);if(!r){this.log(`${s} not in shader. Skipping update.`);return}let a=`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(c=>(Array.isArray(c)?c.length:1)!==r.length))throw new Error(`Tried to update ${s} with some elements that are not length ${r.length}.`);let l=new(r.type==="float"?Float32Array:Int32Array)(i.flat()),m=r.location;if(e?.startIndex){let c=this.gl.getUniformLocation(this.program,`${s}[${e.startIndex}]`);if(!c)throw new Error(`${s}[${e.startIndex}] not in shader. Did you pass an invalid startIndex?`);m=c}this.gl[a+"v"](m,l)}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[a](r.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(t,e){let{width:s,height:i}=e,r=e.history?.depth??0,a=this.gl.createTexture();if(!a)throw new Error("Failed to create texture");let n=e.unitIndex;if(typeof n!="number")try{n=this.reserveTextureUnit(t)}catch(d){throw this.gl.deleteTexture(a),d}let l=r>0,m=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:c}=e;return this.gl.activeTexture(this.gl.TEXTURE0+n),this.gl.bindTexture(m,a),this.gl.texParameteri(m,this.gl.TEXTURE_WRAP_S,c.wrapS),this.gl.texParameteri(m,this.gl.TEXTURE_WRAP_T,c.wrapT),this.gl.texParameteri(m,this.gl.TEXTURE_MIN_FILTER,c.minFilter),this.gl.texParameteri(m,this.gl.TEXTURE_MAG_FILTER,c.magFilter),l?this.gl.texStorage3D(m,1,c.internalFormat,s,i,r):t===A&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,c.internalFormat,s,i,0,c.format,c.type,null),{texture:a,unitIndex:n}}_initializeTexture(t,e,s){if(this.textures.has(t))throw new Error(`Texture '${F(t)}' is already initialized.`);let{history:i=0,...r}=s??{},{width:a,height:n}=D(e);if(!a||!n)throw new Error("Texture source must have valid dimensions");let l={width:a,height:n,options:this.resolveTextureOptions(r)};i>0&&(l.history={depth:i,writeIndex:0});let{texture:m,unitIndex:c}=this.createTexture(t,l),d={texture:m,unitIndex:c,...l};i>0&&(this.initializeUniform(`${F(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(d)),this.textures.set(t,d),this.updateTexture(t,e);let h=this.gl.getUniformLocation(this.program,F(t));h&&this.gl.uniform1i(h,c)}initializeTexture(t,e,s){this._initializeTexture(t,e,s),this.emitHook("initializeTexture",...arguments)}updateTextures(t,e){Object.entries(t).forEach(([s,i])=>{this.updateTexture(s,i,e)}),this.emitHook("updateTextures",...arguments)}updateTexture(t,e,s){let i=this.textures.get(t);if(!i)throw new Error(`Texture '${F(t)}' is not initialized.`);if(e instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e);return}let r=e;if(e instanceof o){let h=e.textures.get(A);if(e.gl===this.gl){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,h.texture);return}let{width:u,height:T,options:{format:g,type:v}}=h,p=this.getPixelArray(v,u*T*4);e.gl.bindFramebuffer(e.gl.FRAMEBUFFER,e.intermediateFbo),e.gl.readPixels(0,0,u,T,g,v,p),e.gl.bindFramebuffer(e.gl.FRAMEBUFFER,null),r={data:p,width:u,height:T}}let{width:a,height:n}=D(r);if(!a||!n)return;let l="isPartial"in r&&r.isPartial;l||this.resizeTexture(t,a,n);let c=!("data"in r&&r.data)&&!i.options?.preserveY,d=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,c),this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,i.history.writeIndex,a,n,1,i.options.format,i.options.type,r.data??r),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,d);let h=`${F(t)}FrameOffset`;this.updateUniforms({[h]: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,c),l){let h=r;this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,h.x??0,h.y??0,a,n,i.options.format,i.options.type,h.data)}else this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,a,n,0,i.options.format,i.options.type,r.data??r);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,d)}}draw(t){this.emitHook("beforeDraw",...arguments);let e=this.gl,s=e.drawingBufferWidth,i=e.drawingBufferHeight,r=this.textures.get(A);e.bindFramebuffer(e.FRAMEBUFFER,this.intermediateFbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,r.texture,0),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.buffer),e.vertexAttribPointer(this.aPositionLocation,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(this.aPositionLocation),e.viewport(0,0,s,i),t?.skipClear||e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLES,0,6);let a=this.textures.get(w);a&&!t?.skipHistoryWrite&&(e.bindTexture(e.TEXTURE_2D_ARRAY,a.texture),e.copyTexSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,a.history.writeIndex,0,0,s,i)),e.bindFramebuffer(e.READ_FRAMEBUFFER,this.intermediateFbo),e.bindFramebuffer(e.DRAW_FRAMEBUFFER,null),e.blitFramebuffer(0,0,s,i,0,0,s,i,e.COLOR_BUFFER_BIT,e.NEAREST),e.bindFramebuffer(e.FRAMEBUFFER,null),this.emitHook("afterDraw",...arguments)}step(t,e){this.emitHook("beforeStep",...arguments);let s={};this.uniforms.has("u_time")&&(s.u_time=t),this.uniforms.has("u_frame")&&(s.u_frame=this.frame),this.updateUniforms(s),this.draw(e);let i=this.textures.get(w);if(i&&!e?.skipHistoryWrite){let{writeIndex:r,depth:a}=i.history;this.updateUniforms({[`${F(w)}FrameOffset`]:r}),i.history.writeIndex=(r+1)%a}++this.frame,this.emitHook("afterStep",...arguments)}play(t,e){this.pause();let s=i=>{i=(i-this.startTime)/1e3;let r=e?.(i,this.frame)??void 0;this.step(i,r),this.animationFrameId=requestAnimationFrame(s),t?.(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(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),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((t,e)=>{this.canvas.removeEventListener(e,t)}),this.program&&this.gl.deleteProgram(this.program),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(t=>{this.gl.deleteTexture(t.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()}},H=M;var $={data:new Uint8Array(4),width:1,height:1};function U(o){return o instanceof HTMLVideoElement||o instanceof HTMLImageElement||o instanceof HTMLCanvasElement||o instanceof OffscreenCanvas}function z(o){return JSON.stringify(o,Object.keys(o).sort())}var I=null;function B(){return I||(I=import("@mediapipe/tasks-vision").then(({FilesetResolver:o})=>o.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.22-rc.20250304/wasm"))),I}function G(o){return{historyParams:o?", framesAgo":"",fn:o?(s,i,r,a)=>{let n=r.replace(/\w+ /g,""),l=r?`${r}, int framesAgo`:"int framesAgo",m=n?`${n}, 0`:"0";return`${s} ${i}(${l}) {
10
+ ${a}
11
+ }
12
+ ${s} ${i}(${r}) { return ${i}(${m}); }`}:(s,i,r,a)=>`${s} ${i}(${r}) {
13
+ ${a}
14
+ }`}}var ie={modelPath:"https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite",outputCategoryMask:!1};function re(o){let t=Array.from({length:o},(s,i)=>`uniform sampler2D u_confidenceMask${i};`).join(`
15
+ `),e=Array.from({length:o},(s,i)=>` ${i>0?"else ":""}if (i == ${i}) c = texelFetch(u_confidenceMask${i}, texCoord, 0).r;`).join(`
11
16
  `);return`#version 300 es
12
17
  precision mediump float;
13
18
  in vec2 v_uv;
@@ -31,12 +36,12 @@ ${e}
31
36
  // Normalize index: 0 = background, 1/(n-1) to 1 for foreground categories.
32
37
  float normalizedIndex = float(maxIndex) / float(max(1, ${o-1}));
33
38
  outColor = vec4(normalizedIndex, maxConfidence, 0.0, 1.0);
34
- }`}function K(o){let{textureName:t,options:e}=o,r="https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite";return function(i,n){let{injectGLSL:a,gl:s,emitHook:m}=n,u=null,l=null,g=-1,f="VIDEO",T=new Map,p=1,v=new OffscreenCanvas(1,1),d=null;async function _(){try{let{FilesetResolver:h,ImageSegmenter:c}=await import("@mediapipe/tasks-vision");l=await h.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"),u=await c.createFromOptions(l,{baseOptions:{modelAssetPath:e?.modelPath||r,delegate:"GPU"},canvas:v,runningMode:f,outputCategoryMask:e?.outputCategoryMask??!1,outputConfidenceMasks:!0})}catch(h){throw console.error("[Segmenter Plugin] Failed to initialize MediaPipe:",h),h}}let A=_();i.on("init",async()=>{i.initializeUniform("u_numCategories","int",p),i.initializeTexture("u_segmentMask",v,{preserveY:!0,minFilter:s.NEAREST,magFilter:s.NEAREST}),await A;let h=u.getLabels();h.length&&(p=h.length),d=new M(j(p),{canvas:v});for(let c=0;c<p;++c)d.initializeTexture(`u_confidenceMask${c}`,V);i.updateUniforms({u_numCategories:p}),m("segmenter:ready")}),i.on("initializeTexture",(h,c)=>{h===t&&U(c)}),i.on("updateTextures",h=>{let c=h[t];c&&U(c)});function O(h){if(!d)return;let c={};for(let x=0;x<h.length;++x)c[`u_confidenceMask${x}`]=h[x].getAsWebGLTexture();d.updateTextures(c),d.draw(),i.updateTextures({u_segmentMask:v}),h.forEach(x=>x.close())}function S(h){let{confidenceMasks:c}=h;!c||c.length===0||(O(c),m("segmenter:result",h))}let P=0;async function U(h){let c=++P;if(await A,c!==P||!u)return;T.get(t)!==h&&(g=-1),T.set(t,h);try{let y=h instanceof HTMLVideoElement?"VIDEO":"IMAGE";if(f!==y&&(f=y,await u.setOptions({runningMode:f})),h instanceof HTMLVideoElement){if(h.videoWidth===0||h.videoHeight===0||h.readyState<2)return;if(h.currentTime!==g){g=h.currentTime;let F=u.segmentForVideo(h,performance.now());S(F)}}else if(h instanceof HTMLImageElement||h instanceof HTMLCanvasElement){if(h.width===0||h.height===0)return;let F=u.segment(h);S(F)}}catch(y){console.error("[Segmenter Plugin] Segmentation error:",y)}}i.on("destroy",()=>{u&&(u.close(),u=null),d&&(d.destroy(),d=null),l=null,T.clear()}),a(`
35
- uniform sampler2D u_segmentMask;
39
+ }`}var L=new Map;function se(o,t){let{mask:{shader:e}}=o,s={};for(let i=0;i<t.length;++i)s[`u_confidenceMask${i}`]=t[i].getAsWebGLTexture();e.updateTextures(s),e.draw(),t.forEach(i=>i.close())}function ne(o){let{textureName:t,options:{history:e,...s}={}}=o,i={...ie,...s},r=z({...i,textureName:t});return function(a,n){let{injectGLSL:l,gl:m,emitHook:c}=n,h=L.get(r)?.canvas??new OffscreenCanvas(1,1),u=null,T=!1;function g(){u&&(a.updateTextures({u_segmentMask:u.canvas},{skipHistoryWrite:T}),c("segmenter:result",u.state.result))}async function v(){if(L.has(r))u=L.get(r);else{let[f,{ImageSegmenter:x}]=await Promise.all([B(),import("@mediapipe/tasks-vision")]),y=await x.createFromOptions(f,{baseOptions:{modelAssetPath:i.modelPath,delegate:"GPU"},canvas:h,runningMode:"VIDEO",outputCategoryMask:i.outputCategoryMask,outputConfidenceMasks:!0}),R=y.getLabels(),E=R.length||1,b=new H(re(E),{canvas:h});for(let _=0;_<E;++_)b.initializeTexture(`u_confidenceMask${_}`,$);u={segmenter:y,canvas:h,subscribers:new Map,state:{runningMode:"VIDEO",source:null,videoTime:-1,resultTimestamp:0,result:null,pending:Promise.resolve()},labels:R,numCategories:E,mask:{shader:b}},L.set(r,u)}u.subscribers.set(g,!1)}let p=v();a.on("init",()=>{a.initializeUniform("u_numCategories","int",1),a.initializeTexture("u_segmentMask",h,{preserveY:!0,minFilter:m.NEAREST,magFilter:m.NEAREST,history:e}),p.then(()=>{a.updateUniforms({u_numCategories:u.numCategories}),c("segmenter:ready")})}),a.on("initializeTexture",(f,x)=>{f===t&&U(x)&&O(x)}),a.on("updateTextures",(f,x)=>{let y=f[t];U(y)&&(T=x?.skipHistoryWrite??!1,O(y))});let S=0;async function O(f){let x=performance.now(),y=++S;await p,u&&(u.state.pending=u.state.pending.then(async()=>{if(y!==S||!u)return;let R=f instanceof HTMLVideoElement?"VIDEO":"IMAGE";u.state.runningMode!==R&&(u.state.runningMode=R,await u.segmenter.setOptions({runningMode:R}));let E=!1;if(f!==u.state.source?(u.state.source=f,u.state.videoTime=-1,E=!0):f instanceof HTMLVideoElement?f.currentTime!==u.state.videoTime&&(u.state.videoTime=f.currentTime,E=!0):f instanceof HTMLImageElement||x-u.state.resultTimestamp>2&&(E=!0),E){let b;if(f instanceof HTMLVideoElement){if(f.videoWidth===0||f.videoHeight===0||f.readyState<2)return;b=u.segmenter.segmentForVideo(f,x)}else{if(f.width===0||f.height===0)return;b=u.segmenter.segment(f)}if(b?.confidenceMasks&&b.confidenceMasks.length>0){u.state.resultTimestamp=x,u.state.result=b,se(u,b.confidenceMasks);for(let _ of u.subscribers.keys())_(),u.subscribers.set(_,!0)}}else u.state.result&&!u.subscribers.get(g)&&(g(),u.subscribers.set(g,!0))}),await u.state.pending)}a.on("destroy",()=>{u&&(u.subscribers.delete(g),u.subscribers.size===0&&(u.segmenter.close(),u.mask.shader?.destroy(),L.delete(r))),u=null});let{fn:W}=G(e),X=e?`int layer = (u_segmentMaskFrameOffset - framesAgo + ${e}) % ${e};
40
+ vec4 mask = texture(u_segmentMask, vec3(pos, float(layer)));`:"vec4 mask = texture(u_segmentMask, pos);";l(`
41
+ uniform sampler2D${e?"Array":""} u_segmentMask;${e?`
42
+ uniform int u_segmentMaskFrameOffset;`:""}
36
43
  uniform int u_numCategories;
37
44
 
38
- vec2 segmentAt(vec2 pos) {
39
- vec4 mask = texture(u_segmentMask, pos);
40
- return vec2(mask.r, mask.g);
41
- }`)}}var q=K;
45
+ ${W("vec2","segmentAt","vec2 pos",`${X}
46
+ return vec2(mask.r, mask.g);`)}`)}}var oe=ne;
42
47
  //# sourceMappingURL=segmenter.js.map