shaderpad 1.0.0-beta.40 → 1.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +262 -40
- package/dist/chunk-A3XQBYSC.mjs +10 -0
- package/dist/chunk-A3XQBYSC.mjs.map +1 -0
- package/dist/index.d.mts +5 -29
- package/dist/index.d.ts +5 -29
- package/dist/index.js +4 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/face.d.mts +0 -3
- package/dist/plugins/face.d.ts +0 -3
- package/dist/plugins/face.js +5 -5
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +5 -5
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/hands.d.mts +0 -3
- package/dist/plugins/hands.d.ts +0 -3
- package/dist/plugins/hands.js +5 -5
- package/dist/plugins/hands.js.map +1 -1
- package/dist/plugins/hands.mjs +4 -4
- package/dist/plugins/hands.mjs.map +1 -1
- package/dist/plugins/pose.d.mts +0 -3
- package/dist/plugins/pose.d.ts +0 -3
- package/dist/plugins/pose.js +35 -36
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +29 -29
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/segmenter.d.mts +0 -3
- package/dist/plugins/segmenter.d.ts +0 -3
- package/dist/plugins/segmenter.js +9 -10
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +6 -6
- package/dist/plugins/segmenter.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6C6DVCZI.mjs +0 -11
- package/dist/chunk-6C6DVCZI.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\tonReady?: () => void;\n\tonResults?: (results: PoseLandmarkerResult) => void;\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 } = 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 initializePoseLandmarker() {\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:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\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 processPoseResults(result: PoseLandmarkerResult) {\n\t\t\tif (!result.landmarks || !landmarksDataArray) return;\n\n\t\t\t// IMPORTANT: maskShader and MediaPipe share a WebGL context. MediaPipe needs to run at least once before\n\t\t\t// ShaderPad is created on the same canvas, otherwise MediaPipe’s WebGL state gets corrupted.\n\t\t\tif (!maskShader) {\n\t\t\t\tmaskShader = new ShaderPad(\n\t\t\t\t\t`#version 300 es\n\t\t\t\t\tprecision mediump float;\n\t\t\t\t\tin vec2 v_uv;\n\t\t\t\t\tout vec4 outColor;\n\t\t\t\t\tuniform sampler2D u_mask;\n\t\t\t\t\tuniform float u_poseIndex;\n\t\t\t\t\tvoid main() {\n\t\t\t\t\t\tivec2 texCoord = ivec2(v_uv * vec2(textureSize(u_mask, 0)));\n\t\t\t\t\t\tfloat confidence = texelFetch(u_mask, texCoord, 0).r;\n\t\t\t\t\t\tif (confidence < 0.01) discard;\n\t\t\t\t\t\toutColor = vec4(1.0, confidence, u_poseIndex, 1.0);\n\t\t\t\t\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\t\t\t}\n\n\t\t\tconst nPoses = result.landmarks.length;\n\t\t\tupdateLandmarksTexture(result.landmarks);\n\t\t\tupdateMaskTexture(result.segmentationMasks);\n\t\t\tshaderPad.updateUniforms({ u_nPoses: nPoses });\n\n\t\t\toptions?.onResults?.(result);\n\t\t}\n\n\t\tshaderPad.registerHook('init', async () => {\n\t\t\tshaderPad.initializeTexture('u_poseMask', dummyTexture, {\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\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\n\t\t\tawait initializePoseLandmarker();\n\t\t\toptions?.onReady?.();\n\t\t});\n\n\t\tshaderPad.registerHook('updateTextures', async (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (!source) return;\n\n\t\t\tconst previousSource = textureSources.get(textureName);\n\t\t\tif (previousSource !== source) {\n\t\t\t\tlastVideoTime = -1;\n\t\t\t}\n\n\t\t\ttextureSources.set(textureName, source);\n\t\t\tif (!poseLandmarker) return;\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: 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\tconst result = poseLandmarker.detectForVideo(source, performance.now());\n\t\t\t\t\t\tprocessPoseResults(result);\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\tconst result = poseLandmarker.detect(source);\n\t\t\t\t\tprocessPoseResults(result);\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.registerHook('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","poseLandmarker","vision","lastVideoTime","runningMode","textureSources","maxPoses","LANDMARKS_TEXTURE_WIDTH","landmarksTextureHeight","landmarksDataArray","sharedCanvas","maskShader","initializePoseLandmarker","FilesetResolver","PoseLandmarker","error","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","processPoseResults","result","index_default","textureSize","updates","source","requiredMode","pose_default"]}
|
|
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,11 +1,8 @@
|
|
|
1
1
|
import ShaderPad, { PluginContext } from '../index.mjs';
|
|
2
|
-
import { ImageSegmenterResult } from '@mediapipe/tasks-vision';
|
|
3
2
|
|
|
4
3
|
interface SegmenterPluginOptions {
|
|
5
4
|
modelPath?: string;
|
|
6
5
|
outputCategoryMask?: boolean;
|
|
7
|
-
onReady?: () => void;
|
|
8
|
-
onResults?: (results: ImageSegmenterResult) => void;
|
|
9
6
|
}
|
|
10
7
|
declare function segmenter(config: {
|
|
11
8
|
textureName: string;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import ShaderPad, { PluginContext } from '../index.js';
|
|
2
|
-
import { ImageSegmenterResult } from '@mediapipe/tasks-vision';
|
|
3
2
|
|
|
4
3
|
interface SegmenterPluginOptions {
|
|
5
4
|
modelPath?: string;
|
|
6
5
|
outputCategoryMask?: boolean;
|
|
7
|
-
onReady?: () => void;
|
|
8
|
-
onResults?: (results: ImageSegmenterResult) => void;
|
|
9
6
|
}
|
|
10
7
|
declare function segmenter(config: {
|
|
11
8
|
textureName: string;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
"use strict";var
|
|
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
|
|
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
|
-
}
|
|
8
|
-
|
|
9
|
-
`),s=e.findLastIndex(i=>{let r=i.trimStart();return r.startsWith("precision ")||r.startsWith("#version ")})+1;return e.splice(s,0,...t),e.join(`
|
|
10
|
-
`)}function A(n){return n instanceof WebGLTexture?{width:0,height:0}:n instanceof HTMLVideoElement?{width:n.videoWidth,height:n.videoHeight}:n instanceof HTMLImageElement?{width:n.naturalWidth??n.width,height:n.naturalHeight??n.height}:{width:n.width,height:n.height}}function T(n){return typeof n=="symbol"?n.description??"":n}var _=class{isInternalCanvas=!1;isTouchDevice=!1;gl;fragmentShaderSrc;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;onResize;hooks=new Map;historyDepth=0;textureOptions;debug;intermediateFbo=null;constructor(t,{canvas:e,plugins:s,history:i,debug:r,...o}={}){if(this.canvas=e||document.createElement("canvas"),!e){this.isInternalCanvas=!0;let m=this.canvas;m.style.position="fixed",m.style.inset="0",m.style.height="100dvh",m.style.width="100dvw",document.body.appendChild(m)}if(this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.textureUnitPool={free:[],next:0,max:this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.textureOptions=o;let{internalFormat:a,type:l}=o;(l===this.gl.FLOAT||l===this.gl.HALF_FLOAT||a===this.gl.RGBA16F||a===this.gl.RGBA32F||a===this.gl.R16F||a===this.gl.R32F||a===this.gl.RG16F||a===this.gl.RG32F)&&!this.gl.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 h=[];if(s){let m={gl:this.gl,uniforms:this.uniforms,textures:this.textures,canvas:this.canvas,reserveTextureUnit:this.reserveTextureUnit.bind(this),releaseTextureUnit:this.releaseTextureUnit.bind(this),injectGLSL:d=>{h.push(d)}};Object.defineProperty(m,"program",{get:()=>this.program,enumerable:!0,configurable:!0}),s.forEach(d=>d(this,m))}this.fragmentShaderSrc=X(t,h),this.init(),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners()}registerHook(t,e){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(e)}init(){let t=B;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let e=this.createShader(this.gl.VERTEX_SHADER,t),s=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,e),this.gl.attachShader(this.program,s),this.gl.linkProgram(this.program),this.gl.deleteShader(e),this.gl.deleteShader(s),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw console.error("Program link error:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),new Error("Failed to link WebGL program");this.aPositionLocation=this.gl.getAttribLocation(this.program,"aPosition"),this.setupBuffer(),this.gl.useProgram(this.program),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(b,this.canvas,{...this.textureOptions}),this._initializeTexture(v,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.intermediateFbo=this.gl.createFramebuffer()),this.hooks.get("init")?.forEach(i=>i.call(this))}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}setupBuffer(){let t=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,t,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.gl.enableVertexAttribArray(this.aPositionLocation),this.gl.vertexAttribPointer(this.aPositionLocation,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),e=this.lastResizeTime+W-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.onResize?.(e,s)}addEventListeners(){let t=this.canvas,e=(i,r)=>{if(!this.uniforms.has("u_cursor"))return;let o=t.getBoundingClientRect();this.cursorPosition[0]=(i-o.left)/o.width,this.cursorPosition[1]=1-(r-o.top)/o.height,this.updateUniforms({u_cursor:this.cursorPosition})},s=(i,r,o)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let a=t.getBoundingClientRect(),l=r,c=o;this.clickPosition[0]=(l-a.left)/a.width,this.clickPosition[1]=1-(c-a.top)/a.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.historyDepth>0&&(this.resizeTexture(v,...t),this.resizeTexture(b,...t)),this.hooks.get("updateResolution")?.forEach(e=>e.call(this))}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}}clearHistoryTextureLayers(t){if(!t.history)return;let e=this.gl,{type:s,format:i}=t.options,r=t.width*t.height*4,o=s===e.FLOAT?new Float32Array(r):s===e.HALF_FLOAT?new Uint16Array(r):new Uint8Array(r);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,o)}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 o=this.gl.getUniformLocation(this.program,t);if(!o&&r&&(o=this.gl.getUniformLocation(this.program,`${t}[0]`)),!o){this.log(`${t} not found in fragment shader. Skipping initialization.`);return}let a=r?s[0]:s,l=Array.isArray(a)?a.length:1;this.uniforms.set(t,{type:e,length:l,location:o,arrayLength:r});try{this.updateUniforms({[t]:s})}catch(c){throw this.uniforms.delete(t),c}this.hooks.get("initializeUniform")?.forEach(c=>c.call(this,...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 found in fragment shader. Skipping update.`);return}let o=`uniform${r.length}${r.type.charAt(0)}`;if(r.arrayLength){if(!Array.isArray(i))throw new Error(`${s} is an array, but the value passed to updateUniforms is not an array.`);let a=i.length;if(!a)return;if(a>r.arrayLength)throw new Error(`${s} received ${a} values, but maximum length is ${r.arrayLength}.`);if(i.some(h=>(Array.isArray(h)?h.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()),c=r.location;if(e?.startIndex){let h=this.gl.getUniformLocation(this.program,`${s}[${e.startIndex}]`);if(!h)throw new Error(`${s}[${e.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`);c=h}this.gl[o+"v"](c,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[o](r.location,...i)}}),this.hooks.get("updateUniforms")?.forEach(s=>s.call(this,...arguments))}createTexture(t,e){let{width:s,height:i}=e,r=e.history?.depth??0,o=this.gl.createTexture();if(!o)throw new Error("Failed to create texture");let a=e.unitIndex;if(typeof a!="number")try{a=this.reserveTextureUnit(t)}catch(m){throw this.gl.deleteTexture(o),m}let l=r>0,c=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:h}=e;return this.gl.activeTexture(this.gl.TEXTURE0+a),this.gl.bindTexture(c,o),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_S,h.wrapS),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_T,h.wrapT),this.gl.texParameteri(c,this.gl.TEXTURE_MIN_FILTER,h.minFilter),this.gl.texParameteri(c,this.gl.TEXTURE_MAG_FILTER,h.magFilter),l?this.gl.texStorage3D(c,1,h.internalFormat,s,i,r):t===b&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,h.internalFormat,s,i,0,h.format,h.type,null),{texture:o,unitIndex:a}}_initializeTexture(t,e,s){if(this.textures.has(t))throw new Error(`Texture '${T(t)}' is already initialized.`);let{history:i=0,...r}=s??{},{width:o,height:a}=A(e);if(!o||!a)throw new Error("Texture source must have valid dimensions");let l={width:o,height:a,options:this.resolveTextureOptions(r)};i>0&&(l.history={depth:i,writeIndex:0});let{texture:c,unitIndex:h}=this.createTexture(t,l),m={texture:c,unitIndex:h,...l};i>0&&(this.initializeUniform(`${T(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(m)),this.textures.set(t,m),this.updateTexture(t,e);let d=this.gl.getUniformLocation(this.program,T(t));d&&this.gl.uniform1i(d,h)}initializeTexture(t,e,s){this._initializeTexture(t,e,s),this.hooks.get("initializeTexture")?.forEach(i=>i.call(this,...arguments))}updateTextures(t,e){this.hooks.get("updateTextures")?.forEach(s=>s.call(this,...arguments)),Object.entries(t).forEach(([s,i])=>{this.updateTexture(s,i,e)})}updateTexture(t,e,s){let i=this.textures.get(t);if(!i)throw new Error(`Texture '${T(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:r,height:o}=A(e);if(!r||!o)return;let a="isPartial"in e&&e.isPartial;a||this.resizeTexture(t,r,o);let c=!("data"in e&&e.data)&&!i.options?.preserveY,h=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,r,o,1,i.options.format,i.options.type,e.data??e),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,h);let m=`${T(t)}FrameOffset`;this.updateUniforms({[m]: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,c),a?this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,e.x??0,e.y??0,r,o,i.options.format,i.options.type,e.data):this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,r,o,0,i.options.format,i.options.type,e.data??e),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,h)}draw(t){let e=this.gl,s=e.drawingBufferWidth,i=e.drawingBufferHeight,r=this.textures.get(v),o=this.textures.get(b),a=r&&!t?.skipHistoryWrite;a&&(e.bindFramebuffer(e.FRAMEBUFFER,this.intermediateFbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,o.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),a&&(e.bindTexture(e.TEXTURE_2D_ARRAY,r.texture),e.copyTexSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,r.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))}step(t,e){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.hooks.get("step")?.forEach(r=>r.call(this,t,this.frame)),this.draw(e);let i=this.textures.get(v);if(i&&!e?.skipHistoryWrite){let{writeIndex:r,depth:o}=i.history;this.updateUniforms({[`${T(v)}FrameOffset`]:r}),i.history.writeIndex=(r+1)%o}this.hooks.get("afterStep")?.forEach(r=>r.call(this,t,this.frame)),++this.frame}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)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.hooks.get("reset")?.forEach(t=>t.call(this))}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.hooks.get("destroy")?.forEach(t=>t.call(this)),this.isInternalCanvas&&this.canvas instanceof HTMLCanvasElement&&this.canvas.remove()}},S=_;var U={data:new Uint8Array(4),width:1,height:1};function $(n){let t=Array.from({length:n},(s,i)=>`uniform sampler2D u_confidenceMask${i};`).join(`
|
|
11
|
-
`),e=Array.from({length:n},(s,i)=>` ${i>0?"else ":""}if (i == ${i}) c = texelFetch(u_confidenceMask${i}, texCoord, 0).r;`).join(`
|
|
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(`
|
|
12
11
|
`);return`#version 300 es
|
|
13
12
|
precision mediump float;
|
|
14
13
|
in vec2 v_uv;
|
|
@@ -20,7 +19,7 @@ void main() {
|
|
|
20
19
|
float maxConfidence = 0.0;
|
|
21
20
|
int maxIndex = 0;
|
|
22
21
|
|
|
23
|
-
for (int i = 0; i < ${
|
|
22
|
+
for (int i = 0; i < ${o}; ++i) {
|
|
24
23
|
float c = 0.0;
|
|
25
24
|
${e}
|
|
26
25
|
if (c > maxConfidence) {
|
|
@@ -30,14 +29,14 @@ ${e}
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
// Normalize index: 0 = background, 1/(n-1) to 1 for foreground categories.
|
|
33
|
-
float normalizedIndex = float(maxIndex) / float(max(1, ${
|
|
32
|
+
float normalizedIndex = float(maxIndex) / float(max(1, ${o-1}));
|
|
34
33
|
outColor = vec4(normalizedIndex, maxConfidence, 0.0, 1.0);
|
|
35
|
-
}`}function
|
|
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(`
|
|
36
35
|
uniform sampler2D u_segmentMask;
|
|
37
36
|
uniform int u_numCategories;
|
|
38
37
|
|
|
39
38
|
vec2 segmentAt(vec2 pos) {
|
|
40
39
|
vec4 mask = texture(u_segmentMask, pos);
|
|
41
40
|
return vec2(mask.r, mask.g);
|
|
42
|
-
}`)}}var
|
|
41
|
+
}`)}}var q=K;
|
|
43
42
|
//# sourceMappingURL=segmenter.js.map
|