shaderpad 1.0.0-beta.33 → 1.0.0-beta.35
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 +5 -3
- package/dist/plugins/face.js +28 -32
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +27 -31
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/pose.js +4 -4
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +2 -2
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/segmenter.js +5 -5
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +5 -5
- package/dist/plugins/segmenter.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/segmenter.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '../index';\nimport type { ImageSegmenter, ImageSegmenterResult, MPMask } from '@mediapipe/tasks-vision';\n\nexport interface SegmenterPluginOptions {\n\tmodelPath?: string;\n\toutputCategoryMask?: boolean;\n}\n\nconst dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\n\nfunction createMaskShaderSource(numMasks: number): string {\n\tconst uniforms = Array.from({ length: numMasks }, (_, i) => `uniform sampler2D u_confidenceMask${i};`).join('\\n');\n\n\t// GLSL doesn't allow dynamic indexing of samplers, so we need a switch-like construct.\n\tconst sampleByIndex = Array.from(\n\t\t{ length: numMasks },\n\t\t(_, i) => `\\t\\t${i > 0 ? 'else ' : ''}if (i == ${i}) c = texelFetch(u_confidenceMask${i}, texCoord, 0).r;`\n\t).join('\\n');\n\n\treturn `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nout vec4 outColor;\n${uniforms}\n\nvoid main() {\n\tivec2 texCoord = ivec2(v_uv * vec2(textureSize(u_confidenceMask0, 0)));\n\tfloat maxConfidence = 0.0;\n\tint maxIndex = 0;\n\n\tfor (int i = 0; i < ${numMasks}; i++) {\n\t\tfloat c = 0.0;\n${sampleByIndex}\n\t\tif (c > maxConfidence) {\n\t\t\tmaxConfidence = c;\n\t\t\tmaxIndex = i;\n\t\t}\n\t}\n\n\t// Normalize index: 0 = background, 1/(n-1) to 1 for foreground categories.\n\tfloat normalizedIndex = float(maxIndex) / float(max(1, ${numMasks - 1}));\n\toutColor = vec4(normalizedIndex, maxConfidence, 0.0, 1.0);\n}`;\n}\n\nfunction segmenter(config: { textureName: string; options?: SegmenterPluginOptions }) {\n\tconst { textureName, options } = config;\n\tconst defaultModelPath =\n\t\t'https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite';\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL } = context;\n\n\t\tlet imageSegmenter: ImageSegmenter | 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\tlet numCategories = 1;\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\t\tasync function initializeImageSegmenter() {\n\t\t\ttry {\n\t\t\t\tconst { FilesetResolver, ImageSegmenter } = 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\n\t\t\t\timageSegmenter = await ImageSegmenter.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: runningMode,\n\t\t\t\t\toutputCategoryMask: options?.outputCategoryMask ?? false, // Better for perf, and category can be inferred from confidence mask index.\n\t\t\t\t\toutputConfidenceMasks: true,\n\t\t\t\t});\n\n\t\t\t\tconst labels = imageSegmenter.getLabels();\n\t\t\t\tif (labels.length) numCategories = labels.length;\n\t\t\t\tshaderPad.updateUniforms({ u_numCategories: numCategories });\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Segmenter Plugin] Failed to initialize:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tfunction updateMaskTexture(confidenceMasks: MPMask[]) {\n\t\t\tif (!maskShader) return;\n\n\t\t\tconst textures: Record<string, WebGLTexture> = {};\n\t\t\tfor (let i = 0; i < confidenceMasks.length; i++) {\n\t\t\t\ttextures[`u_confidenceMask${i}`] = confidenceMasks[i].getAsWebGLTexture();\n\t\t\t}\n\t\t\tmaskShader.updateTextures(textures);\n\t\t\tmaskShader.draw();\n\t\t\tshaderPad.updateTextures({ u_segmentMask: sharedCanvas });\n\t\t}\n\n\t\tfunction processSegmenterResults(result: ImageSegmenterResult) {\n\t\t\tconst { confidenceMasks } = result;\n\t\t\tif (!confidenceMasks || confidenceMasks.length === 0) 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\tconst shaderSource = createMaskShaderSource(confidenceMasks.length);\n\t\t\t\tmaskShader = new ShaderPad(shaderSource, { canvas: sharedCanvas });\n\t\t\t\tfor (let i = 0; i < confidenceMasks.length; i++) {\n\t\t\t\t\tmaskShader.initializeTexture(`u_confidenceMask${i}`, dummyTexture);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdateMaskTexture(confidenceMasks);\n\t\t}\n\n\t\tshaderPad.registerHook('init', async () => {\n\t\t\tshaderPad.initializeTexture('u_segmentMask', dummyTexture, { preserveY: true });\n\t\t\tshaderPad.initializeUniform('u_numCategories', 'int', numCategories);\n\t\t\tawait initializeImageSegmenter();\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 (!imageSegmenter) 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 imageSegmenter.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) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (source.currentTime !== lastVideoTime) {\n\t\t\t\t\t\tlastVideoTime = source.currentTime;\n\t\t\t\t\t\t// TODO: I think segmentForVideo runs its own animation loop maybe? args are (source, startTime, callbackForVideo).\n\t\t\t\t\t\tconst result = imageSegmenter.segmentForVideo(source, performance.now());\n\t\t\t\t\t\tprocessSegmenterResults(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) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst result = imageSegmenter.segment(source);\n\t\t\t\t\tprocessSegmenterResults(result);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Segmenter Plugin] Segmentation error:', error);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.registerHook('destroy', () => {\n\t\t\tif (imageSegmenter) {\n\t\t\t\timageSegmenter.close();\n\t\t\t\timageSegmenter = 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});\n\n\t\tinjectGLSL(`\nuniform sampler2D u_segmentMask;\nuniform int u_numCategories;\n\nvec2 segmentAt(vec2 pos) {\n\tvec4 mask = texture(u_segmentMask, pos);\n\treturn vec2(mask.r, mask.g);\n}`);\n\t};\n}\n\nexport default segmenter;\n"],"mappings":"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","names":["dummyTexture","createMaskShaderSource","numMasks","uniforms","_","i","sampleByIndex","segmenter","config","textureName","options","defaultModelPath","shaderPad","context","injectGLSL","imageSegmenter","vision","lastVideoTime","runningMode","textureSources","numCategories","sharedCanvas","maskShader","initializeImageSegmenter","FilesetResolver","ImageSegmenter","labels","error","updateMaskTexture","confidenceMasks","textures","processSegmenterResults","result","shaderSource","index_default","updates","source","requiredMode","segmenter_default"]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/segmenter.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '../index';\nimport type { ImageSegmenter, ImageSegmenterResult, MPMask } from '@mediapipe/tasks-vision';\n\nexport interface SegmenterPluginOptions {\n\tmodelPath?: string;\n\toutputCategoryMask?: boolean;\n}\n\nconst dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\n\nfunction createMaskShaderSource(numMasks: number): string {\n\tconst uniforms = Array.from({ length: numMasks }, (_, i) => `uniform sampler2D u_confidenceMask${i};`).join('\\n');\n\n\t// GLSL doesn't allow dynamic indexing of samplers, so we need a switch-like construct.\n\tconst sampleByIndex = Array.from(\n\t\t{ length: numMasks },\n\t\t(_, i) => `\\t\\t${i > 0 ? 'else ' : ''}if (i == ${i}) c = texelFetch(u_confidenceMask${i}, texCoord, 0).r;`\n\t).join('\\n');\n\n\treturn `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nout vec4 outColor;\n${uniforms}\n\nvoid main() {\n\tivec2 texCoord = ivec2(v_uv * vec2(textureSize(u_confidenceMask0, 0)));\n\tfloat maxConfidence = 0.0;\n\tint maxIndex = 0;\n\n\tfor (int i = 0; i < ${numMasks}; i++) {\n\t\tfloat c = 0.0;\n${sampleByIndex}\n\t\tif (c > maxConfidence) {\n\t\t\tmaxConfidence = c;\n\t\t\tmaxIndex = i;\n\t\t}\n\t}\n\n\t// Normalize index: 0 = background, 1/(n-1) to 1 for foreground categories.\n\tfloat normalizedIndex = float(maxIndex) / float(max(1, ${numMasks - 1}));\n\toutColor = vec4(normalizedIndex, maxConfidence, 0.0, 1.0);\n}`;\n}\n\nfunction segmenter(config: { textureName: string; options?: SegmenterPluginOptions }) {\n\tconst { textureName, options } = config;\n\tconst defaultModelPath =\n\t\t'https://storage.googleapis.com/mediapipe-models/image_segmenter/hair_segmenter/float32/latest/hair_segmenter.tflite';\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL, gl } = context;\n\n\t\tlet imageSegmenter: ImageSegmenter | 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\tlet numCategories = 1;\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\t\tasync function initializeImageSegmenter() {\n\t\t\ttry {\n\t\t\t\tconst { FilesetResolver, ImageSegmenter } = 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\n\t\t\t\timageSegmenter = await ImageSegmenter.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: runningMode,\n\t\t\t\t\toutputCategoryMask: options?.outputCategoryMask ?? false, // Better for perf, and category can be inferred from confidence mask index.\n\t\t\t\t\toutputConfidenceMasks: true,\n\t\t\t\t});\n\n\t\t\t\tconst labels = imageSegmenter.getLabels();\n\t\t\t\tif (labels.length) numCategories = labels.length;\n\t\t\t\tshaderPad.updateUniforms({ u_numCategories: numCategories });\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Segmenter Plugin] Failed to initialize:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tfunction updateMaskTexture(confidenceMasks: MPMask[]) {\n\t\t\tif (!maskShader) return;\n\n\t\t\tconst textures: Record<string, WebGLTexture> = {};\n\t\t\tfor (let i = 0; i < confidenceMasks.length; i++) {\n\t\t\t\ttextures[`u_confidenceMask${i}`] = confidenceMasks[i].getAsWebGLTexture();\n\t\t\t}\n\t\t\tmaskShader.updateTextures(textures);\n\t\t\tmaskShader.draw();\n\t\t\tshaderPad.updateTextures({ u_segmentMask: sharedCanvas });\n\t\t}\n\n\t\tfunction processSegmenterResults(result: ImageSegmenterResult) {\n\t\t\tconst { confidenceMasks } = result;\n\t\t\tif (!confidenceMasks || confidenceMasks.length === 0) 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\tconst shaderSource = createMaskShaderSource(confidenceMasks.length);\n\t\t\t\tmaskShader = new ShaderPad(shaderSource, { canvas: sharedCanvas });\n\t\t\t\tfor (let i = 0; i < confidenceMasks.length; i++) {\n\t\t\t\t\tmaskShader.initializeTexture(`u_confidenceMask${i}`, dummyTexture);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdateMaskTexture(confidenceMasks);\n\t\t}\n\n\t\tshaderPad.registerHook('init', async () => {\n\t\t\tshaderPad.initializeTexture('u_segmentMask', 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_numCategories', 'int', numCategories);\n\t\t\tawait initializeImageSegmenter();\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 (!imageSegmenter) 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 imageSegmenter.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) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (source.currentTime !== lastVideoTime) {\n\t\t\t\t\t\tlastVideoTime = source.currentTime;\n\t\t\t\t\t\t// TODO: I think segmentForVideo runs its own animation loop maybe? args are (source, startTime, callbackForVideo).\n\t\t\t\t\t\tconst result = imageSegmenter.segmentForVideo(source, performance.now());\n\t\t\t\t\t\tprocessSegmenterResults(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) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst result = imageSegmenter.segment(source);\n\t\t\t\t\tprocessSegmenterResults(result);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Segmenter Plugin] Segmentation error:', error);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.registerHook('destroy', () => {\n\t\t\tif (imageSegmenter) {\n\t\t\t\timageSegmenter.close();\n\t\t\t\timageSegmenter = 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});\n\n\t\tinjectGLSL(`\nuniform sampler2D u_segmentMask;\nuniform int u_numCategories;\n\nvec2 segmentAt(vec2 pos) {\n\tvec4 mask = texture(u_segmentMask, pos);\n\treturn vec2(mask.r, mask.g);\n}`);\n\t};\n}\n\nexport default segmenter;\n"],"mappings":"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","names":["dummyTexture","createMaskShaderSource","numMasks","uniforms","_","i","sampleByIndex","segmenter","config","textureName","options","defaultModelPath","shaderPad","context","injectGLSL","gl","imageSegmenter","vision","lastVideoTime","runningMode","textureSources","numCategories","sharedCanvas","maskShader","initializeImageSegmenter","FilesetResolver","ImageSegmenter","labels","error","updateMaskTexture","confidenceMasks","textures","processSegmenterResults","result","shaderSource","index_default","updates","source","requiredMode","segmenter_default"]}
|