shaderpad 1.0.0-beta.74 → 1.0.0-beta.75
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/dist/dev/plugins/face.js +3 -0
- package/dist/dev/plugins/face.js.map +1 -1
- package/dist/dev/plugins/face.mjs +3 -0
- package/dist/dev/plugins/face.mjs.map +1 -1
- package/dist/plugins/face.js +35 -35
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +32 -32
- package/dist/plugins/face.mjs.map +1 -1
- package/package.json +1 -1
package/dist/dev/plugins/face.js
CHANGED
|
@@ -642,6 +642,7 @@ function face(config) {
|
|
|
642
642
|
const { injectGLSL, emit, updateTexture } = context;
|
|
643
643
|
const existingDetector = sharedDetectors.get(optionsKey);
|
|
644
644
|
const landmarksData = existingDetector?.landmarks.data ?? new Float32Array(LANDMARKS_TEXTURE_WIDTH * textureHeight * 4);
|
|
645
|
+
const mediapipeCanvas = existingDetector?.mediapipeCanvas ?? new OffscreenCanvas(1, 1);
|
|
645
646
|
const maskCanvas = existingDetector?.mask.canvas ?? new OffscreenCanvas(1, 1);
|
|
646
647
|
let detector;
|
|
647
648
|
let destroyed = false;
|
|
@@ -691,6 +692,7 @@ function face(config) {
|
|
|
691
692
|
modelAssetPath: options.modelPath,
|
|
692
693
|
delegate: "GPU"
|
|
693
694
|
},
|
|
695
|
+
canvas: mediapipeCanvas,
|
|
694
696
|
runningMode: "VIDEO",
|
|
695
697
|
numFaces: options.maxFaces,
|
|
696
698
|
minFaceDetectionConfidence: options.minFaceDetectionConfidence,
|
|
@@ -705,6 +707,7 @@ function face(config) {
|
|
|
705
707
|
}
|
|
706
708
|
const detector2 = {
|
|
707
709
|
landmarker: faceLandmarker,
|
|
710
|
+
mediapipeCanvas,
|
|
708
711
|
mask: initMaskRenderer(maskCanvas),
|
|
709
712
|
subscribers: /* @__PURE__ */ new Map(),
|
|
710
713
|
maxFaces: options.maxFaces,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/face.ts","../../../src/internal/error-codes.gen.ts","../../../src/internal/error-codes.dev.gen.ts","../../../src/internal/util.ts","../../../src/plugins/mediapipe-common.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '..';\nimport { spError } from '../internal/util';\nimport {\n\tcalculateBoundingBoxCenter,\n\tgenerateGLSLFn,\n\tgetOrCreateSharedResource,\n\tgetSharedFileset,\n\thashOptions,\n\tisMediaPipeSource,\n\tMediaPipeSource,\n} from './mediapipe-common';\nimport type { FaceLandmarker, FaceLandmarkerResult, NormalizedLandmark } from '@mediapipe/tasks-vision';\n\nexport interface FacePluginOptions {\n\tmodelPath?: string;\n\tmaxFaces?: number;\n\tminFaceDetectionConfidence?: number;\n\tminFacePresenceConfidence?: number;\n\tminTrackingConfidence?: number;\n\toutputFaceBlendshapes?: boolean;\n\toutputFacialTransformationMatrixes?: boolean;\n\thistory?: number;\n}\n\nexport interface FacePluginConfig {\n\ttextureName: string;\n\toptions?: FacePluginOptions;\n}\n\nconst MASK_VERTEX_SHADER = `#version 300 es\nin vec2 a_pos;\nout vec2 v_uv;\nvoid main() {\n\tv_uv = a_pos;\n\tgl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0);\n}`;\nconst MASK_FRAGMENT_SHADER = `#version 300 es\nprecision mediump float;\nuniform vec4 u_color;\nout vec4 outColor;\nvoid main() { outColor = u_color; }`;\nconst BLIT_FRAGMENT_SHADER = `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_texture;\nout vec4 outColor;\nvoid main() { outColor = texture(u_texture, v_uv); }`;\nconst FULLSCREEN_TRIANGLES = new Float32Array([0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1]);\n\nconst STANDARD_LANDMARK_COUNT = 478;\nconst CUSTOM_LANDMARK_COUNT = 2;\nconst LANDMARK_COUNT = STANDARD_LANDMARK_COUNT + CUSTOM_LANDMARK_COUNT;\nconst LANDMARKS_TEXTURE_WIDTH = 512;\nconst N_LANDMARK_METADATA_SLOTS = 1;\n\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst FACE_LANDMARK_L_EYE_CENTER = 473;\nconst FACE_LANDMARK_R_EYE_CENTER = 468;\nconst FACE_LANDMARK_NOSE_TIP = 4;\nconst FACE_LANDMARK_FACE_CENTER = STANDARD_LANDMARK_COUNT;\nconst FACE_LANDMARK_MOUTH_CENTER = STANDARD_LANDMARK_COUNT + 1;\nlet innerMouthIndices: number[] | null = null;\n\n/* Face mask channel layout:\n- R: additive bitfield for face regions. Since it’s additive, it handles overlapping regions.\n- G/B: tessellation ownership. When maxFaces is <= 16, G stores one-hot bits for\n faces 0-7 and B stores one-hot bits for faces 8-15 so overlapping faces\n remain decodable. Above 16 maxFaces, B falls back to storing faceIndex + 1 as\n an additive byte value, which will overcount on overlaps. */\nconst RED_REGION_NAMES = [\n\t'OVAL',\n\t'LEFT_EYEBROW',\n\t'RIGHT_EYEBROW',\n\t'LEFT_EYE',\n\t'RIGHT_EYE',\n\t'MOUTH',\n\t'INNER_MOUTH',\n] as const;\nconst GREEN_REGION_NAMES = ['FACE_0', 'FACE_1', 'FACE_2', 'FACE_3', 'FACE_4', 'FACE_5', 'FACE_6', 'FACE_7'] as const;\nconst BLUE_REGION_NAMES = [\n\t'FACE_8',\n\t'FACE_9',\n\t'FACE_10',\n\t'FACE_11',\n\t'FACE_12',\n\t'FACE_13',\n\t'FACE_14',\n\t'FACE_15',\n] as const;\nconst CHANNEL_BIT_SCALE = 255;\nconst GB_BITMASK_MAX_FACES = GREEN_REGION_NAMES.length + BLUE_REGION_NAMES.length;\n\nfunction createChannelBitValues<const T extends readonly string[]>(names: T): Record<T[number], number> {\n\treturn Object.fromEntries(names.map((name, i) => [name, 1 << i])) as Record<T[number], number>;\n}\n\nfunction normalizeChannelBitValues<T extends Record<string, number>>(bitValues: T): T {\n\treturn Object.fromEntries(\n\t\tObject.entries(bitValues).map(([name, bitValue]) => [name, bitValue / CHANNEL_BIT_SCALE]),\n\t) as T;\n}\n\nconst RED_REGION_BIT_VALUES = createChannelBitValues(RED_REGION_NAMES);\nconst GREEN_REGION_BIT_VALUES = createChannelBitValues(GREEN_REGION_NAMES);\nconst BLUE_REGION_BIT_VALUES = createChannelBitValues(BLUE_REGION_NAMES);\nconst RED_CHANNEL_VALUES = normalizeChannelBitValues(RED_REGION_BIT_VALUES);\nconst GREEN_CHANNEL_VALUES = normalizeChannelBitValues(GREEN_REGION_BIT_VALUES);\nconst BLUE_CHANNEL_VALUES = normalizeChannelBitValues(BLUE_REGION_BIT_VALUES);\n\nconst DEFAULT_FACE_OPTIONS: Required<Omit<FacePluginOptions, 'history'>> = {\n\tmodelPath:\n\t\t'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task',\n\tmaxFaces: 1,\n\tminFaceDetectionConfidence: 0.5,\n\tminFacePresenceConfidence: 0.5,\n\tminTrackingConfidence: 0.5,\n\toutputFaceBlendshapes: false,\n\toutputFacialTransformationMatrixes: false,\n};\n\nfunction fanTriangulate(indices: readonly number[]): number[] {\n\tconst tris: number[] = [];\n\tfor (let i = 1; i < indices.length - 1; ++i) {\n\t\ttris.push(indices[0], indices[i], indices[i + 1]);\n\t}\n\treturn tris;\n}\n\nfunction contourPath(connections: readonly { start: number; end: number }[]): number[] {\n\tconst indices = new Array<number>(connections.length + 1);\n\tindices[0] = connections[0].start;\n\tfor (let i = 0; i < connections.length; ++i) indices[i + 1] = connections[i].end;\n\treturn indices;\n}\n\nfunction stripTriangulate(a: readonly number[], b: readonly number[]): number[] {\n\tconst tris: number[] = [];\n\tconst n = Math.min(a.length, b.length);\n\tfor (let i = 0; i < n - 1; ++i) {\n\t\ttris.push(a[i], b[i], b[i + 1], a[i], b[i + 1], a[i + 1]);\n\t}\n\treturn tris;\n}\n\ntype FaceRegion = { indices: number[]; vertices: Float32Array };\nlet faceRegions: Record<string, FaceRegion> | null = null;\nfunction initFaceRegions(LandmarkerClass: typeof FaceLandmarker): void {\n\tif (!faceRegions) {\n\t\t// Eyes: 2 open chains / 8 connections each. Eyebrows: 2/4. Lips: 4/10.\n\t\tconst tesselationConnections = LandmarkerClass.FACE_LANDMARKS_TESSELATION;\n\t\tconst leftEyebrowConnections = LandmarkerClass.FACE_LANDMARKS_LEFT_EYEBROW;\n\t\tconst leftEyebrowUpper = contourPath(leftEyebrowConnections.slice(0, 4));\n\t\tconst leftEyebrowLower = contourPath(leftEyebrowConnections.slice(4, 8));\n\t\tconst rightEyebrowConnections = LandmarkerClass.FACE_LANDMARKS_RIGHT_EYEBROW;\n\t\tconst rightEyebrowUpper = contourPath(rightEyebrowConnections.slice(0, 4));\n\t\tconst rightEyebrowLower = contourPath(rightEyebrowConnections.slice(4, 8));\n\t\tconst leftEyeConnections = LandmarkerClass.FACE_LANDMARKS_LEFT_EYE;\n\t\tconst leftEyeUpper = contourPath(leftEyeConnections.slice(0, 8));\n\t\tconst leftEyeLower = contourPath(leftEyeConnections.slice(8, 16));\n\t\tconst rightEyeConnections = LandmarkerClass.FACE_LANDMARKS_RIGHT_EYE;\n\t\tconst rightEyeUpper = contourPath(rightEyeConnections.slice(0, 8));\n\t\tconst rightEyeLower = contourPath(rightEyeConnections.slice(8, 16));\n\t\tconst lipConnections = LandmarkerClass.FACE_LANDMARKS_LIPS;\n\t\tconst outerUpperLip = contourPath(lipConnections.slice(0, 10));\n\t\tconst outerLowerLip = contourPath(lipConnections.slice(10, 20));\n\t\tconst innerUpperLip = contourPath(lipConnections.slice(20, 30));\n\t\tconst innerLowerLip = contourPath(lipConnections.slice(30, 40));\n\t\tconst leftEyeIndices = [...leftEyeUpper, ...leftEyeLower.slice(1, -1)];\n\t\tconst rightEyeIndices = [...rightEyeUpper, ...rightEyeLower.slice(1, -1)];\n\t\tinnerMouthIndices = [...innerUpperLip, ...innerLowerLip.slice(1, -1)];\n\t\tconst tessellationHoleRemap = new Int16Array(LANDMARK_COUNT).fill(-1);\n\t\tfor (const index of leftEyeIndices) tessellationHoleRemap[index] = FACE_LANDMARK_L_EYE_CENTER;\n\t\tfor (const index of rightEyeIndices) tessellationHoleRemap[index] = FACE_LANDMARK_R_EYE_CENTER;\n\t\tfor (const index of innerMouthIndices) tessellationHoleRemap[index] = FACE_LANDMARK_MOUTH_CENTER;\n\t\tconst remapTessellationHole = (index: number) => {\n\t\t\tconst remapped = tessellationHoleRemap[index];\n\t\t\treturn remapped >= 0 ? remapped : index;\n\t\t};\n\t\tconst tesselation: number[] = [];\n\t\tfor (let i = 0; i < tesselationConnections.length - 2; i += 3) {\n\t\t\tconst a = remapTessellationHole(tesselationConnections[i].start);\n\t\t\tconst b = remapTessellationHole(tesselationConnections[i + 1].start);\n\t\t\tconst c = remapTessellationHole(tesselationConnections[i + 2].start);\n\t\t\tif (a !== b && a !== c && b !== c) tesselation.push(a, b, c);\n\t\t}\n\t\tconst leftEyebrowFill = stripTriangulate(leftEyebrowUpper, leftEyebrowLower);\n\t\tconst rightEyebrowFill = stripTriangulate(rightEyebrowUpper, rightEyebrowLower);\n\t\tconst leftEyeFill = stripTriangulate(leftEyeUpper, leftEyeLower);\n\t\tconst rightEyeFill = stripTriangulate(rightEyeUpper, rightEyeLower);\n\t\tconst mouthFill = [\n\t\t\t...stripTriangulate(outerUpperLip, innerUpperLip),\n\t\t\t...stripTriangulate(outerLowerLip, innerLowerLip),\n\t\t];\n\t\tconst innerMouthFill = stripTriangulate(innerUpperLip, innerLowerLip);\n\t\tconst ovalIndices = contourPath(LandmarkerClass.FACE_LANDMARKS_FACE_OVAL).slice(0, -1);\n\t\tfaceRegions = Object.fromEntries(\n\t\t\tObject.entries({\n\t\t\t\tLEFT_EYEBROW: leftEyebrowFill,\n\t\t\t\tRIGHT_EYEBROW: rightEyebrowFill,\n\t\t\t\tLEFT_EYE: leftEyeFill,\n\t\t\t\tRIGHT_EYE: rightEyeFill,\n\t\t\t\tMOUTH: mouthFill,\n\t\t\t\tINNER_MOUTH: innerMouthFill,\n\t\t\t\tTESSELATION: tesselation,\n\t\t\t\tOVAL: fanTriangulate(ovalIndices),\n\t\t\t}).map(([key, indices]) => [key, { indices, vertices: new Float32Array(indices.length * 2) }]),\n\t\t);\n\t}\n}\n\ninterface MaskRenderer {\n\tcanvas: OffscreenCanvas;\n\tgl: WebGL2RenderingContext;\n\tregionProgram: WebGLProgram;\n\tblitProgram: WebGLProgram;\n\tregionPositionBuffer: WebGLBuffer;\n\tquadBuffer: WebGLBuffer;\n\tregionPositionLocation: number;\n\tblitPositionLocation: number;\n\tcolorLocation: WebGLUniformLocation;\n\ttextureLocation: WebGLUniformLocation;\n\tscratchTexture: WebGLTexture;\n\tscratchFramebuffer: WebGLFramebuffer;\n}\n\ninterface Detector {\n\tlandmarker: FaceLandmarker;\n\tmask: MaskRenderer;\n\tsubscribers: Map<Function, boolean>;\n\tmaxFaces: number;\n\tstate: {\n\t\tnCalls: number;\n\t\trunningMode: 'IMAGE' | 'VIDEO';\n\t\tsource: MediaPipeSource | null;\n\t\tvideoTime: number;\n\t\tresultTimestamp: number;\n\t\tresult: FaceLandmarkerResult | null;\n\t\tpending: Promise<void>;\n\t\tnFaces: number;\n\t};\n\tlandmarks: {\n\t\tdata: Float32Array;\n\t\ttextureHeight: number;\n\t};\n}\nconst sharedDetectors = new Map<string, Detector>();\nconst sharedDetectorPromises = new Map<string, Promise<Detector | undefined>>();\n\nfunction createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n\tprogramName: string,\n): WebGLProgram {\n\tlet vertexShader: WebGLShader | null = null;\n\tlet fragmentShader: WebGLShader | null = null;\n\tlet program: WebGLProgram | null = null;\n\n\ttry {\n\t\tvertexShader = gl.createShader(gl.VERTEX_SHADER);\n\t\tfragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n\t\tprogram = gl.createProgram();\n\t\tif (!vertexShader || !fragmentShader || !program) throw new Error();\n\n\t\tgl.shaderSource(vertexShader, vertexSource);\n\t\tgl.compileShader(vertexShader);\n\t\tif (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) throw new Error();\n\n\t\tgl.shaderSource(fragmentShader, fragmentSource);\n\t\tgl.compileShader(fragmentShader);\n\t\tif (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) throw new Error();\n\n\t\tgl.attachShader(program, vertexShader);\n\t\tgl.attachShader(program, fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error();\n\n\t\treturn program;\n\t} catch {\n\t\tif (program) gl.deleteProgram(program);\n\t\tthrow spError(\n\t\t\t61,\n\t\t\t__SHADERPAD_DEV__ && {\n\t\t\t\tprogramName,\n\t\t\t\tvertexShaderInfoLog: vertexShader ? gl.getShaderInfoLog(vertexShader) : undefined,\n\t\t\t\tfragmentShaderInfoLog: fragmentShader ? gl.getShaderInfoLog(fragmentShader) : undefined,\n\t\t\t\tprogramInfoLog: program ? gl.getProgramInfoLog(program) : undefined,\n\t\t\t},\n\t\t);\n\t} finally {\n\t\tif (vertexShader) gl.deleteShader(vertexShader);\n\t\tif (fragmentShader) gl.deleteShader(fragmentShader);\n\t}\n}\n\nfunction initMaskRenderer(canvas: OffscreenCanvas): MaskRenderer {\n\tconst gl = canvas.getContext('webgl2', {\n\t\tantialias: false,\n\t\tpreserveDrawingBuffer: true,\n\t});\n\tif (!gl) {\n\t\tthrow spError(60, __SHADERPAD_DEV__ && { canvasWidth: canvas.width, canvasHeight: canvas.height });\n\t}\n\tconst regionProgram = createProgram(gl, MASK_VERTEX_SHADER, MASK_FRAGMENT_SHADER, 'face-mask-region');\n\tconst blitProgram = createProgram(gl, MASK_VERTEX_SHADER, BLIT_FRAGMENT_SHADER, 'face-mask-blit');\n\n\tlet framebufferStatus: number | undefined;\n\ttry {\n\t\tconst regionPositionBuffer = gl.createBuffer();\n\t\tconst regionPositionLocation = gl.getAttribLocation(regionProgram, 'a_pos');\n\t\tconst quadBuffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, FULLSCREEN_TRIANGLES, gl.STATIC_DRAW);\n\t\tconst blitPositionLocation = gl.getAttribLocation(blitProgram, 'a_pos');\n\t\tconst colorLocation = gl.getUniformLocation(regionProgram, 'u_color');\n\t\tconst textureLocation = gl.getUniformLocation(blitProgram, 'u_texture');\n\t\tconst scratchTexture = gl.createTexture();\n\t\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n\t\tconst scratchFramebuffer = gl.createFramebuffer();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, scratchFramebuffer);\n\t\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, scratchTexture, 0);\n\t\tframebufferStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n\t\tif (\n\t\t\t!regionPositionBuffer ||\n\t\t\tregionPositionLocation < 0 ||\n\t\t\t!quadBuffer ||\n\t\t\tblitPositionLocation < 0 ||\n\t\t\t!colorLocation ||\n\t\t\t!textureLocation ||\n\t\t\t!scratchTexture ||\n\t\t\t!scratchFramebuffer ||\n\t\t\tframebufferStatus !== gl.FRAMEBUFFER_COMPLETE\n\t\t) {\n\t\t\tthrow new Error();\n\t\t}\n\n\t\tgl.useProgram(blitProgram);\n\t\tgl.uniform1i(textureLocation, 0);\n\t\tgl.colorMask(true, true, true, false);\n\n\t\treturn {\n\t\t\tcanvas,\n\t\t\tgl,\n\t\t\tregionProgram,\n\t\t\tblitProgram,\n\t\t\tregionPositionBuffer,\n\t\t\tquadBuffer,\n\t\t\tregionPositionLocation,\n\t\t\tblitPositionLocation,\n\t\t\tcolorLocation,\n\t\t\ttextureLocation,\n\t\t\tscratchTexture,\n\t\t\tscratchFramebuffer,\n\t\t};\n\t} catch {\n\t\tthrow spError(62, __SHADERPAD_DEV__ && { framebufferStatus });\n\t}\n}\n\nfunction resizeMaskRenderer(mask: MaskRenderer, width: number, height: number) {\n\tconst { gl, canvas, scratchTexture } = mask;\n\tif (canvas.width === width && canvas.height === height) return;\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n}\n\nfunction drawRegionToScratch(\n\tmask: MaskRenderer,\n\tlandmarksData: Float32Array,\n\tfaceRegion: FaceRegion,\n\tfaceIdx: number,\n\tr: number,\n\tg: number,\n\tb: number,\n) {\n\tconst { gl, regionProgram, regionPositionBuffer, regionPositionLocation, colorLocation, scratchFramebuffer } = mask;\n\tconst baseIdx = N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT;\n\tconst { indices, vertices } = faceRegion;\n\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, scratchFramebuffer);\n\tgl.viewport(0, 0, mask.canvas.width, mask.canvas.height);\n\tgl.clearColor(0, 0, 0, 0);\n\tgl.clear(gl.COLOR_BUFFER_BIT);\n\tgl.useProgram(regionProgram);\n\tgl.bindBuffer(gl.ARRAY_BUFFER, regionPositionBuffer);\n\tgl.enableVertexAttribArray(regionPositionLocation);\n\tgl.vertexAttribPointer(regionPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\tgl.enable(gl.BLEND);\n\tgl.blendEquation(gl.MAX);\n\tgl.blendFunc(gl.ONE, gl.ONE);\n\n\tfor (let i = 0; i < indices.length; ++i) {\n\t\tconst landmarkIdx = (baseIdx + indices[i]) * 4;\n\t\tvertices[i * 2] = landmarksData[landmarkIdx];\n\t\tvertices[i * 2 + 1] = landmarksData[landmarkIdx + 1];\n\t}\n\tgl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\tgl.uniform4f(colorLocation, r, g, b, 1.0);\n\tgl.drawArrays(gl.TRIANGLES, 0, indices.length);\n}\n\nfunction accumulateScratch(mask: MaskRenderer) {\n\tconst { gl, blitProgram, quadBuffer, blitPositionLocation, scratchTexture } = mask;\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\tgl.viewport(0, 0, mask.canvas.width, mask.canvas.height);\n\tgl.useProgram(blitProgram);\n\tgl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);\n\tgl.enableVertexAttribArray(blitPositionLocation);\n\tgl.vertexAttribPointer(blitPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\tgl.activeTexture(gl.TEXTURE0);\n\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\tgl.enable(gl.BLEND);\n\tgl.blendEquation(gl.FUNC_ADD);\n\tgl.blendFunc(gl.ONE, gl.ONE);\n\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n}\n\nfunction updateLandmarksData(detector: Detector, faces: NormalizedLandmark[][]) {\n\tconst data = detector.landmarks.data;\n\tconst nFaces = faces.length;\n\tdata[0] = nFaces;\n\n\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\tconst landmarks = faces[faceIdx];\n\t\tfor (let landmarkIdx = 0; landmarkIdx < STANDARD_LANDMARK_COUNT; ++landmarkIdx) {\n\t\t\tconst landmark = landmarks[landmarkIdx];\n\t\t\tconst dataIdx = (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + landmarkIdx) * 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 faceCenter = calculateBoundingBoxCenter(\n\t\t\tdata,\n\t\t\tfaceIdx,\n\t\t\tALL_STANDARD_INDICES,\n\t\t\tLANDMARK_COUNT,\n\t\t\tN_LANDMARK_METADATA_SLOTS,\n\t\t);\n\t\tdata.set(faceCenter, (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + FACE_LANDMARK_FACE_CENTER) * 4);\n\t\tconst mouthCenter = calculateBoundingBoxCenter(data, faceIdx, innerMouthIndices!, LANDMARK_COUNT, 1);\n\t\tdata.set(mouthCenter, (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + FACE_LANDMARK_MOUTH_CENTER) * 4);\n\t}\n\n\tdetector.state.nFaces = nFaces;\n}\n\nfunction updateMask(detector: Detector, width: number, height: number) {\n\tconst {\n\t\tmask,\n\t\tmaxFaces,\n\t\tlandmarks,\n\t\tstate: { nFaces },\n\t} = detector;\n\tconst { gl, canvas: maskCanvas } = mask;\n\tconst { data: landmarksData } = landmarks;\n\n\tresizeMaskRenderer(mask, width, height);\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\tgl.viewport(0, 0, maskCanvas.width, maskCanvas.height);\n\tgl.clearColor(0, 0, 0, 0);\n\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\tif (!faceRegions) return;\n\n\tconst useTesselationBitmask = maxFaces <= GB_BITMASK_MAX_FACES;\n\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\tconst g =\n\t\t\tuseTesselationBitmask && faceIdx < GREEN_REGION_NAMES.length\n\t\t\t\t? GREEN_CHANNEL_VALUES[GREEN_REGION_NAMES[faceIdx]]\n\t\t\t\t: 0;\n\t\tconst b = useTesselationBitmask\n\t\t\t? faceIdx < GREEN_REGION_NAMES.length\n\t\t\t\t? 0\n\t\t\t\t: BLUE_CHANNEL_VALUES[BLUE_REGION_NAMES[faceIdx - GREEN_REGION_NAMES.length]]\n\t\t\t: (faceIdx + 1) / CHANNEL_BIT_SCALE;\n\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.TESSELATION, faceIdx, 0, g, b);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.OVAL, faceIdx, RED_CHANNEL_VALUES.OVAL, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.LEFT_EYEBROW,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.LEFT_EYEBROW,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.RIGHT_EYEBROW,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.RIGHT_EYEBROW,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.LEFT_EYE, faceIdx, RED_CHANNEL_VALUES.LEFT_EYE, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.RIGHT_EYE, faceIdx, RED_CHANNEL_VALUES.RIGHT_EYE, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.MOUTH, faceIdx, RED_CHANNEL_VALUES.MOUTH, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.INNER_MOUTH,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.INNER_MOUTH,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t}\n}\n\nfunction face(config: FacePluginConfig) {\n\tconst { textureName, options: { history, ...mediapipeOptions } = {} } = config;\n\tconst options = { ...DEFAULT_FACE_OPTIONS, ...mediapipeOptions };\n\tconst optionsKey = hashOptions({ ...options, textureName });\n\n\tconst nLandmarksMax = options.maxFaces * 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, emit, updateTexture } = 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 maskCanvas = existingDetector?.mask.canvas ?? new OffscreenCanvas(1, 1);\n\t\tlet detector: Detector | undefined;\n\t\tlet destroyed = false;\n\t\tlet historySlot = -1;\n\t\tlet pendingBackfillSlots: number[] = [];\n\n\t\tfunction writeTextures(historySlots: number | number[]) {\n\t\t\tif (!detector) return;\n\t\t\tconst nFaces = detector.state.nFaces;\n\t\t\tconst nSlots = nFaces * LANDMARK_COUNT + N_LANDMARK_METADATA_SLOTS;\n\t\t\tconst rowsToUpdate = Math.ceil(nSlots / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tconst targetHistorySlots = history ? historySlots : undefined;\n\t\t\tupdateTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{\n\t\t\t\t\tdata: detector.landmarks.data,\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\ttargetHistorySlots,\n\t\t\t);\n\t\t\tupdateTexture('u_faceMask', detector.mask.canvas, targetHistorySlots);\n\t\t\tshaderPad.updateUniforms({ u_nFaces: nFaces }, { allowMissing: true });\n\t\t}\n\n\t\tfunction onResult() {\n\t\t\tif (history) {\n\t\t\t\twriteTextures(pendingBackfillSlots.length > 0 ? pendingBackfillSlots : historySlot);\n\t\t\t\tpendingBackfillSlots = [];\n\t\t\t} else {\n\t\t\t\twriteTextures(historySlot);\n\t\t\t}\n\t\t\temit('face:result', detector!.state.result);\n\t\t}\n\n\t\tasync function initializeDetector() {\n\t\t\tdetector = await getOrCreateSharedResource(\n\t\t\t\toptionsKey,\n\t\t\t\tsharedDetectors,\n\t\t\t\tsharedDetectorPromises,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst [mediaPipe, { FaceLandmarker }] = await Promise.all([\n\t\t\t\t\t\tgetSharedFileset(),\n\t\t\t\t\t\timport('@mediapipe/tasks-vision'),\n\t\t\t\t\t]);\n\t\t\t\t\tif (destroyed) return;\n\n\t\t\t\t\tconst faceLandmarker = await FaceLandmarker.createFromOptions(mediaPipe, {\n\t\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\t\tmodelAssetPath: options.modelPath,\n\t\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\t\tnumFaces: options.maxFaces,\n\t\t\t\t\t\tminFaceDetectionConfidence: options.minFaceDetectionConfidence,\n\t\t\t\t\t\tminFacePresenceConfidence: options.minFacePresenceConfidence,\n\t\t\t\t\t\tminTrackingConfidence: options.minTrackingConfidence,\n\t\t\t\t\t\toutputFaceBlendshapes: options.outputFaceBlendshapes,\n\t\t\t\t\t\toutputFacialTransformationMatrixes: options.outputFacialTransformationMatrixes,\n\t\t\t\t\t});\n\t\t\t\t\tif (destroyed) {\n\t\t\t\t\t\tfaceLandmarker.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst detector: Detector = {\n\t\t\t\t\t\tlandmarker: faceLandmarker,\n\t\t\t\t\t\tmask: initMaskRenderer(maskCanvas),\n\t\t\t\t\t\tsubscribers: new Map(),\n\t\t\t\t\t\tmaxFaces: options.maxFaces,\n\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\tnCalls: 0,\n\t\t\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\t\t\tsource: null,\n\t\t\t\t\t\t\tvideoTime: -1,\n\t\t\t\t\t\t\tresultTimestamp: 0,\n\t\t\t\t\t\t\tresult: null,\n\t\t\t\t\t\t\tpending: Promise.resolve(),\n\t\t\t\t\t\t\tnFaces: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlandmarks: {\n\t\t\t\t\t\t\tdata: landmarksData,\n\t\t\t\t\t\t\ttextureHeight,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tinitFaceRegions(FaceLandmarker);\n\t\t\t\t\treturn detector;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!detector || destroyed) return;\n\t\t\tdetector.subscribers.set(onResult, false);\n\t\t}\n\t\tconst initPromise = initializeDetector();\n\n\t\tasync function detectFaces(source: MediaPipeSource) {\n\t\t\tconst now = performance.now();\n\t\t\tawait initPromise;\n\t\t\tif (!detector) return;\n\t\t\tconst callOrder = ++detector.state.nCalls;\n\n\t\t\tdetector.state.pending = detector.state.pending.then(async () => {\n\t\t\t\tif (!detector || callOrder !== detector.state.nCalls) 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({\n\t\t\t\t\t\trunningMode: requiredMode,\n\t\t\t\t\t});\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 = source instanceof HTMLVideoElement ? source.currentTime : -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: FaceLandmarkerResult | undefined;\n\t\t\t\t\tlet width: number, height: number;\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\twidth = source.videoWidth;\n\t\t\t\t\t\theight = source.videoHeight;\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\twidth = source.width;\n\t\t\t\t\t\theight = source.height;\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.faceLandmarks);\n\t\t\t\t\t\tupdateMask(detector, width, height);\n\t\t\t\t\t\tfor (const [cb, needsResult] of detector.subscribers.entries()) {\n\t\t\t\t\t\t\tif (needsResult) {\n\t\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t\t\tdetector.subscribers.set(cb, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (detector.state.result) {\n\t\t\t\t\tfor (const [cb, needsResult] of detector.subscribers.entries()) {\n\t\t\t\t\t\tif (needsResult) {\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t\tdetector.subscribers.set(cb, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\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('_init', () => {\n\t\t\tshaderPad.initializeUniform('u_maxFaces', 'int', options.maxFaces, { allowMissing: true });\n\t\t\tshaderPad.initializeUniform('u_nFaces', 'int', 0, { allowMissing: true });\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{\n\t\t\t\t\tdata: landmarksData,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: textureHeight,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tinternalFormat: 'RGBA32F',\n\t\t\t\t\ttype: 'FLOAT',\n\t\t\t\t\tminFilter: 'NEAREST',\n\t\t\t\t\tmagFilter: 'NEAREST',\n\t\t\t\t\thistory,\n\t\t\t\t},\n\t\t\t);\n\t\t\tshaderPad.initializeTexture('u_faceMask', maskCanvas, {\n\t\t\t\tminFilter: 'NEAREST',\n\t\t\t\tmagFilter: 'NEAREST',\n\t\t\t\thistory,\n\t\t\t});\n\t\t\tinitPromise.then(() => {\n\t\t\t\tif (destroyed || !detector) return;\n\t\t\t\temit('face:ready');\n\t\t\t});\n\t\t});\n\n\t\tfunction requestFaces(source: MediaPipeSource) {\n\t\t\tif (!detector) return;\n\t\t\tif (history) {\n\t\t\t\thistorySlot = (historySlot + 1) % (history + 1);\n\t\t\t\twriteTextures(historySlot);\n\t\t\t\tpendingBackfillSlots.push(historySlot);\n\t\t\t}\n\t\t\tdetector.subscribers.set(onResult, true);\n\t\t\tdetectFaces(source);\n\t\t}\n\n\t\tshaderPad.on('initializeTexture', (name: string, source: TextureSource) => {\n\t\t\tif (name === textureName && isMediaPipeSource(source)) {\n\t\t\t\trequestFaces(source);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.on('updateTextures', (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (isMediaPipeSource(source)) {\n\t\t\t\trequestFaces(source);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.on('destroy', () => {\n\t\t\tdestroyed = true;\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.gl.deleteProgram(detector.mask.regionProgram);\n\t\t\t\t\tdetector.mask.gl.deleteProgram(detector.mask.blitProgram);\n\t\t\t\t\tdetector.mask.gl.deleteBuffer(detector.mask.regionPositionBuffer);\n\t\t\t\t\tdetector.mask.gl.deleteBuffer(detector.mask.quadBuffer);\n\t\t\t\t\tdetector.mask.gl.deleteTexture(detector.mask.scratchTexture);\n\t\t\t\t\tdetector.mask.gl.deleteFramebuffer(detector.mask.scratchFramebuffer);\n\t\t\t\t\tsharedDetectors.delete(optionsKey);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdetector = undefined;\n\t\t});\n\n\t\tconst { fn, historyParams } = generateGLSLFn(history);\n\t\tconst sampleMask = history ? `_sampleFaceMask(pos, framesAgo)` : `texture(u_faceMask, pos)`;\n\t\tconst decodeFaceBitIndex = Array.from(\n\t\t\t{ length: GB_BITMASK_MAX_FACES - 1 },\n\t\t\t(_, i) => `step(${2 ** (i + 1)}.0, faceBitF)`,\n\t\t).join(' + ');\n\t\tconst decodeFaceIndex =\n\t\t\toptions.maxFaces <= GB_BITMASK_MAX_FACES\n\t\t\t\t? `uint faceBits = (uint(mask.b * ${CHANNEL_BIT_SCALE}.0 + 0.5) << 8) | uint(mask.g * ${CHANNEL_BIT_SCALE}.0 + 0.5);\n\tuint faceBit = faceBits & (~faceBits + 1u);\n\tfloat faceBitF = float(faceBit);\n\tfloat hasFace = sign(faceBitF);\n\tfloat faceIndex = ${decodeFaceBitIndex} - (1.0 - hasFace);`\n\t\t\t\t: `float faceIndex = float(int(uint(mask.b * ${CHANNEL_BIT_SCALE}.0 + 0.5)) - 1);`;\n\n\t\tconst checkAt = (fnName: string, ...regionNames: (keyof typeof RED_REGION_BIT_VALUES)[]) =>\n\t\t\tfn(\n\t\t\t\t'vec2',\n\t\t\t\t`${fnName}At`,\n\t\t\t\t'vec2 pos',\n\t\t\t\t`vec4 mask = ${sampleMask};\n\t${decodeFaceIndex}\n\tuint bits = uint(mask.r * ${CHANNEL_BIT_SCALE}.0 + 0.5);\n\tfloat hit = sign(float(bits & ${regionNames.reduce(\n\t\t(mask, regionName) => mask | RED_REGION_BIT_VALUES[regionName],\n\t\t0,\n\t)}u));\n\treturn vec2(hit, mix(-1.0, faceIndex, hit));`,\n\t\t\t);\n\n\t\tconst combineLeftRight = (fnName: string, leftFn: string, rightFn: string) =>\n\t\t\tfn(\n\t\t\t\t'vec2',\n\t\t\t\t`${fnName}At`,\n\t\t\t\t'vec2 pos',\n\t\t\t\t`vec2 left = ${leftFn}(pos${historyParams});\n\tvec2 right = ${rightFn}(pos${historyParams});\n\treturn mix(right, left, left.x);`,\n\t\t\t);\n\n\t\tconst checkIn = (fnNames: string[]) =>\n\t\t\tfnNames\n\t\t\t\t.map(fnName =>\n\t\t\t\t\tfn(\n\t\t\t\t\t\t'float',\n\t\t\t\t\t\t`in${fnName[0].toUpperCase() + fnName.slice(1)}`,\n\t\t\t\t\t\t'vec2 pos',\n\t\t\t\t\t\t`vec2 a = ${fnName}At(pos${historyParams}); return step(0.0, a.y) * a.x;`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.join('\\n');\n\n\t\tinjectGLSL(`\nuniform int u_maxFaces;\nuniform int u_nFaces;\nuniform highp sampler2D${history ? 'Array' : ''} u_faceLandmarksTex;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_faceLandmarksTexFrameOffset;`\n\t\t\t\t: ''\n\t\t}\nuniform mediump sampler2D${history ? 'Array' : ''} u_faceMask;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_faceMaskFrameOffset;`\n\t\t\t\t: ''\n\t\t}\n\n#define FACE_LANDMARK_L_EYE_CENTER ${FACE_LANDMARK_L_EYE_CENTER}\n#define FACE_LANDMARK_R_EYE_CENTER ${FACE_LANDMARK_R_EYE_CENTER}\n#define FACE_LANDMARK_NOSE_TIP ${FACE_LANDMARK_NOSE_TIP}\n#define FACE_LANDMARK_FACE_CENTER ${FACE_LANDMARK_FACE_CENTER}\n#define FACE_LANDMARK_MOUTH_CENTER ${FACE_LANDMARK_MOUTH_CENTER}\n\n${fn(\n\t'int',\n\t'nFacesAt',\n\t'',\n\thistory\n\t\t? `\n\tint layer = (u_faceLandmarksTexFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn int(texelFetch(u_faceLandmarksTex, ivec3(0, 0, layer), 0).r + 0.5);`\n\t\t: `\n\treturn int(texelFetch(u_faceLandmarksTex, ivec2(0, 0), 0).r + 0.5);`,\n)}\n${fn(\n\t'vec4',\n\t'faceLandmark',\n\t'int faceIndex, int landmarkIndex',\n\t`int i = ${N_LANDMARK_METADATA_SLOTS} + faceIndex * ${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_faceLandmarksTexFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn texelFetch(u_faceLandmarksTex, ivec3(x, y, layer), 0);`\n\t\t\t: `\n\treturn texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);`\n\t}`,\n)}\n${\n\thistory\n\t\t? `\nvec4 _sampleFaceMask(vec2 pos, int framesAgo) {\n\tint layer = (u_faceMaskFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn texture(u_faceMask, vec3(pos, float(layer)));\n}\n`\n\t\t: ''\n}\n${checkAt('leftEyebrow', 'LEFT_EYEBROW')}\n${checkAt('rightEyebrow', 'RIGHT_EYEBROW')}\n${checkAt('leftEye', 'LEFT_EYE')}\n${checkAt('rightEye', 'RIGHT_EYE')}\n${checkAt('lips', 'MOUTH')}\n${checkAt('mouth', 'MOUTH', 'INNER_MOUTH')}\n${checkAt('innerMouth', 'INNER_MOUTH')}\n${checkAt('faceOval', 'OVAL')}\n${fn(\n\t'vec2',\n\t'faceAt',\n\t'vec2 pos',\n\t`vec4 mask = ${sampleMask};\n\t${decodeFaceIndex}\n\treturn vec2(step(0.0, faceIndex), faceIndex);`,\n)}\n${combineLeftRight('eye', 'leftEyeAt', 'rightEyeAt')}\n${combineLeftRight('eyebrow', 'leftEyebrowAt', 'rightEyebrowAt')}\n${checkIn(['eyebrow', 'eye', 'mouth', 'innerMouth', 'lips', 'face'])}`);\n\t};\n}\n\nexport default face;\n","// Generated by scripts/generate-error-code-artifacts.mjs. Do not edit manually.\nexport type ErrorCode = number;\n\nexport const ERROR_DOCS_BASE_URL = 'https://mry.ac/s/';\n\nexport function errorUrl(code: ErrorCode) {\n\treturn `${ERROR_DOCS_BASE_URL}${code}`;\n}\n","// Generated by scripts/generate-error-code-artifacts.mjs. Do not edit manually.\nimport type { ErrorCode } from './error-codes.gen.js';\n\ntype DevErrorDetails = {\n\ttitle: string;\n\tsummary: string;\n};\n\nexport const DEV_ERRORS: Record<ErrorCode, DevErrorDetails> | undefined = __SHADERPAD_DEV__\n\t? {\n\t\t\t'0': {\n\t\t\t\ttitle: 'WebGL2 Context Unavailable',\n\t\t\t\tsummary: 'ShaderPad could not create a WebGL2 rendering context.',\n\t\t\t},\n\t\t\t'1': {\n\t\t\t\ttitle: 'Program Allocation Failed',\n\t\t\t\tsummary: 'ShaderPad could not allocate a WebGL program object.',\n\t\t\t},\n\t\t\t'2': {\n\t\t\t\ttitle: 'Program Link Failed',\n\t\t\t\tsummary: 'ShaderPad compiled the shaders but failed to link them into a WebGL program.',\n\t\t\t},\n\t\t\t'3': {\n\t\t\t\ttitle: 'Unknown GL Constant',\n\t\t\t\tsummary: 'ShaderPad received a WebGL constant name it does not recognize.',\n\t\t\t},\n\t\t\t'4': {\n\t\t\t\ttitle: 'Shader Compilation Failed',\n\t\t\t\tsummary: 'A vertex or fragment shader failed to compile.',\n\t\t\t},\n\t\t\t'5': {\n\t\t\t\ttitle: 'Texture Units Exhausted',\n\t\t\t\tsummary: 'ShaderPad tried to reserve more texture units than this device exposes.',\n\t\t\t},\n\t\t\t'6': {\n\t\t\t\ttitle: 'Float Color Buffer Extension Missing',\n\t\t\t\tsummary: 'ShaderPad requested a float render texture, but EXT_color_buffer_float is unavailable.',\n\t\t\t},\n\t\t\t'7': {\n\t\t\t\ttitle: 'Uniform Already Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to register a uniform name that was already registered.',\n\t\t\t},\n\t\t\t'8': {\n\t\t\t\ttitle: 'Invalid Uniform Type',\n\t\t\t\tsummary: 'ShaderPad received an unsupported uniform type string.',\n\t\t\t},\n\t\t\t'9': {\n\t\t\t\ttitle: 'Uniform Array Length Mismatch',\n\t\t\t\tsummary: 'ShaderPad was asked to initialize a uniform array with the wrong number of elements.',\n\t\t\t},\n\t\t\t'10': {\n\t\t\t\ttitle: 'Uniform Array Update Expected An Array',\n\t\t\t\tsummary: 'ShaderPad attempted to update a uniform array, but the provided value was not an array.',\n\t\t\t},\n\t\t\t'11': {\n\t\t\t\ttitle: 'Uniform Array Update Too Large',\n\t\t\t\tsummary: 'ShaderPad received more uniform array elements than the initialized array can hold.',\n\t\t\t},\n\t\t\t'12': {\n\t\t\t\ttitle: 'Uniform Array Element Size Mismatch',\n\t\t\t\tsummary: 'At least one uniform array element has the wrong scalar or vector length.',\n\t\t\t},\n\t\t\t'13': {\n\t\t\t\ttitle: 'Uniform Array Start Index Invalid',\n\t\t\t\tsummary: 'ShaderPad could not find the requested starting index for a uniform array.',\n\t\t\t},\n\t\t\t'14': {\n\t\t\t\ttitle: 'Uniform Value Length Invalid',\n\t\t\t\tsummary: 'ShaderPad received a scalar or vector uniform update with the wrong component count.',\n\t\t\t},\n\t\t\t'15': {\n\t\t\t\ttitle: 'Texture Allocation Failed',\n\t\t\t\tsummary: 'ShaderPad could not create a WebGL texture object.',\n\t\t\t},\n\t\t\t'16': {\n\t\t\t\ttitle: 'Texture Already Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to initialize a texture name that is already registered.',\n\t\t\t},\n\t\t\t'17': {\n\t\t\t\ttitle: 'Texture Source Dimensions Invalid',\n\t\t\t\tsummary: 'ShaderPad could not determine valid width and height values for the texture source.',\n\t\t\t},\n\t\t\t'18': {\n\t\t\t\ttitle: 'Texture Not Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to update a texture name that has not been initialized.',\n\t\t\t},\n\t\t\t'19': {\n\t\t\t\ttitle: 'Uniform Missing During Initialization',\n\t\t\t\tsummary:\n\t\t\t\t\t'ShaderPad could not initialize a uniform because the shader program does not contain that symbol.',\n\t\t\t},\n\t\t\t'20': {\n\t\t\t\ttitle: 'Uniform Missing During Update',\n\t\t\t\tsummary:\n\t\t\t\t\t'ShaderPad could not update a uniform because the shader program does not contain that symbol.',\n\t\t\t},\n\t\t\t'60': {\n\t\t\t\ttitle: 'Face Mask Renderer Context Unavailable',\n\t\t\t\tsummary: 'The face plugin could not create the offscreen WebGL2 context used for face-mask rendering.',\n\t\t\t},\n\t\t\t'61': {\n\t\t\t\ttitle: 'Face Mask Shader Setup Failed',\n\t\t\t\tsummary: 'The face plugin could not build the shaders it uses for face-mask rendering.',\n\t\t\t},\n\t\t\t'62': {\n\t\t\t\ttitle: 'Face Mask Renderer Initialization Failed',\n\t\t\t\tsummary: 'The face plugin could not finish setting up its internal face-mask renderer.',\n\t\t\t},\n\t\t}\n\t: undefined;\n","import { errorUrl, type ErrorCode } from './error-codes.gen.js';\nimport { DEV_ERRORS } from './error-codes.dev.gen.js';\n\ntype DevContext = Record<string, unknown> | false | undefined;\ntype ShaderPadError = Error & { code: ErrorCode };\n\nfunction withCode(message: string, code: ErrorCode): ShaderPadError {\n\tconst error = new Error(message) as ShaderPadError;\n\terror.code = code;\n\treturn error;\n}\n\nfunction renderContext(context: Record<string, unknown>) {\n\tconst lines = ['Context:'];\n\n\tfor (const [key, value] of Object.entries(context)) {\n\t\tif (value === undefined) continue;\n\n\t\tconst rendered =\n\t\t\ttypeof value === 'string'\n\t\t\t\t? value\n\t\t\t\t: (JSON.stringify(value, null, 2) ??\n\t\t\t\t\t(typeof value === 'bigint' ||\n\t\t\t\t\ttypeof value === 'number' ||\n\t\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\t\tvalue == null\n\t\t\t\t\t\t? String(value)\n\t\t\t\t\t\t: ''));\n\n\t\tif (!rendered) continue;\n\t\tlines.push(rendered.includes('\\n') ? `${key}:\\n${rendered}` : `${key}: ${rendered}`);\n\t}\n\n\treturn lines.length > 1 ? lines.join('\\n') : '';\n}\n\nfunction renderDevMessage(code: ErrorCode, context?: DevContext) {\n\tconst error = DEV_ERRORS?.[code];\n\tconst parts = error\n\t\t? [`[ShaderPad ${code}] ${error.title}`, error.summary, `Docs: ${errorUrl(code)}`]\n\t\t: [`[ShaderPad ${code}] ${errorUrl(code)}`];\n\n\tif (context) {\n\t\tconst renderedContext = renderContext(context);\n\t\tif (renderedContext) parts.push(renderedContext);\n\t}\n\n\treturn parts.join('\\n\\n');\n}\n\nexport function spError(code: ErrorCode, context?: DevContext) {\n\treturn withCode(__SHADERPAD_DEV__ ? renderDevMessage(code, context) : `ShaderPad error: ${errorUrl(code)}`, code);\n}\n\nexport function safeMod(i: number, m: number): number {\n\treturn ((i % m) + m) % m;\n}\n","import { TextureSource } from '..';\n\nexport const dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\n\nexport type MediaPipeSource = HTMLVideoElement | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas;\n\nexport function isMediaPipeSource(source: TextureSource): source is MediaPipeSource {\n\treturn (\n\t\tsource instanceof HTMLVideoElement ||\n\t\tsource instanceof HTMLImageElement ||\n\t\tsource instanceof HTMLCanvasElement ||\n\t\tsource instanceof OffscreenCanvas\n\t);\n}\n\nexport function hashOptions(options: object): string {\n\treturn JSON.stringify(options, Object.keys(options).sort());\n}\n\nexport function getOrCreateSharedResource<T>(\n\tkey: string,\n\tsharedResources: Map<string, T>,\n\tsharedResourcePromises: Map<string, Promise<T | undefined>>,\n\tcreate: () => Promise<T | undefined>,\n): Promise<T | undefined> {\n\tconst existing = sharedResources.get(key);\n\tif (existing) return Promise.resolve(existing);\n\n\tconst pending = sharedResourcePromises.get(key);\n\tif (pending) return pending;\n\n\tlet promise: Promise<T | undefined>;\n\tpromise = create()\n\t\t.then(resource => {\n\t\t\tif (resource) {\n\t\t\t\tsharedResources.set(key, resource);\n\t\t\t}\n\t\t\treturn resource;\n\t\t})\n\t\t.finally(() => {\n\t\t\tif (sharedResourcePromises.get(key) === promise) {\n\t\t\t\tsharedResourcePromises.delete(key);\n\t\t\t}\n\t\t});\n\tsharedResourcePromises.set(key, promise);\n\treturn promise;\n}\n\nexport function calculateBoundingBoxCenter(\n\tdata: Float32Array,\n\tentityIdx: number,\n\tlandmarkIndices: readonly number[] | number[],\n\tlandmarkCount: number,\n\toffset: number = 0,\n): [number, number, number, number] {\n\tlet minX = Infinity,\n\t\tmaxX = -Infinity,\n\t\tminY = Infinity,\n\t\tmaxY = -Infinity,\n\t\tavgZ = 0,\n\t\tavgVisibility = 0;\n\n\tfor (const idx of landmarkIndices) {\n\t\tconst dataIdx = (offset + entityIdx * landmarkCount + idx) * 4;\n\t\tconst x = data[dataIdx];\n\t\tconst y = data[dataIdx + 1];\n\t\tminX = Math.min(minX, x);\n\t\tmaxX = Math.max(maxX, x);\n\t\tminY = Math.min(minY, y);\n\t\tmaxY = Math.max(maxY, y);\n\t\tavgZ += data[dataIdx + 2];\n\t\tavgVisibility += data[dataIdx + 3];\n\t}\n\n\treturn [\n\t\t(minX + maxX) / 2,\n\t\t(minY + maxY) / 2,\n\t\tavgZ / landmarkIndices.length,\n\t\tavgVisibility / landmarkIndices.length,\n\t];\n}\n\nlet filesetPromise: Promise<any> | null = null;\nexport function getSharedFileset(): Promise<any> {\n\tif (!filesetPromise) {\n\t\tfilesetPromise = import('@mediapipe/tasks-vision').then(({ FilesetResolver }) =>\n\t\t\tFilesetResolver.forVisionTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision/wasm'),\n\t\t);\n\t}\n\treturn filesetPromise;\n}\n\nexport function generateGLSLFn(history: number | undefined) {\n\tconst historyParams = history ? ', framesAgo' : '';\n\tconst fn = history\n\t\t? (returnType: string, name: string, args: string, body: string) => {\n\t\t\t\tconst argsOnly = args.replace(/\\w+ /g, '');\n\t\t\t\tconst historyArgs = args ? `${args}, int framesAgo` : 'int framesAgo';\n\t\t\t\tconst callArgs = argsOnly ? `${argsOnly}, 0` : '0';\n\t\t\t\treturn `${returnType} ${name}(${historyArgs}) {\\n${body}\\n}\n${returnType} ${name}(${args}) { return ${name}(${callArgs}); }`;\n\t\t\t}\n\t\t: (returnType: string, name: string, args: string, body: string) =>\n\t\t\t\t`${returnType} ${name}(${args}) {\\n${body}\\n}`;\n\treturn { historyParams, fn };\n}\n"],"mappings":"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","names":["detector"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/face.ts","../../../src/internal/error-codes.gen.ts","../../../src/internal/error-codes.dev.gen.ts","../../../src/internal/util.ts","../../../src/plugins/mediapipe-common.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '..';\nimport { spError } from '../internal/util';\nimport {\n\tcalculateBoundingBoxCenter,\n\tgenerateGLSLFn,\n\tgetOrCreateSharedResource,\n\tgetSharedFileset,\n\thashOptions,\n\tisMediaPipeSource,\n\tMediaPipeSource,\n} from './mediapipe-common';\nimport type { FaceLandmarker, FaceLandmarkerResult, NormalizedLandmark } from '@mediapipe/tasks-vision';\n\nexport interface FacePluginOptions {\n\tmodelPath?: string;\n\tmaxFaces?: number;\n\tminFaceDetectionConfidence?: number;\n\tminFacePresenceConfidence?: number;\n\tminTrackingConfidence?: number;\n\toutputFaceBlendshapes?: boolean;\n\toutputFacialTransformationMatrixes?: boolean;\n\thistory?: number;\n}\n\nexport interface FacePluginConfig {\n\ttextureName: string;\n\toptions?: FacePluginOptions;\n}\n\nconst MASK_VERTEX_SHADER = `#version 300 es\nin vec2 a_pos;\nout vec2 v_uv;\nvoid main() {\n\tv_uv = a_pos;\n\tgl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0);\n}`;\nconst MASK_FRAGMENT_SHADER = `#version 300 es\nprecision mediump float;\nuniform vec4 u_color;\nout vec4 outColor;\nvoid main() { outColor = u_color; }`;\nconst BLIT_FRAGMENT_SHADER = `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_texture;\nout vec4 outColor;\nvoid main() { outColor = texture(u_texture, v_uv); }`;\nconst FULLSCREEN_TRIANGLES = new Float32Array([0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1]);\n\nconst STANDARD_LANDMARK_COUNT = 478;\nconst CUSTOM_LANDMARK_COUNT = 2;\nconst LANDMARK_COUNT = STANDARD_LANDMARK_COUNT + CUSTOM_LANDMARK_COUNT;\nconst LANDMARKS_TEXTURE_WIDTH = 512;\nconst N_LANDMARK_METADATA_SLOTS = 1;\n\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst FACE_LANDMARK_L_EYE_CENTER = 473;\nconst FACE_LANDMARK_R_EYE_CENTER = 468;\nconst FACE_LANDMARK_NOSE_TIP = 4;\nconst FACE_LANDMARK_FACE_CENTER = STANDARD_LANDMARK_COUNT;\nconst FACE_LANDMARK_MOUTH_CENTER = STANDARD_LANDMARK_COUNT + 1;\nlet innerMouthIndices: number[] | null = null;\n\n/* Face mask channel layout:\n- R: additive bitfield for face regions. Since it’s additive, it handles overlapping regions.\n- G/B: tessellation ownership. When maxFaces is <= 16, G stores one-hot bits for\n faces 0-7 and B stores one-hot bits for faces 8-15 so overlapping faces\n remain decodable. Above 16 maxFaces, B falls back to storing faceIndex + 1 as\n an additive byte value, which will overcount on overlaps. */\nconst RED_REGION_NAMES = [\n\t'OVAL',\n\t'LEFT_EYEBROW',\n\t'RIGHT_EYEBROW',\n\t'LEFT_EYE',\n\t'RIGHT_EYE',\n\t'MOUTH',\n\t'INNER_MOUTH',\n] as const;\nconst GREEN_REGION_NAMES = ['FACE_0', 'FACE_1', 'FACE_2', 'FACE_3', 'FACE_4', 'FACE_5', 'FACE_6', 'FACE_7'] as const;\nconst BLUE_REGION_NAMES = [\n\t'FACE_8',\n\t'FACE_9',\n\t'FACE_10',\n\t'FACE_11',\n\t'FACE_12',\n\t'FACE_13',\n\t'FACE_14',\n\t'FACE_15',\n] as const;\nconst CHANNEL_BIT_SCALE = 255;\nconst GB_BITMASK_MAX_FACES = GREEN_REGION_NAMES.length + BLUE_REGION_NAMES.length;\n\nfunction createChannelBitValues<const T extends readonly string[]>(names: T): Record<T[number], number> {\n\treturn Object.fromEntries(names.map((name, i) => [name, 1 << i])) as Record<T[number], number>;\n}\n\nfunction normalizeChannelBitValues<T extends Record<string, number>>(bitValues: T): T {\n\treturn Object.fromEntries(\n\t\tObject.entries(bitValues).map(([name, bitValue]) => [name, bitValue / CHANNEL_BIT_SCALE]),\n\t) as T;\n}\n\nconst RED_REGION_BIT_VALUES = createChannelBitValues(RED_REGION_NAMES);\nconst GREEN_REGION_BIT_VALUES = createChannelBitValues(GREEN_REGION_NAMES);\nconst BLUE_REGION_BIT_VALUES = createChannelBitValues(BLUE_REGION_NAMES);\nconst RED_CHANNEL_VALUES = normalizeChannelBitValues(RED_REGION_BIT_VALUES);\nconst GREEN_CHANNEL_VALUES = normalizeChannelBitValues(GREEN_REGION_BIT_VALUES);\nconst BLUE_CHANNEL_VALUES = normalizeChannelBitValues(BLUE_REGION_BIT_VALUES);\n\nconst DEFAULT_FACE_OPTIONS: Required<Omit<FacePluginOptions, 'history'>> = {\n\tmodelPath:\n\t\t'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task',\n\tmaxFaces: 1,\n\tminFaceDetectionConfidence: 0.5,\n\tminFacePresenceConfidence: 0.5,\n\tminTrackingConfidence: 0.5,\n\toutputFaceBlendshapes: false,\n\toutputFacialTransformationMatrixes: false,\n};\n\nfunction fanTriangulate(indices: readonly number[]): number[] {\n\tconst tris: number[] = [];\n\tfor (let i = 1; i < indices.length - 1; ++i) {\n\t\ttris.push(indices[0], indices[i], indices[i + 1]);\n\t}\n\treturn tris;\n}\n\nfunction contourPath(connections: readonly { start: number; end: number }[]): number[] {\n\tconst indices = new Array<number>(connections.length + 1);\n\tindices[0] = connections[0].start;\n\tfor (let i = 0; i < connections.length; ++i) indices[i + 1] = connections[i].end;\n\treturn indices;\n}\n\nfunction stripTriangulate(a: readonly number[], b: readonly number[]): number[] {\n\tconst tris: number[] = [];\n\tconst n = Math.min(a.length, b.length);\n\tfor (let i = 0; i < n - 1; ++i) {\n\t\ttris.push(a[i], b[i], b[i + 1], a[i], b[i + 1], a[i + 1]);\n\t}\n\treturn tris;\n}\n\ntype FaceRegion = { indices: number[]; vertices: Float32Array };\nlet faceRegions: Record<string, FaceRegion> | null = null;\nfunction initFaceRegions(LandmarkerClass: typeof FaceLandmarker): void {\n\tif (!faceRegions) {\n\t\t// Eyes: 2 open chains / 8 connections each. Eyebrows: 2/4. Lips: 4/10.\n\t\tconst tesselationConnections = LandmarkerClass.FACE_LANDMARKS_TESSELATION;\n\t\tconst leftEyebrowConnections = LandmarkerClass.FACE_LANDMARKS_LEFT_EYEBROW;\n\t\tconst leftEyebrowUpper = contourPath(leftEyebrowConnections.slice(0, 4));\n\t\tconst leftEyebrowLower = contourPath(leftEyebrowConnections.slice(4, 8));\n\t\tconst rightEyebrowConnections = LandmarkerClass.FACE_LANDMARKS_RIGHT_EYEBROW;\n\t\tconst rightEyebrowUpper = contourPath(rightEyebrowConnections.slice(0, 4));\n\t\tconst rightEyebrowLower = contourPath(rightEyebrowConnections.slice(4, 8));\n\t\tconst leftEyeConnections = LandmarkerClass.FACE_LANDMARKS_LEFT_EYE;\n\t\tconst leftEyeUpper = contourPath(leftEyeConnections.slice(0, 8));\n\t\tconst leftEyeLower = contourPath(leftEyeConnections.slice(8, 16));\n\t\tconst rightEyeConnections = LandmarkerClass.FACE_LANDMARKS_RIGHT_EYE;\n\t\tconst rightEyeUpper = contourPath(rightEyeConnections.slice(0, 8));\n\t\tconst rightEyeLower = contourPath(rightEyeConnections.slice(8, 16));\n\t\tconst lipConnections = LandmarkerClass.FACE_LANDMARKS_LIPS;\n\t\tconst outerUpperLip = contourPath(lipConnections.slice(0, 10));\n\t\tconst outerLowerLip = contourPath(lipConnections.slice(10, 20));\n\t\tconst innerUpperLip = contourPath(lipConnections.slice(20, 30));\n\t\tconst innerLowerLip = contourPath(lipConnections.slice(30, 40));\n\t\tconst leftEyeIndices = [...leftEyeUpper, ...leftEyeLower.slice(1, -1)];\n\t\tconst rightEyeIndices = [...rightEyeUpper, ...rightEyeLower.slice(1, -1)];\n\t\tinnerMouthIndices = [...innerUpperLip, ...innerLowerLip.slice(1, -1)];\n\t\tconst tessellationHoleRemap = new Int16Array(LANDMARK_COUNT).fill(-1);\n\t\tfor (const index of leftEyeIndices) tessellationHoleRemap[index] = FACE_LANDMARK_L_EYE_CENTER;\n\t\tfor (const index of rightEyeIndices) tessellationHoleRemap[index] = FACE_LANDMARK_R_EYE_CENTER;\n\t\tfor (const index of innerMouthIndices) tessellationHoleRemap[index] = FACE_LANDMARK_MOUTH_CENTER;\n\t\tconst remapTessellationHole = (index: number) => {\n\t\t\tconst remapped = tessellationHoleRemap[index];\n\t\t\treturn remapped >= 0 ? remapped : index;\n\t\t};\n\t\tconst tesselation: number[] = [];\n\t\tfor (let i = 0; i < tesselationConnections.length - 2; i += 3) {\n\t\t\tconst a = remapTessellationHole(tesselationConnections[i].start);\n\t\t\tconst b = remapTessellationHole(tesselationConnections[i + 1].start);\n\t\t\tconst c = remapTessellationHole(tesselationConnections[i + 2].start);\n\t\t\tif (a !== b && a !== c && b !== c) tesselation.push(a, b, c);\n\t\t}\n\t\tconst leftEyebrowFill = stripTriangulate(leftEyebrowUpper, leftEyebrowLower);\n\t\tconst rightEyebrowFill = stripTriangulate(rightEyebrowUpper, rightEyebrowLower);\n\t\tconst leftEyeFill = stripTriangulate(leftEyeUpper, leftEyeLower);\n\t\tconst rightEyeFill = stripTriangulate(rightEyeUpper, rightEyeLower);\n\t\tconst mouthFill = [\n\t\t\t...stripTriangulate(outerUpperLip, innerUpperLip),\n\t\t\t...stripTriangulate(outerLowerLip, innerLowerLip),\n\t\t];\n\t\tconst innerMouthFill = stripTriangulate(innerUpperLip, innerLowerLip);\n\t\tconst ovalIndices = contourPath(LandmarkerClass.FACE_LANDMARKS_FACE_OVAL).slice(0, -1);\n\t\tfaceRegions = Object.fromEntries(\n\t\t\tObject.entries({\n\t\t\t\tLEFT_EYEBROW: leftEyebrowFill,\n\t\t\t\tRIGHT_EYEBROW: rightEyebrowFill,\n\t\t\t\tLEFT_EYE: leftEyeFill,\n\t\t\t\tRIGHT_EYE: rightEyeFill,\n\t\t\t\tMOUTH: mouthFill,\n\t\t\t\tINNER_MOUTH: innerMouthFill,\n\t\t\t\tTESSELATION: tesselation,\n\t\t\t\tOVAL: fanTriangulate(ovalIndices),\n\t\t\t}).map(([key, indices]) => [key, { indices, vertices: new Float32Array(indices.length * 2) }]),\n\t\t);\n\t}\n}\n\ninterface MaskRenderer {\n\tcanvas: OffscreenCanvas;\n\tgl: WebGL2RenderingContext;\n\tregionProgram: WebGLProgram;\n\tblitProgram: WebGLProgram;\n\tregionPositionBuffer: WebGLBuffer;\n\tquadBuffer: WebGLBuffer;\n\tregionPositionLocation: number;\n\tblitPositionLocation: number;\n\tcolorLocation: WebGLUniformLocation;\n\ttextureLocation: WebGLUniformLocation;\n\tscratchTexture: WebGLTexture;\n\tscratchFramebuffer: WebGLFramebuffer;\n}\n\ninterface Detector {\n\tlandmarker: FaceLandmarker;\n\tmediapipeCanvas: OffscreenCanvas;\n\tmask: MaskRenderer;\n\tsubscribers: Map<Function, boolean>;\n\tmaxFaces: number;\n\tstate: {\n\t\tnCalls: number;\n\t\trunningMode: 'IMAGE' | 'VIDEO';\n\t\tsource: MediaPipeSource | null;\n\t\tvideoTime: number;\n\t\tresultTimestamp: number;\n\t\tresult: FaceLandmarkerResult | null;\n\t\tpending: Promise<void>;\n\t\tnFaces: number;\n\t};\n\tlandmarks: {\n\t\tdata: Float32Array;\n\t\ttextureHeight: number;\n\t};\n}\nconst sharedDetectors = new Map<string, Detector>();\nconst sharedDetectorPromises = new Map<string, Promise<Detector | undefined>>();\n\nfunction createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n\tprogramName: string,\n): WebGLProgram {\n\tlet vertexShader: WebGLShader | null = null;\n\tlet fragmentShader: WebGLShader | null = null;\n\tlet program: WebGLProgram | null = null;\n\n\ttry {\n\t\tvertexShader = gl.createShader(gl.VERTEX_SHADER);\n\t\tfragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n\t\tprogram = gl.createProgram();\n\t\tif (!vertexShader || !fragmentShader || !program) throw new Error();\n\n\t\tgl.shaderSource(vertexShader, vertexSource);\n\t\tgl.compileShader(vertexShader);\n\t\tif (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) throw new Error();\n\n\t\tgl.shaderSource(fragmentShader, fragmentSource);\n\t\tgl.compileShader(fragmentShader);\n\t\tif (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) throw new Error();\n\n\t\tgl.attachShader(program, vertexShader);\n\t\tgl.attachShader(program, fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error();\n\n\t\treturn program;\n\t} catch {\n\t\tif (program) gl.deleteProgram(program);\n\t\tthrow spError(\n\t\t\t61,\n\t\t\t__SHADERPAD_DEV__ && {\n\t\t\t\tprogramName,\n\t\t\t\tvertexShaderInfoLog: vertexShader ? gl.getShaderInfoLog(vertexShader) : undefined,\n\t\t\t\tfragmentShaderInfoLog: fragmentShader ? gl.getShaderInfoLog(fragmentShader) : undefined,\n\t\t\t\tprogramInfoLog: program ? gl.getProgramInfoLog(program) : undefined,\n\t\t\t},\n\t\t);\n\t} finally {\n\t\tif (vertexShader) gl.deleteShader(vertexShader);\n\t\tif (fragmentShader) gl.deleteShader(fragmentShader);\n\t}\n}\n\nfunction initMaskRenderer(canvas: OffscreenCanvas): MaskRenderer {\n\tconst gl = canvas.getContext('webgl2', {\n\t\tantialias: false,\n\t\tpreserveDrawingBuffer: true,\n\t});\n\tif (!gl) {\n\t\tthrow spError(60, __SHADERPAD_DEV__ && { canvasWidth: canvas.width, canvasHeight: canvas.height });\n\t}\n\tconst regionProgram = createProgram(gl, MASK_VERTEX_SHADER, MASK_FRAGMENT_SHADER, 'face-mask-region');\n\tconst blitProgram = createProgram(gl, MASK_VERTEX_SHADER, BLIT_FRAGMENT_SHADER, 'face-mask-blit');\n\n\tlet framebufferStatus: number | undefined;\n\ttry {\n\t\tconst regionPositionBuffer = gl.createBuffer();\n\t\tconst regionPositionLocation = gl.getAttribLocation(regionProgram, 'a_pos');\n\t\tconst quadBuffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, FULLSCREEN_TRIANGLES, gl.STATIC_DRAW);\n\t\tconst blitPositionLocation = gl.getAttribLocation(blitProgram, 'a_pos');\n\t\tconst colorLocation = gl.getUniformLocation(regionProgram, 'u_color');\n\t\tconst textureLocation = gl.getUniformLocation(blitProgram, 'u_texture');\n\t\tconst scratchTexture = gl.createTexture();\n\t\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n\t\tconst scratchFramebuffer = gl.createFramebuffer();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, scratchFramebuffer);\n\t\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, scratchTexture, 0);\n\t\tframebufferStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n\t\tif (\n\t\t\t!regionPositionBuffer ||\n\t\t\tregionPositionLocation < 0 ||\n\t\t\t!quadBuffer ||\n\t\t\tblitPositionLocation < 0 ||\n\t\t\t!colorLocation ||\n\t\t\t!textureLocation ||\n\t\t\t!scratchTexture ||\n\t\t\t!scratchFramebuffer ||\n\t\t\tframebufferStatus !== gl.FRAMEBUFFER_COMPLETE\n\t\t) {\n\t\t\tthrow new Error();\n\t\t}\n\n\t\tgl.useProgram(blitProgram);\n\t\tgl.uniform1i(textureLocation, 0);\n\t\tgl.colorMask(true, true, true, false);\n\n\t\treturn {\n\t\t\tcanvas,\n\t\t\tgl,\n\t\t\tregionProgram,\n\t\t\tblitProgram,\n\t\t\tregionPositionBuffer,\n\t\t\tquadBuffer,\n\t\t\tregionPositionLocation,\n\t\t\tblitPositionLocation,\n\t\t\tcolorLocation,\n\t\t\ttextureLocation,\n\t\t\tscratchTexture,\n\t\t\tscratchFramebuffer,\n\t\t};\n\t} catch {\n\t\tthrow spError(62, __SHADERPAD_DEV__ && { framebufferStatus });\n\t}\n}\n\nfunction resizeMaskRenderer(mask: MaskRenderer, width: number, height: number) {\n\tconst { gl, canvas, scratchTexture } = mask;\n\tif (canvas.width === width && canvas.height === height) return;\n\tcanvas.width = width;\n\tcanvas.height = height;\n\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n}\n\nfunction drawRegionToScratch(\n\tmask: MaskRenderer,\n\tlandmarksData: Float32Array,\n\tfaceRegion: FaceRegion,\n\tfaceIdx: number,\n\tr: number,\n\tg: number,\n\tb: number,\n) {\n\tconst { gl, regionProgram, regionPositionBuffer, regionPositionLocation, colorLocation, scratchFramebuffer } = mask;\n\tconst baseIdx = N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT;\n\tconst { indices, vertices } = faceRegion;\n\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, scratchFramebuffer);\n\tgl.viewport(0, 0, mask.canvas.width, mask.canvas.height);\n\tgl.clearColor(0, 0, 0, 0);\n\tgl.clear(gl.COLOR_BUFFER_BIT);\n\tgl.useProgram(regionProgram);\n\tgl.bindBuffer(gl.ARRAY_BUFFER, regionPositionBuffer);\n\tgl.enableVertexAttribArray(regionPositionLocation);\n\tgl.vertexAttribPointer(regionPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\tgl.enable(gl.BLEND);\n\tgl.blendEquation(gl.MAX);\n\tgl.blendFunc(gl.ONE, gl.ONE);\n\n\tfor (let i = 0; i < indices.length; ++i) {\n\t\tconst landmarkIdx = (baseIdx + indices[i]) * 4;\n\t\tvertices[i * 2] = landmarksData[landmarkIdx];\n\t\tvertices[i * 2 + 1] = landmarksData[landmarkIdx + 1];\n\t}\n\tgl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\tgl.uniform4f(colorLocation, r, g, b, 1.0);\n\tgl.drawArrays(gl.TRIANGLES, 0, indices.length);\n}\n\nfunction accumulateScratch(mask: MaskRenderer) {\n\tconst { gl, blitProgram, quadBuffer, blitPositionLocation, scratchTexture } = mask;\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\tgl.viewport(0, 0, mask.canvas.width, mask.canvas.height);\n\tgl.useProgram(blitProgram);\n\tgl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);\n\tgl.enableVertexAttribArray(blitPositionLocation);\n\tgl.vertexAttribPointer(blitPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\tgl.activeTexture(gl.TEXTURE0);\n\tgl.bindTexture(gl.TEXTURE_2D, scratchTexture);\n\tgl.enable(gl.BLEND);\n\tgl.blendEquation(gl.FUNC_ADD);\n\tgl.blendFunc(gl.ONE, gl.ONE);\n\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n}\n\nfunction updateLandmarksData(detector: Detector, faces: NormalizedLandmark[][]) {\n\tconst data = detector.landmarks.data;\n\tconst nFaces = faces.length;\n\tdata[0] = nFaces;\n\n\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\tconst landmarks = faces[faceIdx];\n\t\tfor (let landmarkIdx = 0; landmarkIdx < STANDARD_LANDMARK_COUNT; ++landmarkIdx) {\n\t\t\tconst landmark = landmarks[landmarkIdx];\n\t\t\tconst dataIdx = (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + landmarkIdx) * 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 faceCenter = calculateBoundingBoxCenter(\n\t\t\tdata,\n\t\t\tfaceIdx,\n\t\t\tALL_STANDARD_INDICES,\n\t\t\tLANDMARK_COUNT,\n\t\t\tN_LANDMARK_METADATA_SLOTS,\n\t\t);\n\t\tdata.set(faceCenter, (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + FACE_LANDMARK_FACE_CENTER) * 4);\n\t\tconst mouthCenter = calculateBoundingBoxCenter(data, faceIdx, innerMouthIndices!, LANDMARK_COUNT, 1);\n\t\tdata.set(mouthCenter, (N_LANDMARK_METADATA_SLOTS + faceIdx * LANDMARK_COUNT + FACE_LANDMARK_MOUTH_CENTER) * 4);\n\t}\n\n\tdetector.state.nFaces = nFaces;\n}\n\nfunction updateMask(detector: Detector, width: number, height: number) {\n\tconst {\n\t\tmask,\n\t\tmaxFaces,\n\t\tlandmarks,\n\t\tstate: { nFaces },\n\t} = detector;\n\tconst { gl, canvas: maskCanvas } = mask;\n\tconst { data: landmarksData } = landmarks;\n\n\tresizeMaskRenderer(mask, width, height);\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\tgl.viewport(0, 0, maskCanvas.width, maskCanvas.height);\n\tgl.clearColor(0, 0, 0, 0);\n\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\tif (!faceRegions) return;\n\n\tconst useTesselationBitmask = maxFaces <= GB_BITMASK_MAX_FACES;\n\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\tconst g =\n\t\t\tuseTesselationBitmask && faceIdx < GREEN_REGION_NAMES.length\n\t\t\t\t? GREEN_CHANNEL_VALUES[GREEN_REGION_NAMES[faceIdx]]\n\t\t\t\t: 0;\n\t\tconst b = useTesselationBitmask\n\t\t\t? faceIdx < GREEN_REGION_NAMES.length\n\t\t\t\t? 0\n\t\t\t\t: BLUE_CHANNEL_VALUES[BLUE_REGION_NAMES[faceIdx - GREEN_REGION_NAMES.length]]\n\t\t\t: (faceIdx + 1) / CHANNEL_BIT_SCALE;\n\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.TESSELATION, faceIdx, 0, g, b);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.OVAL, faceIdx, RED_CHANNEL_VALUES.OVAL, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.LEFT_EYEBROW,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.LEFT_EYEBROW,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.RIGHT_EYEBROW,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.RIGHT_EYEBROW,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.LEFT_EYE, faceIdx, RED_CHANNEL_VALUES.LEFT_EYE, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.RIGHT_EYE, faceIdx, RED_CHANNEL_VALUES.RIGHT_EYE, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(mask, landmarksData, faceRegions.MOUTH, faceIdx, RED_CHANNEL_VALUES.MOUTH, 0, 0);\n\t\taccumulateScratch(mask);\n\t\tdrawRegionToScratch(\n\t\t\tmask,\n\t\t\tlandmarksData,\n\t\t\tfaceRegions.INNER_MOUTH,\n\t\t\tfaceIdx,\n\t\t\tRED_CHANNEL_VALUES.INNER_MOUTH,\n\t\t\t0,\n\t\t\t0,\n\t\t);\n\t\taccumulateScratch(mask);\n\t}\n}\n\nfunction face(config: FacePluginConfig) {\n\tconst { textureName, options: { history, ...mediapipeOptions } = {} } = config;\n\tconst options = { ...DEFAULT_FACE_OPTIONS, ...mediapipeOptions };\n\tconst optionsKey = hashOptions({ ...options, textureName });\n\n\tconst nLandmarksMax = options.maxFaces * 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, emit, updateTexture } = 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 mediapipeCanvas = existingDetector?.mediapipeCanvas ?? new OffscreenCanvas(1, 1);\n\t\tconst maskCanvas = existingDetector?.mask.canvas ?? new OffscreenCanvas(1, 1);\n\t\tlet detector: Detector | undefined;\n\t\tlet destroyed = false;\n\t\tlet historySlot = -1;\n\t\tlet pendingBackfillSlots: number[] = [];\n\n\t\tfunction writeTextures(historySlots: number | number[]) {\n\t\t\tif (!detector) return;\n\t\t\tconst nFaces = detector.state.nFaces;\n\t\t\tconst nSlots = nFaces * LANDMARK_COUNT + N_LANDMARK_METADATA_SLOTS;\n\t\t\tconst rowsToUpdate = Math.ceil(nSlots / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tconst targetHistorySlots = history ? historySlots : undefined;\n\t\t\tupdateTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{\n\t\t\t\t\tdata: detector.landmarks.data,\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\ttargetHistorySlots,\n\t\t\t);\n\t\t\tupdateTexture('u_faceMask', detector.mask.canvas, targetHistorySlots);\n\t\t\tshaderPad.updateUniforms({ u_nFaces: nFaces }, { allowMissing: true });\n\t\t}\n\n\t\tfunction onResult() {\n\t\t\tif (history) {\n\t\t\t\twriteTextures(pendingBackfillSlots.length > 0 ? pendingBackfillSlots : historySlot);\n\t\t\t\tpendingBackfillSlots = [];\n\t\t\t} else {\n\t\t\t\twriteTextures(historySlot);\n\t\t\t}\n\t\t\temit('face:result', detector!.state.result);\n\t\t}\n\n\t\tasync function initializeDetector() {\n\t\t\tdetector = await getOrCreateSharedResource(\n\t\t\t\toptionsKey,\n\t\t\t\tsharedDetectors,\n\t\t\t\tsharedDetectorPromises,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst [mediaPipe, { FaceLandmarker }] = await Promise.all([\n\t\t\t\t\t\tgetSharedFileset(),\n\t\t\t\t\t\timport('@mediapipe/tasks-vision'),\n\t\t\t\t\t]);\n\t\t\t\t\tif (destroyed) return;\n\n\t\t\t\t\tconst faceLandmarker = await FaceLandmarker.createFromOptions(mediaPipe, {\n\t\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\t\tmodelAssetPath: options.modelPath,\n\t\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcanvas: mediapipeCanvas,\n\t\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\t\tnumFaces: options.maxFaces,\n\t\t\t\t\t\tminFaceDetectionConfidence: options.minFaceDetectionConfidence,\n\t\t\t\t\t\tminFacePresenceConfidence: options.minFacePresenceConfidence,\n\t\t\t\t\t\tminTrackingConfidence: options.minTrackingConfidence,\n\t\t\t\t\t\toutputFaceBlendshapes: options.outputFaceBlendshapes,\n\t\t\t\t\t\toutputFacialTransformationMatrixes: options.outputFacialTransformationMatrixes,\n\t\t\t\t\t});\n\t\t\t\t\tif (destroyed) {\n\t\t\t\t\t\tfaceLandmarker.close();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst detector: Detector = {\n\t\t\t\t\t\tlandmarker: faceLandmarker,\n\t\t\t\t\t\tmediapipeCanvas,\n\t\t\t\t\t\tmask: initMaskRenderer(maskCanvas),\n\t\t\t\t\t\tsubscribers: new Map(),\n\t\t\t\t\t\tmaxFaces: options.maxFaces,\n\t\t\t\t\t\tstate: {\n\t\t\t\t\t\t\tnCalls: 0,\n\t\t\t\t\t\t\trunningMode: 'VIDEO',\n\t\t\t\t\t\t\tsource: null,\n\t\t\t\t\t\t\tvideoTime: -1,\n\t\t\t\t\t\t\tresultTimestamp: 0,\n\t\t\t\t\t\t\tresult: null,\n\t\t\t\t\t\t\tpending: Promise.resolve(),\n\t\t\t\t\t\t\tnFaces: 0,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlandmarks: {\n\t\t\t\t\t\t\tdata: landmarksData,\n\t\t\t\t\t\t\ttextureHeight,\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\n\t\t\t\t\tinitFaceRegions(FaceLandmarker);\n\t\t\t\t\treturn detector;\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!detector || destroyed) return;\n\t\t\tdetector.subscribers.set(onResult, false);\n\t\t}\n\t\tconst initPromise = initializeDetector();\n\n\t\tasync function detectFaces(source: MediaPipeSource) {\n\t\t\tconst now = performance.now();\n\t\t\tawait initPromise;\n\t\t\tif (!detector) return;\n\t\t\tconst callOrder = ++detector.state.nCalls;\n\n\t\t\tdetector.state.pending = detector.state.pending.then(async () => {\n\t\t\t\tif (!detector || callOrder !== detector.state.nCalls) 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({\n\t\t\t\t\t\trunningMode: requiredMode,\n\t\t\t\t\t});\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 = source instanceof HTMLVideoElement ? source.currentTime : -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: FaceLandmarkerResult | undefined;\n\t\t\t\t\tlet width: number, height: number;\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\twidth = source.videoWidth;\n\t\t\t\t\t\theight = source.videoHeight;\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\twidth = source.width;\n\t\t\t\t\t\theight = source.height;\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.faceLandmarks);\n\t\t\t\t\t\tupdateMask(detector, width, height);\n\t\t\t\t\t\tfor (const [cb, needsResult] of detector.subscribers.entries()) {\n\t\t\t\t\t\t\tif (needsResult) {\n\t\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t\t\tdetector.subscribers.set(cb, false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (detector.state.result) {\n\t\t\t\t\tfor (const [cb, needsResult] of detector.subscribers.entries()) {\n\t\t\t\t\t\tif (needsResult) {\n\t\t\t\t\t\t\tcb();\n\t\t\t\t\t\t\tdetector.subscribers.set(cb, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\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('_init', () => {\n\t\t\tshaderPad.initializeUniform('u_maxFaces', 'int', options.maxFaces, { allowMissing: true });\n\t\t\tshaderPad.initializeUniform('u_nFaces', 'int', 0, { allowMissing: true });\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{\n\t\t\t\t\tdata: landmarksData,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: textureHeight,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tinternalFormat: 'RGBA32F',\n\t\t\t\t\ttype: 'FLOAT',\n\t\t\t\t\tminFilter: 'NEAREST',\n\t\t\t\t\tmagFilter: 'NEAREST',\n\t\t\t\t\thistory,\n\t\t\t\t},\n\t\t\t);\n\t\t\tshaderPad.initializeTexture('u_faceMask', maskCanvas, {\n\t\t\t\tminFilter: 'NEAREST',\n\t\t\t\tmagFilter: 'NEAREST',\n\t\t\t\thistory,\n\t\t\t});\n\t\t\tinitPromise.then(() => {\n\t\t\t\tif (destroyed || !detector) return;\n\t\t\t\temit('face:ready');\n\t\t\t});\n\t\t});\n\n\t\tfunction requestFaces(source: MediaPipeSource) {\n\t\t\tif (!detector) return;\n\t\t\tif (history) {\n\t\t\t\thistorySlot = (historySlot + 1) % (history + 1);\n\t\t\t\twriteTextures(historySlot);\n\t\t\t\tpendingBackfillSlots.push(historySlot);\n\t\t\t}\n\t\t\tdetector.subscribers.set(onResult, true);\n\t\t\tdetectFaces(source);\n\t\t}\n\n\t\tshaderPad.on('initializeTexture', (name: string, source: TextureSource) => {\n\t\t\tif (name === textureName && isMediaPipeSource(source)) {\n\t\t\t\trequestFaces(source);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.on('updateTextures', (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (isMediaPipeSource(source)) {\n\t\t\t\trequestFaces(source);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.on('destroy', () => {\n\t\t\tdestroyed = true;\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.gl.deleteProgram(detector.mask.regionProgram);\n\t\t\t\t\tdetector.mask.gl.deleteProgram(detector.mask.blitProgram);\n\t\t\t\t\tdetector.mask.gl.deleteBuffer(detector.mask.regionPositionBuffer);\n\t\t\t\t\tdetector.mask.gl.deleteBuffer(detector.mask.quadBuffer);\n\t\t\t\t\tdetector.mask.gl.deleteTexture(detector.mask.scratchTexture);\n\t\t\t\t\tdetector.mask.gl.deleteFramebuffer(detector.mask.scratchFramebuffer);\n\t\t\t\t\tsharedDetectors.delete(optionsKey);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdetector = undefined;\n\t\t});\n\n\t\tconst { fn, historyParams } = generateGLSLFn(history);\n\t\tconst sampleMask = history ? `_sampleFaceMask(pos, framesAgo)` : `texture(u_faceMask, pos)`;\n\t\tconst decodeFaceBitIndex = Array.from(\n\t\t\t{ length: GB_BITMASK_MAX_FACES - 1 },\n\t\t\t(_, i) => `step(${2 ** (i + 1)}.0, faceBitF)`,\n\t\t).join(' + ');\n\t\tconst decodeFaceIndex =\n\t\t\toptions.maxFaces <= GB_BITMASK_MAX_FACES\n\t\t\t\t? `uint faceBits = (uint(mask.b * ${CHANNEL_BIT_SCALE}.0 + 0.5) << 8) | uint(mask.g * ${CHANNEL_BIT_SCALE}.0 + 0.5);\n\tuint faceBit = faceBits & (~faceBits + 1u);\n\tfloat faceBitF = float(faceBit);\n\tfloat hasFace = sign(faceBitF);\n\tfloat faceIndex = ${decodeFaceBitIndex} - (1.0 - hasFace);`\n\t\t\t\t: `float faceIndex = float(int(uint(mask.b * ${CHANNEL_BIT_SCALE}.0 + 0.5)) - 1);`;\n\n\t\tconst checkAt = (fnName: string, ...regionNames: (keyof typeof RED_REGION_BIT_VALUES)[]) =>\n\t\t\tfn(\n\t\t\t\t'vec2',\n\t\t\t\t`${fnName}At`,\n\t\t\t\t'vec2 pos',\n\t\t\t\t`vec4 mask = ${sampleMask};\n\t${decodeFaceIndex}\n\tuint bits = uint(mask.r * ${CHANNEL_BIT_SCALE}.0 + 0.5);\n\tfloat hit = sign(float(bits & ${regionNames.reduce(\n\t\t(mask, regionName) => mask | RED_REGION_BIT_VALUES[regionName],\n\t\t0,\n\t)}u));\n\treturn vec2(hit, mix(-1.0, faceIndex, hit));`,\n\t\t\t);\n\n\t\tconst combineLeftRight = (fnName: string, leftFn: string, rightFn: string) =>\n\t\t\tfn(\n\t\t\t\t'vec2',\n\t\t\t\t`${fnName}At`,\n\t\t\t\t'vec2 pos',\n\t\t\t\t`vec2 left = ${leftFn}(pos${historyParams});\n\tvec2 right = ${rightFn}(pos${historyParams});\n\treturn mix(right, left, left.x);`,\n\t\t\t);\n\n\t\tconst checkIn = (fnNames: string[]) =>\n\t\t\tfnNames\n\t\t\t\t.map(fnName =>\n\t\t\t\t\tfn(\n\t\t\t\t\t\t'float',\n\t\t\t\t\t\t`in${fnName[0].toUpperCase() + fnName.slice(1)}`,\n\t\t\t\t\t\t'vec2 pos',\n\t\t\t\t\t\t`vec2 a = ${fnName}At(pos${historyParams}); return step(0.0, a.y) * a.x;`,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t\t.join('\\n');\n\n\t\tinjectGLSL(`\nuniform int u_maxFaces;\nuniform int u_nFaces;\nuniform highp sampler2D${history ? 'Array' : ''} u_faceLandmarksTex;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_faceLandmarksTexFrameOffset;`\n\t\t\t\t: ''\n\t\t}\nuniform mediump sampler2D${history ? 'Array' : ''} u_faceMask;${\n\t\t\thistory\n\t\t\t\t? `\nuniform int u_faceMaskFrameOffset;`\n\t\t\t\t: ''\n\t\t}\n\n#define FACE_LANDMARK_L_EYE_CENTER ${FACE_LANDMARK_L_EYE_CENTER}\n#define FACE_LANDMARK_R_EYE_CENTER ${FACE_LANDMARK_R_EYE_CENTER}\n#define FACE_LANDMARK_NOSE_TIP ${FACE_LANDMARK_NOSE_TIP}\n#define FACE_LANDMARK_FACE_CENTER ${FACE_LANDMARK_FACE_CENTER}\n#define FACE_LANDMARK_MOUTH_CENTER ${FACE_LANDMARK_MOUTH_CENTER}\n\n${fn(\n\t'int',\n\t'nFacesAt',\n\t'',\n\thistory\n\t\t? `\n\tint layer = (u_faceLandmarksTexFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn int(texelFetch(u_faceLandmarksTex, ivec3(0, 0, layer), 0).r + 0.5);`\n\t\t: `\n\treturn int(texelFetch(u_faceLandmarksTex, ivec2(0, 0), 0).r + 0.5);`,\n)}\n${fn(\n\t'vec4',\n\t'faceLandmark',\n\t'int faceIndex, int landmarkIndex',\n\t`int i = ${N_LANDMARK_METADATA_SLOTS} + faceIndex * ${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_faceLandmarksTexFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn texelFetch(u_faceLandmarksTex, ivec3(x, y, layer), 0);`\n\t\t\t: `\n\treturn texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);`\n\t}`,\n)}\n${\n\thistory\n\t\t? `\nvec4 _sampleFaceMask(vec2 pos, int framesAgo) {\n\tint layer = (u_faceMaskFrameOffset - framesAgo + ${history + 1}) % ${history + 1};\n\treturn texture(u_faceMask, vec3(pos, float(layer)));\n}\n`\n\t\t: ''\n}\n${checkAt('leftEyebrow', 'LEFT_EYEBROW')}\n${checkAt('rightEyebrow', 'RIGHT_EYEBROW')}\n${checkAt('leftEye', 'LEFT_EYE')}\n${checkAt('rightEye', 'RIGHT_EYE')}\n${checkAt('lips', 'MOUTH')}\n${checkAt('mouth', 'MOUTH', 'INNER_MOUTH')}\n${checkAt('innerMouth', 'INNER_MOUTH')}\n${checkAt('faceOval', 'OVAL')}\n${fn(\n\t'vec2',\n\t'faceAt',\n\t'vec2 pos',\n\t`vec4 mask = ${sampleMask};\n\t${decodeFaceIndex}\n\treturn vec2(step(0.0, faceIndex), faceIndex);`,\n)}\n${combineLeftRight('eye', 'leftEyeAt', 'rightEyeAt')}\n${combineLeftRight('eyebrow', 'leftEyebrowAt', 'rightEyebrowAt')}\n${checkIn(['eyebrow', 'eye', 'mouth', 'innerMouth', 'lips', 'face'])}`);\n\t};\n}\n\nexport default face;\n","// Generated by scripts/generate-error-code-artifacts.mjs. Do not edit manually.\nexport type ErrorCode = number;\n\nexport const ERROR_DOCS_BASE_URL = 'https://mry.ac/s/';\n\nexport function errorUrl(code: ErrorCode) {\n\treturn `${ERROR_DOCS_BASE_URL}${code}`;\n}\n","// Generated by scripts/generate-error-code-artifacts.mjs. Do not edit manually.\nimport type { ErrorCode } from './error-codes.gen.js';\n\ntype DevErrorDetails = {\n\ttitle: string;\n\tsummary: string;\n};\n\nexport const DEV_ERRORS: Record<ErrorCode, DevErrorDetails> | undefined = __SHADERPAD_DEV__\n\t? {\n\t\t\t'0': {\n\t\t\t\ttitle: 'WebGL2 Context Unavailable',\n\t\t\t\tsummary: 'ShaderPad could not create a WebGL2 rendering context.',\n\t\t\t},\n\t\t\t'1': {\n\t\t\t\ttitle: 'Program Allocation Failed',\n\t\t\t\tsummary: 'ShaderPad could not allocate a WebGL program object.',\n\t\t\t},\n\t\t\t'2': {\n\t\t\t\ttitle: 'Program Link Failed',\n\t\t\t\tsummary: 'ShaderPad compiled the shaders but failed to link them into a WebGL program.',\n\t\t\t},\n\t\t\t'3': {\n\t\t\t\ttitle: 'Unknown GL Constant',\n\t\t\t\tsummary: 'ShaderPad received a WebGL constant name it does not recognize.',\n\t\t\t},\n\t\t\t'4': {\n\t\t\t\ttitle: 'Shader Compilation Failed',\n\t\t\t\tsummary: 'A vertex or fragment shader failed to compile.',\n\t\t\t},\n\t\t\t'5': {\n\t\t\t\ttitle: 'Texture Units Exhausted',\n\t\t\t\tsummary: 'ShaderPad tried to reserve more texture units than this device exposes.',\n\t\t\t},\n\t\t\t'6': {\n\t\t\t\ttitle: 'Float Color Buffer Extension Missing',\n\t\t\t\tsummary: 'ShaderPad requested a float render texture, but EXT_color_buffer_float is unavailable.',\n\t\t\t},\n\t\t\t'7': {\n\t\t\t\ttitle: 'Uniform Already Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to register a uniform name that was already registered.',\n\t\t\t},\n\t\t\t'8': {\n\t\t\t\ttitle: 'Invalid Uniform Type',\n\t\t\t\tsummary: 'ShaderPad received an unsupported uniform type string.',\n\t\t\t},\n\t\t\t'9': {\n\t\t\t\ttitle: 'Uniform Array Length Mismatch',\n\t\t\t\tsummary: 'ShaderPad was asked to initialize a uniform array with the wrong number of elements.',\n\t\t\t},\n\t\t\t'10': {\n\t\t\t\ttitle: 'Uniform Array Update Expected An Array',\n\t\t\t\tsummary: 'ShaderPad attempted to update a uniform array, but the provided value was not an array.',\n\t\t\t},\n\t\t\t'11': {\n\t\t\t\ttitle: 'Uniform Array Update Too Large',\n\t\t\t\tsummary: 'ShaderPad received more uniform array elements than the initialized array can hold.',\n\t\t\t},\n\t\t\t'12': {\n\t\t\t\ttitle: 'Uniform Array Element Size Mismatch',\n\t\t\t\tsummary: 'At least one uniform array element has the wrong scalar or vector length.',\n\t\t\t},\n\t\t\t'13': {\n\t\t\t\ttitle: 'Uniform Array Start Index Invalid',\n\t\t\t\tsummary: 'ShaderPad could not find the requested starting index for a uniform array.',\n\t\t\t},\n\t\t\t'14': {\n\t\t\t\ttitle: 'Uniform Value Length Invalid',\n\t\t\t\tsummary: 'ShaderPad received a scalar or vector uniform update with the wrong component count.',\n\t\t\t},\n\t\t\t'15': {\n\t\t\t\ttitle: 'Texture Allocation Failed',\n\t\t\t\tsummary: 'ShaderPad could not create a WebGL texture object.',\n\t\t\t},\n\t\t\t'16': {\n\t\t\t\ttitle: 'Texture Already Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to initialize a texture name that is already registered.',\n\t\t\t},\n\t\t\t'17': {\n\t\t\t\ttitle: 'Texture Source Dimensions Invalid',\n\t\t\t\tsummary: 'ShaderPad could not determine valid width and height values for the texture source.',\n\t\t\t},\n\t\t\t'18': {\n\t\t\t\ttitle: 'Texture Not Initialized',\n\t\t\t\tsummary: 'ShaderPad was asked to update a texture name that has not been initialized.',\n\t\t\t},\n\t\t\t'19': {\n\t\t\t\ttitle: 'Uniform Missing During Initialization',\n\t\t\t\tsummary:\n\t\t\t\t\t'ShaderPad could not initialize a uniform because the shader program does not contain that symbol.',\n\t\t\t},\n\t\t\t'20': {\n\t\t\t\ttitle: 'Uniform Missing During Update',\n\t\t\t\tsummary:\n\t\t\t\t\t'ShaderPad could not update a uniform because the shader program does not contain that symbol.',\n\t\t\t},\n\t\t\t'60': {\n\t\t\t\ttitle: 'Face Mask Renderer Context Unavailable',\n\t\t\t\tsummary: 'The face plugin could not create the offscreen WebGL2 context used for face-mask rendering.',\n\t\t\t},\n\t\t\t'61': {\n\t\t\t\ttitle: 'Face Mask Shader Setup Failed',\n\t\t\t\tsummary: 'The face plugin could not build the shaders it uses for face-mask rendering.',\n\t\t\t},\n\t\t\t'62': {\n\t\t\t\ttitle: 'Face Mask Renderer Initialization Failed',\n\t\t\t\tsummary: 'The face plugin could not finish setting up its internal face-mask renderer.',\n\t\t\t},\n\t\t}\n\t: undefined;\n","import { errorUrl, type ErrorCode } from './error-codes.gen.js';\nimport { DEV_ERRORS } from './error-codes.dev.gen.js';\n\ntype DevContext = Record<string, unknown> | false | undefined;\ntype ShaderPadError = Error & { code: ErrorCode };\n\nfunction withCode(message: string, code: ErrorCode): ShaderPadError {\n\tconst error = new Error(message) as ShaderPadError;\n\terror.code = code;\n\treturn error;\n}\n\nfunction renderContext(context: Record<string, unknown>) {\n\tconst lines = ['Context:'];\n\n\tfor (const [key, value] of Object.entries(context)) {\n\t\tif (value === undefined) continue;\n\n\t\tconst rendered =\n\t\t\ttypeof value === 'string'\n\t\t\t\t? value\n\t\t\t\t: (JSON.stringify(value, null, 2) ??\n\t\t\t\t\t(typeof value === 'bigint' ||\n\t\t\t\t\ttypeof value === 'number' ||\n\t\t\t\t\ttypeof value === 'boolean' ||\n\t\t\t\t\tvalue == null\n\t\t\t\t\t\t? String(value)\n\t\t\t\t\t\t: ''));\n\n\t\tif (!rendered) continue;\n\t\tlines.push(rendered.includes('\\n') ? `${key}:\\n${rendered}` : `${key}: ${rendered}`);\n\t}\n\n\treturn lines.length > 1 ? lines.join('\\n') : '';\n}\n\nfunction renderDevMessage(code: ErrorCode, context?: DevContext) {\n\tconst error = DEV_ERRORS?.[code];\n\tconst parts = error\n\t\t? [`[ShaderPad ${code}] ${error.title}`, error.summary, `Docs: ${errorUrl(code)}`]\n\t\t: [`[ShaderPad ${code}] ${errorUrl(code)}`];\n\n\tif (context) {\n\t\tconst renderedContext = renderContext(context);\n\t\tif (renderedContext) parts.push(renderedContext);\n\t}\n\n\treturn parts.join('\\n\\n');\n}\n\nexport function spError(code: ErrorCode, context?: DevContext) {\n\treturn withCode(__SHADERPAD_DEV__ ? renderDevMessage(code, context) : `ShaderPad error: ${errorUrl(code)}`, code);\n}\n\nexport function safeMod(i: number, m: number): number {\n\treturn ((i % m) + m) % m;\n}\n","import { TextureSource } from '..';\n\nexport const dummyTexture = { data: new Uint8Array(4), width: 1, height: 1 };\n\nexport type MediaPipeSource = HTMLVideoElement | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas;\n\nexport function isMediaPipeSource(source: TextureSource): source is MediaPipeSource {\n\treturn (\n\t\tsource instanceof HTMLVideoElement ||\n\t\tsource instanceof HTMLImageElement ||\n\t\tsource instanceof HTMLCanvasElement ||\n\t\tsource instanceof OffscreenCanvas\n\t);\n}\n\nexport function hashOptions(options: object): string {\n\treturn JSON.stringify(options, Object.keys(options).sort());\n}\n\nexport function getOrCreateSharedResource<T>(\n\tkey: string,\n\tsharedResources: Map<string, T>,\n\tsharedResourcePromises: Map<string, Promise<T | undefined>>,\n\tcreate: () => Promise<T | undefined>,\n): Promise<T | undefined> {\n\tconst existing = sharedResources.get(key);\n\tif (existing) return Promise.resolve(existing);\n\n\tconst pending = sharedResourcePromises.get(key);\n\tif (pending) return pending;\n\n\tlet promise: Promise<T | undefined>;\n\tpromise = create()\n\t\t.then(resource => {\n\t\t\tif (resource) {\n\t\t\t\tsharedResources.set(key, resource);\n\t\t\t}\n\t\t\treturn resource;\n\t\t})\n\t\t.finally(() => {\n\t\t\tif (sharedResourcePromises.get(key) === promise) {\n\t\t\t\tsharedResourcePromises.delete(key);\n\t\t\t}\n\t\t});\n\tsharedResourcePromises.set(key, promise);\n\treturn promise;\n}\n\nexport function calculateBoundingBoxCenter(\n\tdata: Float32Array,\n\tentityIdx: number,\n\tlandmarkIndices: readonly number[] | number[],\n\tlandmarkCount: number,\n\toffset: number = 0,\n): [number, number, number, number] {\n\tlet minX = Infinity,\n\t\tmaxX = -Infinity,\n\t\tminY = Infinity,\n\t\tmaxY = -Infinity,\n\t\tavgZ = 0,\n\t\tavgVisibility = 0;\n\n\tfor (const idx of landmarkIndices) {\n\t\tconst dataIdx = (offset + entityIdx * landmarkCount + idx) * 4;\n\t\tconst x = data[dataIdx];\n\t\tconst y = data[dataIdx + 1];\n\t\tminX = Math.min(minX, x);\n\t\tmaxX = Math.max(maxX, x);\n\t\tminY = Math.min(minY, y);\n\t\tmaxY = Math.max(maxY, y);\n\t\tavgZ += data[dataIdx + 2];\n\t\tavgVisibility += data[dataIdx + 3];\n\t}\n\n\treturn [\n\t\t(minX + maxX) / 2,\n\t\t(minY + maxY) / 2,\n\t\tavgZ / landmarkIndices.length,\n\t\tavgVisibility / landmarkIndices.length,\n\t];\n}\n\nlet filesetPromise: Promise<any> | null = null;\nexport function getSharedFileset(): Promise<any> {\n\tif (!filesetPromise) {\n\t\tfilesetPromise = import('@mediapipe/tasks-vision').then(({ FilesetResolver }) =>\n\t\t\tFilesetResolver.forVisionTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision/wasm'),\n\t\t);\n\t}\n\treturn filesetPromise;\n}\n\nexport function generateGLSLFn(history: number | undefined) {\n\tconst historyParams = history ? ', framesAgo' : '';\n\tconst fn = history\n\t\t? (returnType: string, name: string, args: string, body: string) => {\n\t\t\t\tconst argsOnly = args.replace(/\\w+ /g, '');\n\t\t\t\tconst historyArgs = args ? `${args}, int framesAgo` : 'int framesAgo';\n\t\t\t\tconst callArgs = argsOnly ? `${argsOnly}, 0` : '0';\n\t\t\t\treturn `${returnType} ${name}(${historyArgs}) {\\n${body}\\n}\n${returnType} ${name}(${args}) { return ${name}(${callArgs}); }`;\n\t\t\t}\n\t\t: (returnType: string, name: string, args: string, body: string) =>\n\t\t\t\t`${returnType} ${name}(${args}) {\\n${body}\\n}`;\n\treturn { historyParams, fn };\n}\n"],"mappings":"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","names":["detector"]}
|
|
@@ -410,6 +410,7 @@ function face(config) {
|
|
|
410
410
|
const { injectGLSL, emit, updateTexture } = context;
|
|
411
411
|
const existingDetector = sharedDetectors.get(optionsKey);
|
|
412
412
|
const landmarksData = existingDetector?.landmarks.data ?? new Float32Array(LANDMARKS_TEXTURE_WIDTH * textureHeight * 4);
|
|
413
|
+
const mediapipeCanvas = existingDetector?.mediapipeCanvas ?? new OffscreenCanvas(1, 1);
|
|
413
414
|
const maskCanvas = existingDetector?.mask.canvas ?? new OffscreenCanvas(1, 1);
|
|
414
415
|
let detector;
|
|
415
416
|
let destroyed = false;
|
|
@@ -459,6 +460,7 @@ function face(config) {
|
|
|
459
460
|
modelAssetPath: options.modelPath,
|
|
460
461
|
delegate: "GPU"
|
|
461
462
|
},
|
|
463
|
+
canvas: mediapipeCanvas,
|
|
462
464
|
runningMode: "VIDEO",
|
|
463
465
|
numFaces: options.maxFaces,
|
|
464
466
|
minFaceDetectionConfidence: options.minFaceDetectionConfidence,
|
|
@@ -473,6 +475,7 @@ function face(config) {
|
|
|
473
475
|
}
|
|
474
476
|
const detector2 = {
|
|
475
477
|
landmarker: faceLandmarker,
|
|
478
|
+
mediapipeCanvas,
|
|
476
479
|
mask: initMaskRenderer(maskCanvas),
|
|
477
480
|
subscribers: /* @__PURE__ */ new Map(),
|
|
478
481
|
maxFaces: options.maxFaces,
|