shaderpad 1.0.0-beta.40 → 1.0.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +323 -41
- package/dist/chunk-5CBGNOA3.mjs +10 -0
- package/dist/chunk-5CBGNOA3.mjs.map +1 -0
- package/dist/chunk-JRSBIGBN.mjs +7 -0
- package/dist/chunk-JRSBIGBN.mjs.map +1 -0
- package/dist/index.d.mts +7 -30
- package/dist/index.d.ts +7 -30
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/face.d.mts +1 -3
- package/dist/plugins/face.d.ts +1 -3
- package/dist/plugins/face.js +53 -76
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +51 -79
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/hands.d.mts +1 -3
- package/dist/plugins/hands.d.ts +1 -3
- package/dist/plugins/hands.js +20 -16
- package/dist/plugins/hands.js.map +1 -1
- package/dist/plugins/hands.mjs +14 -15
- package/dist/plugins/hands.mjs.map +1 -1
- package/dist/plugins/helpers.js +1 -1
- package/dist/plugins/helpers.js.map +1 -1
- package/dist/plugins/helpers.mjs +1 -1
- package/dist/plugins/helpers.mjs.map +1 -1
- package/dist/plugins/mediapipe-common.d.mts +18 -0
- package/dist/plugins/mediapipe-common.d.ts +18 -0
- package/dist/plugins/mediapipe-common.js +7 -0
- package/dist/plugins/mediapipe-common.js.map +1 -0
- package/dist/plugins/mediapipe-common.mjs +2 -0
- package/dist/plugins/mediapipe-common.mjs.map +1 -0
- package/dist/plugins/pose.d.mts +1 -3
- package/dist/plugins/pose.d.ts +1 -3
- package/dist/plugins/pose.js +53 -49
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +30 -30
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/save.d.mts +1 -1
- package/dist/plugins/save.d.ts +1 -1
- package/dist/plugins/save.js +1 -1
- package/dist/plugins/save.js.map +1 -1
- package/dist/plugins/save.mjs.map +1 -1
- package/dist/plugins/segmenter.d.mts +1 -3
- package/dist/plugins/segmenter.d.ts +1 -3
- package/dist/plugins/segmenter.js +17 -13
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +11 -11
- 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 '..';\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"]}
|
package/dist/plugins/save.d.mts
CHANGED
package/dist/plugins/save.d.ts
CHANGED
package/dist/plugins/save.js
CHANGED
|
@@ -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
|
|
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
|
package/dist/plugins/save.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/save.ts"],"sourcesContent":["import ShaderPad, { PluginContext } from '
|
|
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 '
|
|
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"]}
|
|
@@ -1,11 +1,9 @@
|
|
|
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
|
-
|
|
8
|
-
onResults?: (results: ImageSegmenterResult) => void;
|
|
6
|
+
history?: number;
|
|
9
7
|
}
|
|
10
8
|
declare function segmenter(config: {
|
|
11
9
|
textureName: string;
|
|
@@ -1,11 +1,9 @@
|
|
|
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
|
-
|
|
8
|
-
onResults?: (results: ImageSegmenterResult) => void;
|
|
6
|
+
history?: number;
|
|
9
7
|
}
|
|
10
8
|
declare function segmenter(config: {
|
|
11
9
|
textureName: string;
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
"use strict";var
|
|
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
|
-
}
|
|
8
|
-
`,W=33.333333333333336,v=Symbol("u_history"),b=Symbol("__SHADERPAD_BUFFER");function X(n,t){if(!t?.length)return n;let e=n.split(`
|
|
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(`
|
|
9
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(`
|
|
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
|
-
|
|
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(`
|
|
12
16
|
`);return`#version 300 es
|
|
13
17
|
precision mediump float;
|
|
14
18
|
in vec2 v_uv;
|
|
@@ -20,7 +24,7 @@ void main() {
|
|
|
20
24
|
float maxConfidence = 0.0;
|
|
21
25
|
int maxIndex = 0;
|
|
22
26
|
|
|
23
|
-
for (int i = 0; i < ${
|
|
27
|
+
for (int i = 0; i < ${o}; ++i) {
|
|
24
28
|
float c = 0.0;
|
|
25
29
|
${e}
|
|
26
30
|
if (c > maxConfidence) {
|
|
@@ -30,14 +34,14 @@ ${e}
|
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
// Normalize index: 0 = background, 1/(n-1) to 1 for foreground categories.
|
|
33
|
-
float normalizedIndex = float(maxIndex) / float(max(1, ${
|
|
37
|
+
float normalizedIndex = float(maxIndex) / float(max(1, ${o-1}));
|
|
34
38
|
outColor = vec4(normalizedIndex, maxConfidence, 0.0, 1.0);
|
|
35
|
-
}`}function
|
|
36
|
-
|
|
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;`:""}
|
|
37
43
|
uniform int u_numCategories;
|
|
38
44
|
|
|
39
|
-
vec2
|
|
40
|
-
|
|
41
|
-
return vec2(mask.r, mask.g);
|
|
42
|
-
}`)}}var N=Y;
|
|
45
|
+
${W("vec2","segmentAt","vec2 pos",`${X}
|
|
46
|
+
return vec2(mask.r, mask.g);`)}`)}}var oe=ne;
|
|
43
47
|
//# sourceMappingURL=segmenter.js.map
|