shaderpad 1.0.0-beta.36 → 1.0.0-beta.38

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\nexport interface TextureOptions {\n\tinternalFormat?: number;\n\tformat?: number;\n\ttype?: number;\n\tminFilter?: number;\n\tmagFilter?: number;\n\twrapS?: number;\n\twrapT?: number;\n\tpreserveY?: boolean;\n}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n\twidth: number;\n\theight: number;\n\thistory?: {\n\t\tdepth: number;\n\t\twriteIndex: number;\n\t};\n\toptions?: TextureOptions;\n}\n\nexport interface CustomTexture {\n\tdata: ArrayBufferView | null;\n\twidth: number;\n\theight: number;\n}\n\nexport interface PartialCustomTexture extends CustomTexture {\n\tisPartial?: boolean;\n\tx?: number;\n\ty?: number;\n}\n\nexport type TextureSource =\n\t| HTMLImageElement\n\t| HTMLVideoElement\n\t| HTMLCanvasElement\n\t| OffscreenCanvas\n\t| ImageBitmap\n\t| WebGLTexture\n\t| CustomTexture;\n\n// Custom textures allow partial updates starting from (x, y).\ntype UpdateTextureSource = Exclude<TextureSource, CustomTexture> | PartialCustomTexture;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement | OffscreenCanvas;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options {\n\tcanvas?: HTMLCanvasElement | OffscreenCanvas | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n\tdebug?: boolean;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource): { width: number; height: number } {\n\tif (source instanceof WebGLTexture) {\n\t\treturn { width: 0, height: 0 }; // Invalid - dimensions not readable.\n\t}\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t}\n\tif (source instanceof HTMLImageElement) {\n\t\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n\t}\n\t// CustomTexture, HTMLCanvasElement, OffscreenCanvas, ImageBitmap.\n\treturn { width: source.width, height: source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate aPositionLocation = 0;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement | OffscreenCanvas;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth: number;\n\tprivate debug: boolean;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\t\thtmlCanvas.style.position = 'fixed';\n\t\t\thtmlCanvas.style.inset = '0';\n\t\t\thtmlCanvas.style.height = '100dvh';\n\t\t\thtmlCanvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(htmlCanvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.historyDepth = options.history ?? 0;\n\t\tthis.debug = options.debug ?? (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (options.plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\toptions.plugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tthis.aPositionLocation = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\t\tthis.resizeObserver.observe(this.canvas);\n\t\t}\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, { history: this.historyDepth });\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer() {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(this.aPositionLocation);\n\t\tthis.gl.vertexAttribPointer(this.aPositionLocation, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tif (!(this.canvas instanceof HTMLCanvasElement)) return;\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\thtmlCanvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst type = textureInfo.options?.type ?? this.gl.UNSIGNED_BYTE;\n\t\tconst transparent =\n\t\t\ttype === this.gl.FLOAT\n\t\t\t\t? new Float32Array(textureInfo.width * textureInfo.height * 4)\n\t\t\t\t: new Uint8Array(textureInfo.width * textureInfo.height * 4);\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tthis.gl.texSubImage3D(\n\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\ttextureInfo.options?.format ?? this.gl.RGBA,\n\t\t\t\ttype,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tthis.log(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate log(...args: any[]) {\n\t\tif (this.debug) console.debug(...args);\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tthis.gl.useProgram(this.program);\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tthis.log(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](uniform.location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history'>,\n\t\toptions?: TextureOptions & { unitIndex?: number }\n\t) {\n\t\tconst { width, height } = textureInfo;\n\t\tconst historyDepth = textureInfo.history?.depth ?? 0;\n\n\t\tconst texture = this.gl.createTexture();\n\t\tif (!texture) {\n\t\t\tthrow new Error('Failed to create texture');\n\t\t}\n\n\t\tlet unitIndex = options?.unitIndex;\n\t\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, options?.wrapS ?? this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, options?.wrapT ?? this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, options?.minFilter ?? this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, options?.magFilter ?? this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tconst type = options?.type ?? this.gl.UNSIGNED_BYTE;\n\t\t\tconst internalFormat =\n\t\t\t\toptions?.internalFormat ?? (type === this.gl.FLOAT ? this.gl.RGBA32F : this.gl.RGBA8);\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, internalFormat, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(\n\t\tname: string | symbol,\n\t\tsource: TextureSource,\n\t\toptions?: TextureOptions & { history?: number }\n\t) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${stringFrom(name)}' is already initialized.`);\n\t\t}\n\n\t\tconst { history: historyDepth = 0, ...textureOptions } = options ?? {};\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history'> = { width, height };\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo, textureOptions);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo, options: textureOptions };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: TextureOptions & { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: UpdateTextureSource) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\tif (source instanceof WebGLTexture) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, source);\n\t\t\treturn;\n\t\t}\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) return;\n\n\t\tconst isPartial = 'isPartial' in source && source.isPartial;\n\t\tif (!isPartial && (info.width !== width || info.height !== height)) {\n\t\t\tthis.gl.deleteTexture(info.texture);\n\t\t\tinfo.width = width;\n\t\t\tinfo.height = height;\n\t\t\tconst { texture } = this.createTexture(name, info, { ...info.options, unitIndex: info.unitIndex });\n\t\t\tinfo.texture = texture;\n\t\t\tif (info.history) {\n\t\t\t\tinfo.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t\t}\n\t\t}\n\n\t\t// UNPACK_FLIP_Y_WEBGL only works for DOM element sources, not typed arrays.\n\t\tconst isTypedArray = 'data' in source && source.data;\n\t\tconst shouldFlipY = !isTypedArray && !info.options?.preserveY;\n\t\tconst previousFlipY = this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);\n\n\t\tif (info.history) {\n\t\t\tconst isFramebufferHistory = name === HISTORY_TEXTURE_KEY;\n\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (isFramebufferHistory) {\n\t\t\t\tthis.gl.copyTexSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tinfo.options?.format ?? this.gl.RGBA,\n\t\t\t\t\tinfo.options?.type ?? this.gl.UNSIGNED_BYTE,\n\t\t\t\t\t((source as PartialCustomTexture).data ?? (source as Exclude<TextureSource, CustomTexture>)) as any\n\t\t\t\t);\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t\t}\n\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\n\t\t\tconst format = info.options?.format ?? this.gl.RGBA;\n\t\t\tconst type = info.options?.type ?? this.gl.UNSIGNED_BYTE;\n\n\t\t\tif (isPartial) {\n\t\t\t\tthis.gl.texSubImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tsource.x ?? 0,\n\t\t\t\t\tsource.y ?? 0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tformat,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource.data\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst internalFormat =\n\t\t\t\t\tinfo.options?.internalFormat ??\n\t\t\t\t\t(isTypedArray ? (type === this.gl.FLOAT ? this.gl.RGBA32F : this.gl.RGBA8) : this.gl.RGBA);\n\t\t\t\tthis.gl.texImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tinternalFormat,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t0,\n\t\t\t\t\tformat,\n\t\t\t\t\ttype,\n\t\t\t\t\t((source as PartialCustomTexture).data ?? (source as Exclude<TextureSource, CustomTexture>)) as any\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t}\n\t}\n\n\tdraw(clear = true) {\n\t\tconst gl = this.gl;\n\t\tgl.useProgram(this.program);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\t\tif (clear) gl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t}\n\n\tstep(time: number) {\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\tthis.draw();\n\n\t\tif (this.textures.get(HISTORY_TEXTURE_KEY)) {\n\t\t\tthis.updateTexture(HISTORY_TEXTURE_KEY, this.canvas);\n\t\t}\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t\t});\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas && this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAMI,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ5BC,EAA2B,mBA6F3BC,EAAsB,OAAO,WAAW,EAE9C,SAASC,EAAkBC,EAAgBC,EAA8B,CACxE,GAAI,CAACA,GAAY,OAAQ,OAAOD,EAChC,IAAME,EAAQF,EAAO,MAAM;AAAA,CAAI,EACzBG,EACLD,EAAM,cAAcE,GAAQ,CAC3B,IAAMC,EAAUD,EAAK,UAAU,EAC/B,OAAOC,EAAQ,WAAW,YAAY,GAAKA,EAAQ,WAAW,WAAW,CAC1E,CAAC,EAAI,EACN,OAAAH,EAAM,OAAOC,EAAU,EAAG,GAAGF,CAAU,EAChCC,EAAM,KAAK;AAAA,CAAI,CACvB,CAEA,SAASI,EAAoBC,EAA0D,CACtF,OAAIA,aAAkB,aACd,CAAE,MAAO,EAAG,OAAQ,CAAE,EAE1BA,aAAkB,iBACd,CAAE,MAAOA,EAAO,WAAY,OAAQA,EAAO,WAAY,EAE3DA,aAAkB,iBACd,CAAE,MAAOA,EAAO,cAAgBA,EAAO,MAAO,OAAQA,EAAO,eAAiBA,EAAO,MAAO,EAG7F,CAAE,MAAOA,EAAO,MAAO,OAAQA,EAAO,MAAO,CACrD,CAEA,SAASC,EAAWC,EAAuB,CAC1C,OAAO,OAAOA,GAAS,SAAWA,EAAK,aAAe,GAAKA,CAC5D,CAEA,IAAMC,EAAN,KAAgB,CACP,iBAAmB,GACnB,cAAgB,GAChB,GACA,kBACA,SAAiC,IAAI,IACrC,SAA0C,IAAI,IAC9C,gBACA,OAA6B,KAC7B,QAA+B,KAC/B,kBAAoB,EACpB,iBACA,mBACA,eACA,cAA+C,KAC/C,eAAiB,KACjB,eAA6C,IAAI,IACjD,MAAQ,EACR,UAAY,EACZ,eAAiB,CAAC,GAAK,EAAG,EAC1B,cAAgB,CAAC,GAAK,EAAG,EACzB,YAAc,GACf,OACA,SACC,MAA0C,IAAI,IAC9C,aACA,MAER,YAAYC,EAA2BC,EAAmB,CAAC,EAAG,CAE7D,GADA,KAAK,OAASA,EAAQ,QAAU,SAAS,cAAc,QAAQ,EAC3D,CAACA,EAAQ,OAAQ,CACpB,KAAK,iBAAmB,GACxB,IAAMC,EAAa,KAAK,OACxBA,EAAW,MAAM,SAAW,QAC5BA,EAAW,MAAM,MAAQ,IACzBA,EAAW,MAAM,OAAS,SAC1BA,EAAW,MAAM,MAAQ,SACzB,SAAS,KAAK,YAAYA,CAAU,CACrC,CAGA,GADA,KAAK,GAAK,KAAK,OAAO,WAAW,SAAU,CAAE,UAAW,EAAM,CAAC,EAC3D,CAAC,KAAK,GACT,MAAM,IAAI,MAAM,kEAAkE,EAGnF,KAAK,gBAAkB,CACtB,KAAM,CAAC,EACP,KAAM,EACN,IAAK,KAAK,GAAG,aAAa,KAAK,GAAG,gCAAgC,CACnE,EACA,KAAK,aAAeD,EAAQ,SAAW,EACvC,KAAK,MAAQA,EAAQ,QAAU,OAAO,QAAY,KAAe,IACjE,KAAK,iBAAmB,KACxB,KAAK,mBAAqB,IAAI,iBAAiB,IAAM,KAAK,iBAAiB,CAAC,EAC5E,KAAK,eAAiB,IAAI,eAAe,IAAM,KAAK,sBAAsB,CAAC,EAE3E,IAAME,EAA2B,CAAC,EAClC,GAAIF,EAAQ,QAAS,CACpB,IAAMG,EAAyB,CAC9B,GAAI,KAAK,GACT,SAAU,KAAK,SACf,SAAU,KAAK,SACf,OAAQ,KAAK,OACb,mBAAoB,KAAK,mBAAmB,KAAK,IAAI,EACrD,mBAAoB,KAAK,mBAAmB,KAAK,IAAI,EACrD,WAAaC,GAAiB,CAC7BF,EAAe,KAAKE,CAAI,CACzB,CACD,EAEA,OAAO,eAAeD,EAAS,UAAW,CACzC,IAAK,IAAM,KAAK,QAChB,WAAY,GACZ,aAAc,EACf,CAAC,EACDH,EAAQ,QAAQ,QAAQK,GAAUA,EAAO,KAAMF,CAAO,CAAC,CACxD,CAEA,KAAK,kBAAoBhB,EAAkBY,EAAmBG,CAAc,EAC5E,KAAK,KAAK,EACN,KAAK,kBAAkB,mBAC1B,KAAK,kBAAkB,CAEzB,CAEA,aAAaL,EAAuBS,EAAc,CAC5C,KAAK,MAAM,IAAIT,CAAI,GACvB,KAAK,MAAM,IAAIA,EAAM,CAAC,CAAC,EAExB,KAAK,MAAM,IAAIA,CAAI,EAAG,KAAKS,CAAE,CAC9B,CAEQ,MAAO,CACd,IAAMC,EAAkBvB,EAGxB,GADA,KAAK,QAAU,KAAK,GAAG,cAAc,EACjC,CAAC,KAAK,QACT,MAAM,IAAI,MAAM,gCAAgC,EAEjD,IAAMwB,EAAe,KAAK,aAAa,KAAK,GAAG,cAAeD,CAAe,EACvEE,EAAiB,KAAK,aAAa,KAAK,GAAG,gBAAiB,KAAK,iBAAiB,EAQxF,GANA,KAAK,GAAG,aAAa,KAAK,QAASD,CAAY,EAC/C,KAAK,GAAG,aAAa,KAAK,QAASC,CAAc,EACjD,KAAK,GAAG,YAAY,KAAK,OAAO,EAChC,KAAK,GAAG,aAAaD,CAAY,EACjC,KAAK,GAAG,aAAaC,CAAc,EAE/B,CAAC,KAAK,GAAG,oBAAoB,KAAK,QAAS,KAAK,GAAG,WAAW,EACjE,cAAQ,MAAM,sBAAuB,KAAK,GAAG,kBAAkB,KAAK,OAAO,CAAC,EAC5E,KAAK,GAAG,cAAc,KAAK,OAAO,EAC5B,IAAI,MAAM,8BAA8B,EAG/C,KAAK,kBAAoB,KAAK,GAAG,kBAAkB,KAAK,QAAS,WAAW,EAC5E,KAAK,YAAY,EAEjB,KAAK,GAAG,WAAW,KAAK,OAAO,EAE3B,KAAK,kBAAkB,oBAC1B,KAAK,mBAAmB,QAAQ,KAAK,OAAQ,CAAE,WAAY,GAAM,gBAAiB,CAAC,QAAS,QAAQ,CAAE,CAAC,EACvG,KAAK,eAAe,QAAQ,KAAK,MAAM,GAGnC,KAAK,kBACT,KAAK,iBAAiB,EAEvB,KAAK,kBAAkB,WAAY,QAAS,KAAK,cAAc,EAC/D,KAAK,kBAAkB,UAAW,QAAS,CAAC,GAAG,KAAK,cAAe,KAAK,YAAc,EAAM,CAAG,CAAC,EAChG,KAAK,kBAAkB,SAAU,QAAS,CAAC,EAC3C,KAAK,kBAAkB,UAAW,MAAO,CAAC,EACtC,KAAK,aAAe,GACvB,KAAK,mBAAmBvB,EAAqB,KAAK,OAAQ,CAAE,QAAS,KAAK,YAAa,CAAC,EAGzF,KAAK,MAAM,IAAI,MAAM,GAAG,QAAQwB,GAAQA,EAAK,KAAK,IAAI,CAAC,CACxD,CAEQ,aAAaC,EAAchB,EAA6B,CAC/D,IAAMP,EAAS,KAAK,GAAG,aAAauB,CAAI,EAGxC,GAFA,KAAK,GAAG,aAAavB,EAAQO,CAAM,EACnC,KAAK,GAAG,cAAcP,CAAM,EACxB,CAAC,KAAK,GAAG,mBAAmBA,EAAQ,KAAK,GAAG,cAAc,EAC7D,cAAQ,MAAM,6BAA8BO,CAAM,EAClD,QAAQ,MAAM,KAAK,GAAG,iBAAiBP,CAAM,CAAC,EAC9C,KAAK,GAAG,aAAaA,CAAM,EACrB,IAAI,MAAM,2BAA2B,EAE5C,OAAOA,CACR,CAEQ,aAAc,CACrB,IAAMwB,EAAe,IAAI,aAAa,CAAC,GAAI,GAAI,EAAG,GAAI,GAAI,EAAG,GAAI,EAAG,EAAG,GAAI,EAAG,CAAC,CAAC,EAEhF,KAAK,OAAS,KAAK,GAAG,aAAa,EACnC,KAAK,GAAG,WAAW,KAAK,GAAG,aAAc,KAAK,MAAM,EACpD,KAAK,GAAG,WAAW,KAAK,GAAG,aAAcA,EAAc,KAAK,GAAG,WAAW,EAC1E,KAAK,GAAG,SAAS,EAAG,EAAG,KAAK,GAAG,mBAAoB,KAAK,GAAG,mBAAmB,EAC9E,KAAK,GAAG,wBAAwB,KAAK,iBAAiB,EACtD,KAAK,GAAG,oBAAoB,KAAK,kBAAmB,EAAG,KAAK,GAAG,MAAO,GAAO,EAAG,CAAC,CAClF,CAEQ,uBAAwB,CAC/B,aAAa,KAAK,aAAa,EAC/B,IAAMC,EAAM,YAAY,IAAI,EACtBC,EAAsB,KAAK,eAAiB7B,EAA2B4B,EACzEC,GAAuB,GAC1B,KAAK,eAAiBD,EACtB,KAAK,aAAa,GAElB,KAAK,cAAgB,WAAW,IAAM,KAAK,sBAAsB,EAAGC,CAAmB,CAEzF,CAEQ,cAAe,CACtB,GAAI,EAAE,KAAK,kBAAkB,mBAAoB,OACjD,IAAMC,EAAa,OAAO,kBAAoB,EACxCC,EAAQ,KAAK,OAAO,YAAcD,EAClCE,EAAS,KAAK,OAAO,aAAeF,EACtC,KAAK,mBAAqB,KAAK,OAAO,QAAUC,GAAS,KAAK,OAAO,SAAWC,KACnF,KAAK,OAAO,MAAQD,EACpB,KAAK,OAAO,OAASC,GAEtB,KAAK,WAAWD,EAAOC,CAAM,CAC9B,CAEQ,mBAAoB,CAC3B,IAAMhB,EAAa,KAAK,OAClBiB,EAAe,CAACC,EAAWC,IAAc,CAC9C,GAAI,CAAC,KAAK,SAAS,IAAI,UAAU,EAAG,OACpC,IAAMC,EAAOpB,EAAW,sBAAsB,EAC9C,KAAK,eAAe,CAAC,GAAKkB,EAAIE,EAAK,MAAQA,EAAK,MAChD,KAAK,eAAe,CAAC,EAAI,GAAKD,EAAIC,EAAK,KAAOA,EAAK,OACnD,KAAK,eAAe,CAAE,SAAU,KAAK,cAAe,CAAC,CACtD,EAEMC,EAAc,CAACC,EAAsBJ,EAAYC,IAAe,CACrE,GAAK,KAAK,SAAS,IAAI,SAAS,EAEhC,IADA,KAAK,YAAcG,EACfA,EAAa,CAChB,IAAMF,EAAOpB,EAAW,sBAAsB,EACxCuB,EAAOL,EACPM,EAAOL,EACb,KAAK,cAAc,CAAC,GAAKI,EAAOH,EAAK,MAAQA,EAAK,MAClD,KAAK,cAAc,CAAC,EAAI,GAAKI,EAAOJ,EAAK,KAAOA,EAAK,MACtD,CACA,KAAK,eAAe,CAAE,QAAS,CAAC,GAAG,KAAK,cAAe,KAAK,YAAc,EAAM,CAAG,CAAE,CAAC,EACvF,EAEA,KAAK,eAAe,IAAI,YAAaK,GAAS,CAC7C,IAAMC,EAAaD,EACd,KAAK,eACTR,EAAaS,EAAW,QAASA,EAAW,OAAO,CAErD,CAAC,EAED,KAAK,eAAe,IAAI,YAAaD,GAAS,CAC7C,IAAMC,EAAaD,EACd,KAAK,eACLC,EAAW,SAAW,IACzB,KAAK,YAAc,GACnBL,EAAY,GAAMK,EAAW,QAASA,EAAW,OAAO,EAG3D,CAAC,EAED,KAAK,eAAe,IAAI,UAAWD,GAAS,CAC3C,IAAMC,EAAaD,EACd,KAAK,eACLC,EAAW,SAAW,GACzBL,EAAY,EAAK,CAGpB,CAAC,EAED,KAAK,eAAe,IAAI,YAAaI,GAAS,CAC7C,IAAME,EAAaF,EACfE,EAAW,QAAQ,OAAS,GAC/BV,EAAaU,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,CAE3E,CAAC,EAED,KAAK,eAAe,IAAI,aAAcF,GAAS,CAC9C,IAAME,EAAaF,EACnB,KAAK,cAAgB,GACjBE,EAAW,QAAQ,OAAS,IAC/BV,EAAaU,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,EACzEN,EAAY,GAAMM,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,EAEhF,CAAC,EAED,KAAK,eAAe,IAAI,WAAYF,GAAS,CACzBA,EACJ,QAAQ,SAAW,GACjCJ,EAAY,EAAK,CAEnB,CAAC,EAED,KAAK,eAAe,QAAQ,CAACO,EAAUH,IAAU,CAChDzB,EAAW,iBAAiByB,EAAOG,CAAQ,CAC5C,CAAC,CACF,CAEQ,kBAAmB,CAC1B,IAAMC,EAA+B,CAAC,KAAK,GAAG,mBAAoB,KAAK,GAAG,mBAAmB,EAC7F,KAAK,GAAG,SAAS,EAAG,EAAG,GAAGA,CAAU,EAChC,KAAK,SAAS,IAAI,cAAc,EACnC,KAAK,eAAe,CAAE,aAAcA,CAAW,CAAC,EAEhD,KAAK,kBAAkB,eAAgB,QAASA,CAAU,EAE3D,KAAK,MAAM,IAAI,kBAAkB,GAAG,QAAQpB,GAAQA,EAAK,KAAK,IAAI,CAAC,CACpE,CAEQ,mBAAmBb,EAAuB,CACjD,IAAMkC,EAAW,KAAK,SAAS,IAAIlC,CAAI,EACvC,GAAIkC,EAAU,OAAOA,EAAS,UAC9B,GAAI,KAAK,gBAAgB,KAAK,OAAS,EAAG,OAAO,KAAK,gBAAgB,KAAK,IAAI,EAC/E,GAAI,KAAK,gBAAgB,MAAQ,KAAK,gBAAgB,IACrD,MAAM,IAAI,MAAM,uDAAuD,EAExE,OAAO,KAAK,gBAAgB,MAC7B,CAEQ,mBAAmBlC,EAAuB,CACjD,IAAMkC,EAAW,KAAK,SAAS,IAAIlC,CAAI,EACnCkC,GACH,KAAK,gBAAgB,KAAK,KAAKA,EAAS,SAAS,CAEnD,CAEQ,0BAA0BC,EAA4B,CAC7D,GAAI,CAACA,EAAY,QAAS,OAE1B,IAAMrB,EAAOqB,EAAY,SAAS,MAAQ,KAAK,GAAG,cAC5CC,EACLtB,IAAS,KAAK,GAAG,MACd,IAAI,aAAaqB,EAAY,MAAQA,EAAY,OAAS,CAAC,EAC3D,IAAI,WAAWA,EAAY,MAAQA,EAAY,OAAS,CAAC,EAC7D,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWA,EAAY,SAAS,EAC9D,KAAK,GAAG,YAAY,KAAK,GAAG,iBAAkBA,EAAY,OAAO,EACjE,QAASE,EAAQ,EAAGA,EAAQF,EAAY,QAAQ,MAAO,EAAEE,EACxD,KAAK,GAAG,cACP,KAAK,GAAG,iBACR,EACA,EACA,EACAA,EACAF,EAAY,MACZA,EAAY,OACZ,EACAA,EAAY,SAAS,QAAU,KAAK,GAAG,KACvCrB,EACAsB,CACD,CAEF,CAEA,kBACCpC,EACAc,EACAwB,EACAnC,EACC,CACD,IAAMoC,EAAcpC,GAAS,YAC7B,GAAI,KAAK,SAAS,IAAIH,CAAI,EACzB,MAAM,IAAI,MAAM,GAAGA,CAAI,0BAA0B,EAElD,GAAIc,IAAS,SAAWA,IAAS,MAChC,MAAM,IAAI,MAAM,yBAAyBA,CAAI,8BAA8B,EAE5E,GAAIyB,GAAe,EAAE,MAAM,QAAQD,CAAK,GAAKA,EAAM,SAAWC,GAC7D,MAAM,IAAI,MAAM,GAAGvC,CAAI,gDAAgDuC,CAAW,YAAY,EAG/F,IAAIC,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAUxC,CAAI,EAI7D,GAHI,CAACwC,GAAYD,IAChBC,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAU,GAAGxC,CAAI,KAAK,GAE9D,CAACwC,EAAU,CACd,KAAK,IAAI,GAAGxC,CAAI,yDAAyD,EACzE,MACD,CAEA,IAAMyC,EAAaF,EAAeD,EAAgC,CAAC,EAAIA,EACjEI,EAAS,MAAM,QAAQD,CAAU,EAAKA,EAAW,OAA2B,EAClF,KAAK,SAAS,IAAIzC,EAAM,CAAE,KAAAc,EAAM,OAAA4B,EAAQ,SAAAF,EAAU,YAAAD,CAAY,CAAC,EAE/D,GAAI,CACH,KAAK,eAAe,CAAE,CAACvC,CAAI,EAAGsC,CAAM,CAAC,CACtC,OAASK,EAAO,CACf,WAAK,SAAS,OAAO3C,CAAI,EACnB2C,CACP,CACA,KAAK,MAAM,IAAI,mBAAmB,GAAG,QAAQ9B,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CACnF,CAEQ,OAAO+B,EAAa,CACvB,KAAK,OAAO,QAAQ,MAAM,GAAGA,CAAI,CACtC,CAEA,eACCC,EACA1C,EACC,CACD,KAAK,GAAG,WAAW,KAAK,OAAO,EAC/B,OAAO,QAAQ0C,CAAO,EAAE,QAAQ,CAAC,CAAC7C,EAAMsC,CAAK,IAAM,CAClD,IAAMQ,EAAU,KAAK,SAAS,IAAI9C,CAAI,EACtC,GAAI,CAAC8C,EAAS,CACb,KAAK,IAAI,GAAG9C,CAAI,iDAAiD,EACjE,MACD,CAEA,IAAI+C,EAAiB,UAAUD,EAAQ,MAAM,GAAGA,EAAQ,KAAK,OAAO,CAAC,CAAC,GACtE,GAAIA,EAAQ,YAAa,CACxB,GAAI,CAAC,MAAM,QAAQR,CAAK,EACvB,MAAM,IAAI,MAAM,GAAGtC,CAAI,uEAAuE,EAE/F,IAAMgD,EAAUV,EAAM,OACtB,GAAI,CAACU,EAAS,OACd,GAAIA,EAAUF,EAAQ,YACrB,MAAM,IAAI,MACT,GAAG9C,CAAI,aAAagD,CAAO,kCAAkCF,EAAQ,WAAW,GACjF,EAED,GAAIR,EAAM,KAAKW,IAAS,MAAM,QAAQA,CAAI,EAAIA,EAAK,OAAS,KAAOH,EAAQ,MAAM,EAChF,MAAM,IAAI,MACT,mBAAmB9C,CAAI,2CAA2C8C,EAAQ,MAAM,GACjF,EAED,IAAMI,EAAa,IAAKJ,EAAQ,OAAS,QAAU,aAAe,YAAYR,EAAM,KAAK,CAAC,EACtFE,EAAWM,EAAQ,SACvB,GAAI3C,GAAS,WAAY,CACxB,IAAMgD,EAAc,KAAK,GAAG,mBAAmB,KAAK,QAAU,GAAGnD,CAAI,IAAIG,EAAQ,UAAU,GAAG,EAC9F,GAAI,CAACgD,EACJ,MAAM,IAAI,MACT,GAAGnD,CAAI,IAAIG,EAAQ,UAAU,qEAC9B,EAEDqC,EAAWW,CACZ,CACC,KAAK,GAAWJ,EAAiB,GAAG,EAAED,EAAQ,SAAUI,CAAU,CACpE,KAAO,CAEN,GADK,MAAM,QAAQZ,CAAK,IAAGA,EAAQ,CAACA,CAAK,GACrCA,EAAM,SAAWQ,EAAQ,OAC5B,MAAM,IAAI,MAAM,iCAAiCR,EAAM,MAAM,cAAcQ,EAAQ,MAAM,GAAG,EAE5F,KAAK,GAAWC,CAAc,EAAED,EAAQ,SAAU,GAAGR,CAAK,CAC5D,CACD,CAAC,EACD,KAAK,MAAM,IAAI,gBAAgB,GAAG,QAAQzB,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CAChF,CAEQ,cACPb,EACAmC,EACAhC,EACC,CACD,GAAM,CAAE,MAAAgB,EAAO,OAAAC,CAAO,EAAIe,EACpBiB,EAAejB,EAAY,SAAS,OAAS,EAE7CkB,EAAU,KAAK,GAAG,cAAc,EACtC,GAAI,CAACA,EACJ,MAAM,IAAI,MAAM,0BAA0B,EAG3C,IAAIC,EAAYnD,GAAS,UACzB,GAAI,OAAOmD,GAAc,SACxB,GAAI,CACHA,EAAY,KAAK,mBAAmBtD,CAAI,CACzC,OAAS2C,EAAO,CACf,WAAK,GAAG,cAAcU,CAAO,EACvBV,CACP,CAGD,IAAMY,EAAaH,EAAe,EAC5BI,EAAgBD,EAAa,KAAK,GAAG,iBAAmB,KAAK,GAAG,WAQtE,GANA,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWD,CAAS,EAClD,KAAK,GAAG,YAAYE,EAAeH,CAAO,EAC1C,KAAK,GAAG,cAAcG,EAAe,KAAK,GAAG,eAAgBrD,GAAS,OAAS,KAAK,GAAG,aAAa,EACpG,KAAK,GAAG,cAAcqD,EAAe,KAAK,GAAG,eAAgBrD,GAAS,OAAS,KAAK,GAAG,aAAa,EACpG,KAAK,GAAG,cAAcqD,EAAe,KAAK,GAAG,mBAAoBrD,GAAS,WAAa,KAAK,GAAG,MAAM,EACrG,KAAK,GAAG,cAAcqD,EAAe,KAAK,GAAG,mBAAoBrD,GAAS,WAAa,KAAK,GAAG,MAAM,EACjGoD,EAAY,CACf,IAAMzC,EAAOX,GAAS,MAAQ,KAAK,GAAG,cAChCsD,EACLtD,GAAS,iBAAmBW,IAAS,KAAK,GAAG,MAAQ,KAAK,GAAG,QAAU,KAAK,GAAG,OAChF,KAAK,GAAG,aAAa0C,EAAe,EAAGC,EAAgBtC,EAAOC,EAAQgC,CAAY,CACnF,CACA,MAAO,CAAE,QAAAC,EAAS,UAAAC,CAAU,CAC7B,CAEQ,mBACPtD,EACAF,EACAK,EACC,CACD,GAAI,KAAK,SAAS,IAAIH,CAAI,EACzB,MAAM,IAAI,MAAM,YAAYD,EAAWC,CAAI,CAAC,2BAA2B,EAGxE,GAAM,CAAE,QAASoD,EAAe,EAAG,GAAGM,CAAe,EAAIvD,GAAW,CAAC,EAC/D,CAAE,MAAAgB,EAAO,OAAAC,CAAO,EAAIvB,EAAoBC,CAAM,EACpD,GAAI,CAACqB,GAAS,CAACC,EACd,MAAM,IAAI,MAAM,2CAA2C,EAE5D,IAAMe,EAA6D,CAAE,MAAAhB,EAAO,OAAAC,CAAO,EAC/EgC,EAAe,IAClBjB,EAAY,QAAU,CAAE,MAAOiB,EAAc,WAAY,CAAE,GAE5D,GAAM,CAAE,QAAAC,EAAS,UAAAC,CAAU,EAAI,KAAK,cAActD,EAAMmC,EAAauB,CAAc,EAC7EC,EAA+B,CAAE,QAAAN,EAAS,UAAAC,EAAW,GAAGnB,EAAa,QAASuB,CAAe,EAC/FN,EAAe,IAClB,KAAK,kBAAkB,GAAGrD,EAAWC,CAAI,CAAC,cAAe,MAAO,CAAC,EACjE,KAAK,0BAA0B2D,CAAmB,GAEnD,KAAK,SAAS,IAAI3D,EAAM2D,CAAmB,EAC3C,KAAK,cAAc3D,EAAMF,CAAM,EAG/B,IAAM8D,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAU7D,EAAWC,CAAI,CAAC,EACvE4D,GACH,KAAK,GAAG,UAAUA,EAAUN,CAAS,CAEvC,CAEA,kBAAkBtD,EAAcF,EAAuBK,EAAiD,CACvG,KAAK,mBAAmBH,EAAMF,EAAQK,CAAO,EAC7C,KAAK,MAAM,IAAI,mBAAmB,GAAG,QAAQU,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CACnF,CAEA,eAAegC,EAA8C,CAC5D,KAAK,MAAM,IAAI,gBAAgB,GAAG,QAAQhC,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,EAC/E,OAAO,QAAQgC,CAAO,EAAE,QAAQ,CAAC,CAAC7C,EAAMF,CAAM,IAAM,CACnD,KAAK,cAAcE,EAAMF,CAAM,CAChC,CAAC,CACF,CAEQ,cAAcE,EAAuBF,EAA6B,CACzE,IAAM+D,EAAO,KAAK,SAAS,IAAI7D,CAAI,EACnC,GAAI,CAAC6D,EAAM,MAAM,IAAI,MAAM,YAAY9D,EAAWC,CAAI,CAAC,uBAAuB,EAE9E,GAAIF,aAAkB,aAAc,CACnC,KAAK,GAAG,cAAc,KAAK,GAAG,SAAW+D,EAAK,SAAS,EACvD,KAAK,GAAG,YAAY,KAAK,GAAG,WAAY/D,CAAM,EAC9C,MACD,CAGA,GAAM,CAAE,MAAAqB,EAAO,OAAAC,CAAO,EAAIvB,EAAoBC,CAAM,EACpD,GAAI,CAACqB,GAAS,CAACC,EAAQ,OAEvB,IAAM0C,EAAY,cAAehE,GAAUA,EAAO,UAClD,GAAI,CAACgE,IAAcD,EAAK,QAAU1C,GAAS0C,EAAK,SAAWzC,GAAS,CACnE,KAAK,GAAG,cAAcyC,EAAK,OAAO,EAClCA,EAAK,MAAQ1C,EACb0C,EAAK,OAASzC,EACd,GAAM,CAAE,QAAAiC,CAAQ,EAAI,KAAK,cAAcrD,EAAM6D,EAAM,CAAE,GAAGA,EAAK,QAAS,UAAWA,EAAK,SAAU,CAAC,EACjGA,EAAK,QAAUR,EACXQ,EAAK,UACRA,EAAK,QAAQ,WAAa,EAC1B,KAAK,0BAA0BA,CAAI,EAErC,CAGA,IAAME,EAAe,SAAUjE,GAAUA,EAAO,KAC1CkE,EAAc,CAACD,GAAgB,CAACF,EAAK,SAAS,UAC9CI,EAAgB,KAAK,GAAG,aAAa,KAAK,GAAG,mBAAmB,EAEtE,GAAIJ,EAAK,QAAS,CACjB,IAAMK,EAAuBlE,IAASX,EAEtC,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWwE,EAAK,SAAS,EACvD,KAAK,GAAG,YAAY,KAAK,GAAG,iBAAkBA,EAAK,OAAO,EACtDK,EACH,KAAK,GAAG,kBACP,KAAK,GAAG,iBACR,EACA,EACA,EACAL,EAAK,QAAQ,WACb,EACA,EACA1C,EACAC,CACD,GAEA,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAqB4C,CAAW,EAC5D,KAAK,GAAG,cACP,KAAK,GAAG,iBACR,EACA,EACA,EACAH,EAAK,QAAQ,WACb1C,EACAC,EACA,EACAyC,EAAK,SAAS,QAAU,KAAK,GAAG,KAChCA,EAAK,SAAS,MAAQ,KAAK,GAAG,cAC5B/D,EAAgC,MAASA,CAC5C,EACA,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAqBmE,CAAa,GAE/D,IAAME,EAAyB,GAAGpE,EAAWC,CAAI,CAAC,cAClD,KAAK,eAAe,CAAE,CAACmE,CAAsB,EAAGN,EAAK,QAAQ,UAAW,CAAC,EACzEA,EAAK,QAAQ,YAAcA,EAAK,QAAQ,WAAa,GAAKA,EAAK,QAAQ,KACxE,KAAO,CACN,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWA,EAAK,SAAS,EACvD,KAAK,GAAG,YAAY,KAAK,GAAG,WAAYA,EAAK,OAAO,EACpD,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAqBG,CAAW,EAE5D,IAAMI,EAASP,EAAK,SAAS,QAAU,KAAK,GAAG,KACzC/C,EAAO+C,EAAK,SAAS,MAAQ,KAAK,GAAG,cAE3C,GAAIC,EACH,KAAK,GAAG,cACP,KAAK,GAAG,WACR,EACAhE,EAAO,GAAK,EACZA,EAAO,GAAK,EACZqB,EACAC,EACAgD,EACAtD,EACAhB,EAAO,IACR,MACM,CACN,IAAM2D,EACLI,EAAK,SAAS,iBACbE,EAAgBjD,IAAS,KAAK,GAAG,MAAQ,KAAK,GAAG,QAAU,KAAK,GAAG,MAAS,KAAK,GAAG,MACtF,KAAK,GAAG,WACP,KAAK,GAAG,WACR,EACA2C,EACAtC,EACAC,EACA,EACAgD,EACAtD,EACEhB,EAAgC,MAASA,CAC5C,CACD,CACA,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAqBmE,CAAa,CAC/D,CACD,CAEA,KAAKI,EAAQ,GAAM,CAClB,IAAMC,EAAK,KAAK,GAChBA,EAAG,WAAW,KAAK,OAAO,EAC1BA,EAAG,WAAWA,EAAG,aAAc,KAAK,MAAM,EAC1CA,EAAG,oBAAoB,KAAK,kBAAmB,EAAGA,EAAG,MAAO,GAAO,EAAG,CAAC,EACvEA,EAAG,wBAAwB,KAAK,iBAAiB,EACjDA,EAAG,SAAS,EAAG,EAAGA,EAAG,mBAAoBA,EAAG,mBAAmB,EAC3DD,GAAOC,EAAG,MAAMA,EAAG,gBAAgB,EACvCA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,CACjC,CAEA,KAAKC,EAAc,CACd,KAAK,SAAS,IAAI,QAAQ,GAC7B,KAAK,eAAe,CAAE,OAAQA,CAAK,CAAC,EAEjC,KAAK,SAAS,IAAI,SAAS,GAC9B,KAAK,eAAe,CAAE,QAAS,KAAK,KAAM,CAAC,EAG5C,KAAK,KAAK,EAEN,KAAK,SAAS,IAAIlF,CAAmB,GACxC,KAAK,cAAcA,EAAqB,KAAK,MAAM,EAEpD,KAAK,MAAM,IAAI,MAAM,GAAG,QAAQwB,GAAQA,EAAK,KAAK,KAAM0D,EAAM,KAAK,KAAK,CAAC,EACzE,EAAE,KAAK,KACR,CAEA,KAAKC,EAAkD,CACtD,KAAK,MAAM,EACX,IAAMC,EAAQF,GAAiB,CAC9BA,GAAQA,EAAO,KAAK,WAAa,IACjC,KAAK,KAAKA,CAAI,EACd,KAAK,iBAAmB,sBAAsBE,CAAI,EAC9CD,GAAUA,EAASD,EAAM,KAAK,KAAK,CACxC,EACA,KAAK,iBAAmB,sBAAsBE,CAAI,CACnD,CAEA,OAAQ,CACH,KAAK,mBACR,qBAAqB,KAAK,gBAAgB,EAC1C,KAAK,iBAAmB,KAE1B,CAEA,OAAQ,CACP,KAAK,MAAQ,EACb,KAAK,UAAY,YAAY,IAAI,EACjC,KAAK,SAAS,QAAQpB,GAAW,CAC5BA,EAAQ,UACXA,EAAQ,QAAQ,WAAa,EAC7B,KAAK,0BAA0BA,CAAO,EAExC,CAAC,EACD,KAAK,MAAM,IAAI,OAAO,GAAG,QAAQxC,GAAQA,EAAK,KAAK,IAAI,CAAC,CACzD,CAEA,SAAU,CACL,KAAK,mBACR,qBAAqB,KAAK,gBAAgB,EAC1C,KAAK,iBAAmB,MAGzB,KAAK,mBAAmB,WAAW,EACnC,KAAK,eAAe,WAAW,EAC3B,KAAK,kBAAkB,mBAC1B,KAAK,eAAe,QAAQ,CAACmB,EAAUH,IAAU,CAChD,KAAK,OAAO,oBAAoBA,EAAOG,CAAQ,CAChD,CAAC,EAGE,KAAK,SACR,KAAK,GAAG,cAAc,KAAK,OAAO,EAGnC,KAAK,SAAS,QAAQqB,GAAW,CAChC,KAAK,GAAG,cAAcA,EAAQ,OAAO,CACtC,CAAC,EACD,KAAK,gBAAgB,KAAO,CAAC,EAC7B,KAAK,gBAAgB,KAAO,EAExB,KAAK,SACR,KAAK,GAAG,aAAa,KAAK,MAAM,EAChC,KAAK,OAAS,MAGf,KAAK,MAAM,IAAI,SAAS,GAAG,QAAQxC,GAAQA,EAAK,KAAK,IAAI,CAAC,EAEtD,KAAK,kBAAoB,KAAK,kBAAkB,mBACnD,KAAK,OAAO,OAAO,CAErB,CACD,EAEO5B,EAAQgB","names":["index_exports","__export","index_default","__toCommonJS","DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","stringFrom","name","ShaderPad","fragmentShaderSrc","options","htmlCanvas","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","hook","type","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","existing","textureInfo","transparent","layer","value","arrayLength","location","probeValue","length","error","args","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","historyDepth","texture","unitIndex","hasHistory","textureTarget","internalFormat","textureOptions","completeTextureInfo","uSampler","info","isPartial","isTypedArray","shouldFlipY","previousFlipY","isFramebufferHistory","frameOffsetUniformName","format","clear","gl","time","callback","loop"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\nexport interface TextureOptions {\n\tinternalFormat?: number;\n\tformat?: number;\n\ttype?: number;\n\tminFilter?: number;\n\tmagFilter?: number;\n\twrapS?: number;\n\twrapT?: number;\n\tpreserveY?: boolean;\n}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n\twidth: number;\n\theight: number;\n\thistory?: {\n\t\tdepth: number;\n\t\twriteIndex: number;\n\t};\n\toptions?: TextureOptions;\n}\n\nexport interface CustomTexture {\n\tdata: ArrayBufferView | null;\n\twidth: number;\n\theight: number;\n}\n\nexport interface PartialCustomTexture extends CustomTexture {\n\tisPartial?: boolean;\n\tx?: number;\n\ty?: number;\n}\n\nexport type TextureSource =\n\t| HTMLImageElement\n\t| HTMLVideoElement\n\t| HTMLCanvasElement\n\t| OffscreenCanvas\n\t| ImageBitmap\n\t| WebGLTexture\n\t| CustomTexture;\n\n// Custom textures allow partial updates starting from (x, y).\ntype UpdateTextureSource = Exclude<TextureSource, CustomTexture> | PartialCustomTexture;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement | OffscreenCanvas;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'afterStep'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options extends Exclude<TextureOptions, 'preserveY'> {\n\tcanvas?: HTMLCanvasElement | OffscreenCanvas | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n\tdebug?: boolean;\n}\n\nexport interface StepOptions {\n\tskipClear?: boolean;\n\tskipHistoryWrite?: boolean;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\nconst INTERMEDIATE_TEXTURE_KEY = Symbol('__SHADERPAD_BUFFER');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource): { width: number; height: number } {\n\tif (source instanceof WebGLTexture) {\n\t\treturn { width: 0, height: 0 }; // Invalid - dimensions not readable.\n\t}\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t}\n\tif (source instanceof HTMLImageElement) {\n\t\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n\t}\n\t// CustomTexture, HTMLCanvasElement, OffscreenCanvas, ImageBitmap.\n\treturn { width: source.width, height: source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate aPositionLocation = 0;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement | OffscreenCanvas;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth = 0;\n\tprivate textureOptions: TextureOptions;\n\tprivate debug: boolean;\n\t// WebGL can’t read from and write to the history texture at the same time.\n\t// We write to an intermediate texture then blit to the history texture.\n\tprivate intermediateFbo: WebGLFramebuffer | null = null;\n\n\tconstructor(fragmentShaderSrc: string, { canvas, plugins, history, debug, ...textureOptions }: Options = {}) {\n\t\tthis.canvas = canvas || document.createElement('canvas');\n\t\tif (!canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\t\thtmlCanvas.style.position = 'fixed';\n\t\t\thtmlCanvas.style.inset = '0';\n\t\t\thtmlCanvas.style.height = '100dvh';\n\t\t\thtmlCanvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(htmlCanvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.textureOptions = textureOptions;\n\n\t\tconst { internalFormat, type } = textureOptions;\n\t\tconst isFloatFormat =\n\t\t\ttype === this.gl.FLOAT ||\n\t\t\ttype === this.gl.HALF_FLOAT ||\n\t\t\tinternalFormat === this.gl.RGBA16F ||\n\t\t\tinternalFormat === this.gl.RGBA32F ||\n\t\t\tinternalFormat === this.gl.R16F ||\n\t\t\tinternalFormat === this.gl.R32F ||\n\t\t\tinternalFormat === this.gl.RG16F ||\n\t\t\tinternalFormat === this.gl.RG32F;\n\t\tif (isFloatFormat && !this.gl.getExtension('EXT_color_buffer_float')) {\n\t\t\tconsole.warn('EXT_color_buffer_float not supported, falling back to RGBA8');\n\t\t\tdelete this.textureOptions?.internalFormat;\n\t\t\tdelete this.textureOptions?.format;\n\t\t\tdelete this.textureOptions?.type;\n\t\t}\n\n\t\tif (history) this.historyDepth = history;\n\t\tthis.debug = debug ?? (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\tplugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tthis.aPositionLocation = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\t\tthis.resizeObserver.observe(this.canvas);\n\t\t}\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(INTERMEDIATE_TEXTURE_KEY, this.canvas, {\n\t\t\t\t...this.textureOptions,\n\t\t\t});\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, {\n\t\t\t\thistory: this.historyDepth,\n\t\t\t\t...this.textureOptions,\n\t\t\t});\n\t\t\tthis.intermediateFbo = this.gl.createFramebuffer();\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer() {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(this.aPositionLocation);\n\t\tthis.gl.vertexAttribPointer(this.aPositionLocation, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tif (!(this.canvas instanceof HTMLCanvasElement)) return;\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst htmlCanvas = this.canvas as HTMLCanvasElement;\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = htmlCanvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\thtmlCanvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis.resizeTexture(HISTORY_TEXTURE_KEY, ...resolution);\n\t\t\tthis.resizeTexture(INTERMEDIATE_TEXTURE_KEY, ...resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate resizeTexture(name: string | symbol, width: number, height: number) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info || (info.width === width && info.height === height)) return;\n\n\t\tthis.gl.deleteTexture(info.texture);\n\t\tinfo.width = width;\n\t\tinfo.height = height;\n\t\tconst { texture } = this.createTexture(name, info);\n\t\tinfo.texture = texture;\n\t\tif (info.history) {\n\t\t\tinfo.history.writeIndex = 0;\n\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t}\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst gl = this.gl;\n\t\tconst type = textureInfo.options?.type ?? gl.UNSIGNED_BYTE;\n\t\tconst size = textureInfo.width * textureInfo.height * 4;\n\t\tconst transparent =\n\t\t\ttype === gl.FLOAT\n\t\t\t\t? new Float32Array(size)\n\t\t\t\t: type === gl.HALF_FLOAT\n\t\t\t\t? new Uint16Array(size)\n\t\t\t\t: new Uint8Array(size);\n\t\tgl.activeTexture(gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tgl.texSubImage3D(\n\t\t\t\tgl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\ttextureInfo.options?.format ?? gl.RGBA,\n\t\t\t\ttype,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tthis.log(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate log(...args: any[]) {\n\t\tif (this.debug) console.debug(...args);\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tthis.gl.useProgram(this.program);\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tthis.log(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history' | 'options'> & { unitIndex?: number }\n\t) {\n\t\tconst { width, height } = textureInfo;\n\t\tconst historyDepth = textureInfo.history?.depth ?? 0;\n\n\t\tconst texture = this.gl.createTexture();\n\t\tif (!texture) {\n\t\t\tthrow new Error('Failed to create texture');\n\t\t}\n\n\t\tlet unitIndex = textureInfo.unitIndex;\n\t\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\t\tconst { options } = textureInfo;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, options?.wrapS ?? this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, options?.wrapT ?? this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, options?.minFilter ?? this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, options?.magFilter ?? this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tconst type = options?.type ?? this.gl.UNSIGNED_BYTE;\n\t\t\tconst internalFormat =\n\t\t\t\toptions?.internalFormat ?? (type === this.gl.FLOAT ? this.gl.RGBA32F : this.gl.RGBA8);\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, internalFormat, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(\n\t\tname: string | symbol,\n\t\tsource: TextureSource,\n\t\toptions?: TextureOptions & { history?: number }\n\t) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${stringFrom(name)}' is already initialized.`);\n\t\t}\n\n\t\tconst { history: historyDepth = 0, ...textureOptions } = options ?? {};\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history' | 'options'> = {\n\t\t\twidth,\n\t\t\theight,\n\t\t\toptions: textureOptions,\n\t\t};\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: TextureOptions & { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: { skipHistoryWrite?: boolean }) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t}\n\n\tprivate updateTexture(\n\t\tname: string | symbol,\n\t\tsource: UpdateTextureSource,\n\t\toptions?: { skipHistoryWrite?: boolean }\n\t) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\tif (source instanceof WebGLTexture) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, source);\n\t\t\treturn;\n\t\t}\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) return;\n\n\t\tconst isPartial = 'isPartial' in source && source.isPartial;\n\t\tif (!isPartial) {\n\t\t\tthis.resizeTexture(name, width, height);\n\t\t}\n\n\t\t// UNPACK_FLIP_Y_WEBGL only works for DOM element sources, not typed arrays.\n\t\tconst isTypedArray = 'data' in source && source.data;\n\t\tconst shouldFlipY = !isTypedArray && !info.options?.preserveY;\n\t\tconst previousFlipY = this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);\n\n\t\tif (info.history) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (!options?.skipHistoryWrite) {\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tinfo.options?.format ?? this.gl.RGBA,\n\t\t\t\t\tinfo.options?.type ?? this.gl.UNSIGNED_BYTE,\n\t\t\t\t\t((source as PartialCustomTexture).data ?? (source as Exclude<TextureSource, CustomTexture>)) as any\n\t\t\t\t);\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\n\t\t\tconst format = info.options?.format ?? this.gl.RGBA;\n\t\t\tconst type = info.options?.type ?? this.gl.UNSIGNED_BYTE;\n\n\t\t\tif (isPartial) {\n\t\t\t\tthis.gl.texSubImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tsource.x ?? 0,\n\t\t\t\t\tsource.y ?? 0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tformat,\n\t\t\t\t\ttype,\n\t\t\t\t\tsource.data\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst internalFormat =\n\t\t\t\t\tinfo.options?.internalFormat ??\n\t\t\t\t\t(isTypedArray ? (type === this.gl.FLOAT ? this.gl.RGBA32F : this.gl.RGBA8) : this.gl.RGBA);\n\t\t\t\tthis.gl.texImage2D(\n\t\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t\t0,\n\t\t\t\t\tinternalFormat,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t0,\n\t\t\t\t\tformat,\n\t\t\t\t\ttype,\n\t\t\t\t\t((source as PartialCustomTexture).data ?? (source as Exclude<TextureSource, CustomTexture>)) as any\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\t\t}\n\t}\n\n\tdraw(options?: StepOptions) {\n\t\tconst gl = this.gl;\n\t\tconst w = gl.drawingBufferWidth;\n\t\tconst h = gl.drawingBufferHeight;\n\t\tconst historyInfo = this.textures.get(HISTORY_TEXTURE_KEY);\n\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY);\n\t\tconst shouldStoreHistory = historyInfo && !options?.skipHistoryWrite;\n\n\t\tif (shouldStoreHistory) {\n\t\t\t// Render to intermediate texture to avoid feedback loop with history texture\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.intermediateFbo);\n\t\t\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, intermediateInfo!.texture, 0);\n\t\t}\n\n\t\tgl.useProgram(this.program);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.viewport(0, 0, w, h);\n\t\tif (!options?.skipClear) gl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\tif (shouldStoreHistory) {\n\t\t\t// Copy to history layer\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, historyInfo.texture);\n\t\t\tgl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, historyInfo.history!.writeIndex, 0, 0, w, h);\n\n\t\t\t// Blit to screen\n\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\t\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n\t\t\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t}\n\t}\n\n\tstep(time: number, options?: StepOptions) {\n\t\tconst updates: Record<string, number> = {};\n\t\tif (this.uniforms.has('u_time')) updates.u_time = time;\n\t\tif (this.uniforms.has('u_frame')) updates.u_frame = this.frame;\n\t\tthis.updateUniforms(updates);\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\n\t\tthis.draw(options);\n\n\t\tconst historyInfo = this.textures.get(HISTORY_TEXTURE_KEY);\n\t\tif (historyInfo && !options?.skipHistoryWrite) {\n\t\t\tconst { writeIndex, depth } = historyInfo.history!;\n\t\t\tthis.updateUniforms({ [`${stringFrom(HISTORY_TEXTURE_KEY)}FrameOffset`]: writeIndex });\n\t\t\thistoryInfo.history!.writeIndex = (writeIndex + 1) % depth;\n\t\t}\n\n\t\tthis.hooks.get('afterStep')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(\n\t\tonStepComplete?: (time: number, frame: number) => void,\n\t\tsetStepOptions?: (time: number, frame: number) => StepOptions | void\n\t) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tconst options = setStepOptions?.(time, this.frame) ?? undefined;\n\t\t\tthis.step(time, options);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tonStepComplete?.(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t\t});\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tif (this.intermediateFbo) {\n\t\t\tthis.gl.deleteFramebuffer(this.intermediateFbo);\n\t\t\tthis.intermediateFbo = null;\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas && this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["index_exports","__export","index_default","__toCommonJS","DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","INTERMEDIATE_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","stringFrom","name","ShaderPad","fragmentShaderSrc","canvas","plugins","history","debug","textureOptions","htmlCanvas","internalFormat","type","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","hook","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","textureInfo","gl","size","transparent","layer","value","options","arrayLength","location","probeValue","length","error","args","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","isPartial","isTypedArray","shouldFlipY","previousFlipY","frameOffsetUniformName","format","w","h","historyInfo","intermediateInfo","shouldStoreHistory","time","writeIndex","depth","onStepComplete","setStepOptions","loop"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{a}from"./chunk-RKULNJXI.mjs";export{a as default};
1
+ import{a}from"./chunk-CRUQQQ46.mjs";export{a as default};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -9,6 +9,7 @@ interface FacePluginOptions {
9
9
  minTrackingConfidence?: number;
10
10
  outputFaceBlendshapes?: boolean;
11
11
  outputFacialTransformationMatrixes?: boolean;
12
+ onReady?: () => void;
12
13
  onResults?: (results: FaceLandmarkerResult) => void;
13
14
  }
14
15
  declare function face(config: {
@@ -9,6 +9,7 @@ interface FacePluginOptions {
9
9
  minTrackingConfidence?: number;
10
10
  outputFaceBlendshapes?: boolean;
11
11
  outputFacialTransformationMatrixes?: boolean;
12
+ onReady?: () => void;
12
13
  onResults?: (results: FaceLandmarkerResult) => void;
13
14
  }
14
15
  declare function face(config: {
@@ -1,56 +1,62 @@
1
- "use strict";var ae=Object.create;var g=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ce=Object.getPrototypeOf,ie=Object.prototype.hasOwnProperty;var se=(r,c)=>{for(var i in c)g(r,i,{get:c[i],enumerable:!0})},P=(r,c,i,O)=>{if(c&&typeof c=="object"||typeof c=="function")for(let s of re(c))!ie.call(r,s)&&s!==i&&g(r,s,{get:()=>c[s],enumerable:!(O=oe(c,s))||O.enumerable});return r};var le=(r,c,i)=>(i=r!=null?ae(ce(r)):{},P(c||!r||!r.__esModule?g(i,"default",{value:r,enumerable:!0}):i,r)),ue=r=>P(g({},"__esModule",{value:!0}),r);var de={};se(de,{default:()=>_e});module.exports=ue(de);var k=478,Ee=2,m=k+Ee,N=512,W=[336,296,334,293,300,276,283,282,295,285],V=[362,398,384,385,386,387,388,466,263,249,390,373,374,380,381,382],z=[70,63,105,66,107,55,65,52,53,46],j=[33,246,161,160,159,158,157,173,133,155,154,153,145,144,163,7],X=[61,185,40,39,37,0,267,269,270,409,291,375,321,405,314,17,84,181,91,146],G=[78,191,80,81,82,13,312,311,310,415,308,324,318,402,317,14,87,178,88,95],me=Array.from({length:k},(r,c)=>c),v={LEFT_EYEBROW:W,LEFT_EYE:V,LEFT_EYE_CENTER:473,RIGHT_EYEBROW:z,RIGHT_EYE:j,RIGHT_EYE_CENTER:468,NOSE_TIP:4,OUTER_MOUTH:X,INNER_MOUTH:G,FACE_CENTER:k,MOUTH_CENTER:k+1},q=["BACKGROUND","LEFT_EYEBROW","RIGHT_EYEBROW","LEFT_EYE","RIGHT_EYE","OUTER_MOUTH","INNER_MOUTH"],Z=q.length-1,A=Object.fromEntries(q.map((r,c)=>[r,c/Z])),K=.5/Z;function fe(r){let{textureName:c,options:i}=r,O="https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task";return function(s,J){let{injectGLSL:Q,gl:h}=J,F=null,y=null,b=-1,L="VIDEO",H=new Map,D=i?.maxFaces??1,S=0,o=null,U=new OffscreenCanvas(1,1),f=document.createElement("canvas"),u=f.getContext("2d"),Y=null,w=null;async function ee(){try{let{FilesetResolver:t,FaceLandmarker:e}=await import("@mediapipe/tasks-vision");y=await t.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"),F=await e.createFromOptions(y,{baseOptions:{modelAssetPath:i?.modelPath||O,delegate:"GPU"},canvas:U,runningMode:L,numFaces:i?.maxFaces??1,minFaceDetectionConfidence:i?.minFaceDetectionConfidence??.5,minFacePresenceConfidence:i?.minFacePresenceConfidence??.5,minTrackingConfidence:i?.minTrackingConfidence??.5,outputFaceBlendshapes:i?.outputFaceBlendshapes??!1,outputFacialTransformationMatrixes:i?.outputFacialTransformationMatrixes??!1}),Y=e.FACE_LANDMARKS_TESSELATION.map(({start:l})=>l),w=e.FACE_LANDMARKS_FACE_OVAL.map(({start:l})=>l)}catch(t){throw console.error("[Face Plugin] Failed to initialize:",t),t}}function $(t,e,l){let n=1/0,a=-1/0,d=1/0,T=-1/0,x=0,p=0;for(let C of l){let E=(e*m+C)*4,I=t[E],M=t[E+1];n=Math.min(n,I),a=Math.max(a,I),d=Math.min(d,M),T=Math.max(T,M),x+=t[E+2],p+=t[E+3]}return[(n+a)/2,(d+T)/2,x/l.length,p/l.length]}function _(t,e,l,n,a){if(!o)return;let{width:d,height:T}=f;u.fillStyle=`rgba(${l}, ${n}, ${a}, 255)`,u.beginPath();let x=(t*m+e[0])*4;u.moveTo(o[x]*d,o[x+1]*T);for(let p=1;p<e.length;++p){let C=(t*m+e[p])*4;u.lineTo(o[C]*d,o[C+1]*T)}u.closePath(),u.fill()}function te(t){if(!o||!Y||!w)return;let{width:e,height:l}=f;u.clearRect(0,0,e,l),u.save(),u.globalCompositeOperation="lighten";for(let n=0;n<t;++n){let a=Math.round((n+1)/D*255);_(n,Y,0,128,a),_(n,w,0,255,a),_(n,W,Math.round(A.LEFT_EYEBROW*255),0,a),_(n,z,Math.round(A.RIGHT_EYEBROW*255),0,a),_(n,V,Math.round(A.LEFT_EYE*255),0,a),_(n,j,Math.round(A.RIGHT_EYE*255),0,a),_(n,X,Math.round(A.OUTER_MOUTH*255),0,a),_(n,G,Math.round(A.INNER_MOUTH*255),0,a)}u.restore(),s.updateTextures({u_faceMask:f})}function ne(t){if(!o)return;let e=t.length,l=e*m;for(let a=0;a<e;++a){let d=t[a];for(let E=0;E<k;++E){let I=d[E],M=(a*m+E)*4;o[M]=I.x,o[M+1]=1-I.y,o[M+2]=I.z??0,o[M+3]=I.visibility??1}let T=$(o,a,me),x=(a*m+v.FACE_CENTER)*4;o.set(T,x);let p=$(o,a,G),C=(a*m+v.MOUTH_CENTER)*4;o.set(p,C)}let n=Math.ceil(l/N);s.updateTextures({u_faceLandmarksTex:{data:o,width:N,height:n,isPartial:!0}})}function B(t){if(!t.faceLandmarks||!o)return;f.width=U.width,f.height=U.height;let e=t.faceLandmarks.length;ne(t.faceLandmarks),te(e),s.updateUniforms({u_nFaces:e}),i?.onResults?.(t)}s.registerHook("init",async()=>{s.initializeTexture("u_faceMask",f,{preserveY:!0,minFilter:h.NEAREST,magFilter:h.NEAREST}),s.initializeUniform("u_maxFaces","int",D),s.initializeUniform("u_nFaces","int",0);let t=D*m;S=Math.ceil(t/N),o=new Float32Array(N*S*4),s.initializeTexture("u_faceLandmarksTex",{data:o,width:N,height:S},{internalFormat:h.RGBA32F,type:h.FLOAT,minFilter:h.NEAREST,magFilter:h.NEAREST}),await ee()}),s.registerHook("updateTextures",async t=>{let e=t[c];if(!(!e||(H.get(c)!==e&&(b=-1),H.set(c,e),!F)))try{let n=e instanceof HTMLVideoElement?"VIDEO":"IMAGE";if(L!==n&&(L=n,await F.setOptions({runningMode:L})),e instanceof HTMLVideoElement){if(e.videoWidth===0||e.videoHeight===0||e.readyState<2)return;e.currentTime!==b&&(b=e.currentTime,B(F.detectForVideo(e,performance.now())))}else if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement){if(e.width===0||e.height===0)return;B(F.detect(e))}}catch(n){console.error("[Face Plugin] Detection error:",n)}}),s.registerHook("destroy",()=>{F?.close(),F=null,y=null,H.clear(),f.remove(),o=null});let R=(t,e=t)=>`vec4 mask = texture(u_faceMask, pos);
2
- if (mask.a < 0.9) return vec2(0.0, -1.0);
1
+ "use strict";var se=Object.create;var S=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var ue=Object.getPrototypeOf,fe=Object.prototype.hasOwnProperty;var me=(o,i)=>{for(var r in i)S(o,r,{get:i[r],enumerable:!0})},z=(o,i,r,k)=>{if(i&&typeof i=="object"||typeof i=="function")for(let E of le(i))!fe.call(o,E)&&E!==r&&S(o,E,{get:()=>i[E],enumerable:!(k=Ee(i,E))||k.enumerable});return o};var _e=(o,i,r)=>(r=o!=null?se(ue(o)):{},z(i||!o||!o.__esModule?S(r,"default",{value:o,enumerable:!0}):r,o)),Te=o=>z(S({},"__esModule",{value:!0}),o);var Fe={};me(Fe,{default:()=>pe});module.exports=Te(Fe);var M=478,de=2,R=M+de,I=512,j=[336,296,334,293,300,276,283,282,295,285],q=[362,398,384,385,386,387,388,466,263,249,390,373,374,380,381,382],Z=[70,63,105,66,107,55,65,52,53,46],J=[33,246,161,160,159,158,157,173,133,155,154,153,145,144,163,7],Q=[61,185,40,39,37,0,267,269,270,409,291,375,321,405,314,17,84,181,91,146],G=[78,191,80,81,82,13,312,311,310,415,308,324,318,402,317,14,87,178,88,95],Re=Array.from({length:M},(o,i)=>i),O={LEFT_EYEBROW:j,LEFT_EYE:q,LEFT_EYE_CENTER:473,RIGHT_EYEBROW:Z,RIGHT_EYE:J,RIGHT_EYE_CENTER:468,NOSE_TIP:4,OUTER_MOUTH:Q,INNER_MOUTH:G,FACE_CENTER:M,MOUTH_CENTER:M+1},ee=["BACKGROUND","LEFT_EYEBROW","RIGHT_EYEBROW","LEFT_EYE","RIGHT_EYE","OUTER_MOUTH","INNER_MOUTH"],te=ee.length-1,A=Object.fromEntries(ee.map((o,i)=>[o,i/te])),X=.5/te;function v(o){let i=[];for(let r=1;r<o.length-1;++r)i.push(o[0],o[r],o[r+1]);return i}function Ae(o){let{textureName:i,options:r}=o,k="https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task";return function(E,ne){let{injectGLSL:ae,gl:g}=ne,p=null,b=null,H=-1,C="VIDEO",y=new Map,U=r?.maxFaces??1,D=0,s=null,Y=new OffscreenCanvas(1,1),F=new OffscreenCanvas(1,1),t=null,f=null,w=null,B=null,l={LEFT_EYEBROW:v(j),RIGHT_EYEBROW:v(Z),LEFT_EYE:v(q),RIGHT_EYE:v(J),OUTER_MOUTH:v(Q),INNER_MOUTH:v(G),TESSELATION:[],OVAL:[]};function oe(){if(t=F.getContext("webgl2",{antialias:!1,preserveDrawingBuffer:!0}),!t)throw new Error("Failed to get WebGL2 context for mask");let e=t.createShader(t.VERTEX_SHADER);t.shaderSource(e,`#version 300 es
2
+ in vec2 a_pos;
3
+ void main() {
4
+ gl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0);
5
+ }`),t.compileShader(e);let n=t.createShader(t.FRAGMENT_SHADER);t.shaderSource(n,`#version 300 es
6
+ precision mediump float;
7
+ uniform vec4 u_color;
8
+ out vec4 outColor;
9
+ void main() { outColor = u_color; }`),t.compileShader(n),f=t.createProgram(),t.attachShader(f,e),t.attachShader(f,n),t.linkProgram(f),t.deleteShader(e),t.deleteShader(n),w=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,w);let a=t.getAttribLocation(f,"a_pos");t.enableVertexAttribArray(a),t.vertexAttribPointer(a,2,t.FLOAT,!1,0,0),B=t.getUniformLocation(f,"u_color"),t.useProgram(f),t.enable(t.BLEND),t.blendEquation(t.MAX)}function d(e,n,a,m,c){if(!t||!s||e.length===0)return;let _=new Float32Array(e.length*2);for(let u=0;u<e.length;++u){let N=(n*R+e[u])*4;_[u*2]=s[N],_[u*2+1]=s[N+1]}t.bufferData(t.ARRAY_BUFFER,_,t.DYNAMIC_DRAW),t.uniform4f(B,a,m,c,1),t.drawArrays(t.TRIANGLES,0,e.length)}async function re(){try{let{FilesetResolver:e,FaceLandmarker:n}=await import("@mediapipe/tasks-vision");b=await e.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"),p=await n.createFromOptions(b,{baseOptions:{modelAssetPath:r?.modelPath||k,delegate:"GPU"},canvas:Y,runningMode:C,numFaces:r?.maxFaces??1,minFaceDetectionConfidence:r?.minFaceDetectionConfidence??.5,minFacePresenceConfidence:r?.minFacePresenceConfidence??.5,minTrackingConfidence:r?.minTrackingConfidence??.5,outputFaceBlendshapes:r?.outputFaceBlendshapes??!1,outputFacialTransformationMatrixes:r?.outputFacialTransformationMatrixes??!1});let a=n.FACE_LANDMARKS_TESSELATION;l.TESSELATION=[];for(let c=0;c<a.length-2;c+=3)l.TESSELATION.push(a[c].start,a[c+1].start,a[c+2].start);let m=n.FACE_LANDMARKS_FACE_OVAL.map(({start:c})=>c);l.OVAL=v(m),oe()}catch(e){throw console.error("[Face Plugin] Failed to initialize:",e),e}}function W(e,n,a){let m=1/0,c=-1/0,_=1/0,u=-1/0,N=0,x=0;for(let h of a){let T=(n*R+h)*4,$=e[T],K=e[T+1];m=Math.min(m,$),c=Math.max(c,$),_=Math.min(_,K),u=Math.max(u,K),N+=e[T+2],x+=e[T+3]}return[(m+c)/2,(_+u)/2,N/a.length,x/a.length]}function ie(e){if(!s)return;let n=e.length,a=n*R;for(let c=0;c<n;++c){let _=e[c];for(let x=0;x<M;++x){let h=_[x],T=(c*R+x)*4;s[T]=h.x,s[T+1]=1-h.y,s[T+2]=h.z??0,s[T+3]=h.visibility??1}let u=W(s,c,Re);s.set(u,(c*R+O.FACE_CENTER)*4);let N=W(s,c,G);s.set(N,(c*R+O.MOUTH_CENTER)*4)}let m=Math.ceil(a/I);E.updateTextures({u_faceLandmarksTex:{data:s,width:I,height:m,isPartial:!0}})}function ce(e){if(!(!t||!s)){F.width=Y.width,F.height=Y.height,t.viewport(0,0,F.width,F.height),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT);for(let n=0;n<e;++n){let a=(n+1)/U;d(l.TESSELATION,n,0,.5,a),d(l.OVAL,n,0,1,a),d(l.LEFT_EYEBROW,n,A.LEFT_EYEBROW,0,a),d(l.RIGHT_EYEBROW,n,A.RIGHT_EYEBROW,0,a),d(l.LEFT_EYE,n,A.LEFT_EYE,0,a),d(l.RIGHT_EYE,n,A.RIGHT_EYE,0,a),d(l.OUTER_MOUTH,n,A.OUTER_MOUTH,0,a),d(l.INNER_MOUTH,n,A.INNER_MOUTH,0,a)}E.updateTextures({u_faceMask:F})}}function P(e){if(!e.faceLandmarks||!s)return;let n=e.faceLandmarks.length;ie(e.faceLandmarks),ce(n),E.updateUniforms({u_nFaces:n}),r?.onResults?.(e)}async function V(e){if(y.get(i)!==e&&(H=-1),y.set(i,e),!!p)try{let a=e instanceof HTMLVideoElement?"VIDEO":"IMAGE";if(C!==a&&(C=a,await p.setOptions({runningMode:C})),e instanceof HTMLVideoElement){if(e.videoWidth===0||e.videoHeight===0||e.readyState<2)return;e.currentTime!==H&&(H=e.currentTime,P(p.detectForVideo(e,performance.now())))}else if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement){if(e.width===0||e.height===0)return;P(p.detect(e))}}catch(a){console.error("[Face Plugin] Detection error:",a)}}E.registerHook("init",async()=>{E.initializeTexture("u_faceMask",F,{minFilter:g.NEAREST,magFilter:g.NEAREST}),E.initializeUniform("u_maxFaces","int",U),E.initializeUniform("u_nFaces","int",0);let e=U*R;D=Math.ceil(e/I),s=new Float32Array(I*D*4),E.initializeTexture("u_faceLandmarksTex",{data:s,width:I,height:D},{internalFormat:g.RGBA32F,type:g.FLOAT,minFilter:g.NEAREST,magFilter:g.NEAREST}),await re(),r?.onReady?.()}),E.registerHook("initializeTexture",(e,n)=>{e===i&&V(n)}),E.registerHook("updateTextures",e=>{let n=e[i];n&&V(n)}),E.registerHook("destroy",()=>{p?.close(),p=null,t&&f&&(t.deleteProgram(f),t.deleteBuffer(w)),t=null,f=null,b=null,y.clear(),s=null});let L=(e,n=e)=>`vec4 mask = texture(u_faceMask, pos);
3
10
  float faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;
4
- return (mask.r > ${(A[t]-K).toFixed(4)} && mask.r < ${(A[e]+K).toFixed(4)}) ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`;Q(`
11
+ return (mask.r > ${(A[e]-X).toFixed(4)} && mask.r < ${(A[n]+X).toFixed(4)}) ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`;ae(`
5
12
  uniform int u_maxFaces;
6
13
  uniform int u_nFaces;
7
14
  uniform sampler2D u_faceLandmarksTex;
8
15
  uniform sampler2D u_faceMask;
9
16
 
10
- #define FACE_LANDMARK_L_EYE_CENTER ${v.LEFT_EYE_CENTER}
11
- #define FACE_LANDMARK_R_EYE_CENTER ${v.RIGHT_EYE_CENTER}
12
- #define FACE_LANDMARK_NOSE_TIP ${v.NOSE_TIP}
13
- #define FACE_LANDMARK_FACE_CENTER ${v.FACE_CENTER}
14
- #define FACE_LANDMARK_MOUTH_CENTER ${v.MOUTH_CENTER}
17
+ #define FACE_LANDMARK_L_EYE_CENTER ${O.LEFT_EYE_CENTER}
18
+ #define FACE_LANDMARK_R_EYE_CENTER ${O.RIGHT_EYE_CENTER}
19
+ #define FACE_LANDMARK_NOSE_TIP ${O.NOSE_TIP}
20
+ #define FACE_LANDMARK_FACE_CENTER ${O.FACE_CENTER}
21
+ #define FACE_LANDMARK_MOUTH_CENTER ${O.MOUTH_CENTER}
15
22
 
16
23
  vec4 faceLandmark(int faceIndex, int landmarkIndex) {
17
- int i = faceIndex * ${m} + landmarkIndex;
18
- int x = i % ${N};
19
- int y = i / ${N};
24
+ int i = faceIndex * ${R} + landmarkIndex;
25
+ int x = i % ${I};
26
+ int y = i / ${I};
20
27
  return texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);
21
28
  }
22
29
 
23
30
  vec2 leftEyebrowAt(vec2 pos) {
24
- ${R("LEFT_EYEBROW")}
31
+ ${L("LEFT_EYEBROW")}
25
32
  }
26
33
 
27
34
  vec2 rightEyebrowAt(vec2 pos) {
28
- ${R("RIGHT_EYEBROW")}
35
+ ${L("RIGHT_EYEBROW")}
29
36
  }
30
37
 
31
38
  vec2 leftEyeAt(vec2 pos) {
32
- ${R("LEFT_EYE")}
39
+ ${L("LEFT_EYE")}
33
40
  }
34
41
 
35
42
  vec2 rightEyeAt(vec2 pos) {
36
- ${R("RIGHT_EYE")}
43
+ ${L("RIGHT_EYE")}
37
44
  }
38
45
 
39
46
  vec2 lipsAt(vec2 pos) {
40
- ${R("OUTER_MOUTH")}
47
+ ${L("OUTER_MOUTH")}
41
48
  }
42
49
 
43
50
  vec2 outerMouthAt(vec2 pos) {
44
- ${R("OUTER_MOUTH","INNER_MOUTH")}
51
+ ${L("OUTER_MOUTH","INNER_MOUTH")}
45
52
  }
46
53
 
47
54
  vec2 innerMouthAt(vec2 pos) {
48
- ${R("INNER_MOUTH")}
55
+ ${L("INNER_MOUTH")}
49
56
  }
50
57
 
51
58
  vec2 faceOvalAt(vec2 pos) {
52
59
  vec4 mask = texture(u_faceMask, pos);
53
- if (mask.a < 0.9) return vec2(0.0, -1.0);
54
60
  float faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;
55
61
  return mask.g > 0.75 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);
56
62
  }
@@ -58,7 +64,6 @@ vec2 faceOvalAt(vec2 pos) {
58
64
  // Includes face mesh and oval.
59
65
  vec2 faceAt(vec2 pos) {
60
66
  vec4 mask = texture(u_faceMask, pos);
61
- if (mask.a < 0.9) return vec2(0.0, -1.0);
62
67
  float faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;
63
68
  return mask.g > 0.25 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);
64
69
  }
@@ -78,5 +83,5 @@ float inEye(vec2 pos) { return eyeAt(pos).x; }
78
83
  float inOuterMouth(vec2 pos) { return outerMouthAt(pos).x; }
79
84
  float inInnerMouth(vec2 pos) { return innerMouthAt(pos).x; }
80
85
  float inLips(vec2 pos) { return lipsAt(pos).x; }
81
- float inFace(vec2 pos) { return faceAt(pos).x; }`)}}var _e=fe;
86
+ float inFace(vec2 pos) { return faceAt(pos).x; }`)}}var pe=Ae;
82
87
  //# sourceMappingURL=face.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/face.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '../index';\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\tonResults?: (results: FaceLandmarkerResult) => void;\n}\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;\n\nconst LEFT_EYEBROW_INDICES = [336, 296, 334, 293, 300, 276, 283, 282, 295, 285] as const;\nconst LEFT_EYE_INDICES = [362, 398, 384, 385, 386, 387, 388, 466, 263, 249, 390, 373, 374, 380, 381, 382] as const;\nconst RIGHT_EYEBROW_INDICES = [70, 63, 105, 66, 107, 55, 65, 52, 53, 46] as const;\nconst RIGHT_EYE_INDICES = [33, 246, 161, 160, 159, 158, 157, 173, 133, 155, 154, 153, 145, 144, 163, 7] as const;\nconst OUTER_MOUTH_INDICES = [\n\t61, 185, 40, 39, 37, 0, 267, 269, 270, 409, 291, 375, 321, 405, 314, 17, 84, 181, 91, 146,\n] as const;\nconst INNER_MOUTH_INDICES = [\n\t78, 191, 80, 81, 82, 13, 312, 311, 310, 415, 308, 324, 318, 402, 317, 14, 87, 178, 88, 95,\n] as const;\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst LANDMARK_INDICES = {\n\tLEFT_EYEBROW: LEFT_EYEBROW_INDICES,\n\tLEFT_EYE: LEFT_EYE_INDICES,\n\tLEFT_EYE_CENTER: 473,\n\tRIGHT_EYEBROW: RIGHT_EYEBROW_INDICES,\n\tRIGHT_EYE: RIGHT_EYE_INDICES,\n\tRIGHT_EYE_CENTER: 468,\n\tNOSE_TIP: 4,\n\tOUTER_MOUTH: OUTER_MOUTH_INDICES,\n\tINNER_MOUTH: INNER_MOUTH_INDICES,\n\t// Custom landmarks.\n\tFACE_CENTER: STANDARD_LANDMARK_COUNT,\n\tMOUTH_CENTER: STANDARD_LANDMARK_COUNT + 1,\n};\n\n// Face region types for R channel encoding (evenly spaced 0-1).\nconst FACE_REGION_NAMES = [\n\t'BACKGROUND',\n\t'LEFT_EYEBROW',\n\t'RIGHT_EYEBROW',\n\t'LEFT_EYE',\n\t'RIGHT_EYE',\n\t'OUTER_MOUTH',\n\t'INNER_MOUTH',\n] as const;\nconst nFaceRegions = FACE_REGION_NAMES.length - 1;\nconst FACE_REGION = Object.fromEntries(FACE_REGION_NAMES.map((name, i) => [name, i / nFaceRegions])) as Record<\n\t(typeof FACE_REGION_NAMES)[number],\n\tnumber\n>;\nconst HALF_GAP = 0.5 / nFaceRegions;\n\nfunction face(config: { textureName: string; options?: FacePluginOptions }) {\n\tconst { textureName, options } = config;\n\tconst defaultModelPath =\n\t\t'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task';\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL, gl } = context;\n\n\t\tlet faceLandmarker: FaceLandmarker | null = null;\n\t\tlet vision: any = null;\n\t\tlet lastVideoTime = -1;\n\t\tlet runningMode: 'IMAGE' | 'VIDEO' = 'VIDEO';\n\t\tconst textureSources = new Map<string, TextureSource>();\n\t\tconst maxFaces = options?.maxFaces ?? 1;\n\n\t\tlet landmarksTextureHeight = 0;\n\t\tlet landmarksDataArray: Float32Array | null = null;\n\n\t\tconst mediaPipeCanvas = new OffscreenCanvas(1, 1);\n\t\tconst faceMaskCanvas = document.createElement('canvas');\n\t\tconst faceMaskCtx = faceMaskCanvas.getContext('2d')!;\n\n\t\tlet faceTesselationIndices: number[] | null = null;\n\t\tlet faceOvalIndices: number[] | null = null;\n\t\tasync function initializeFaceLandmarker() {\n\t\t\ttry {\n\t\t\t\tconst { FilesetResolver, FaceLandmarker } = await import('@mediapipe/tasks-vision');\n\t\t\t\tvision = await FilesetResolver.forVisionTasks(\n\t\t\t\t\t'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm'\n\t\t\t\t);\n\n\t\t\t\tfaceLandmarker = await FaceLandmarker.createFromOptions(vision, {\n\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\tmodelAssetPath: options?.modelPath || defaultModelPath,\n\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t},\n\t\t\t\t\tcanvas: mediaPipeCanvas,\n\t\t\t\t\trunningMode: runningMode,\n\t\t\t\t\tnumFaces: options?.maxFaces ?? 1,\n\t\t\t\t\tminFaceDetectionConfidence: options?.minFaceDetectionConfidence ?? 0.5,\n\t\t\t\t\tminFacePresenceConfidence: options?.minFacePresenceConfidence ?? 0.5,\n\t\t\t\t\tminTrackingConfidence: options?.minTrackingConfidence ?? 0.5,\n\t\t\t\t\toutputFaceBlendshapes: options?.outputFaceBlendshapes ?? false,\n\t\t\t\t\toutputFacialTransformationMatrixes: options?.outputFacialTransformationMatrixes ?? false,\n\t\t\t\t});\n\n\t\t\t\tfaceTesselationIndices = FaceLandmarker.FACE_LANDMARKS_TESSELATION.map(({ start }) => start);\n\t\t\t\tfaceOvalIndices = FaceLandmarker.FACE_LANDMARKS_FACE_OVAL.map(({ start }) => start);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Face Plugin] Failed to initialize:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tfunction calculateBoundingBoxCenter(\n\t\t\tdata: Float32Array,\n\t\t\tfaceIdx: number,\n\t\t\tindices: readonly number[] | number[]\n\t\t): [number, number, number, number] {\n\t\t\tlet minX = Infinity,\n\t\t\t\tmaxX = -Infinity,\n\t\t\t\tminY = Infinity,\n\t\t\t\tmaxY = -Infinity,\n\t\t\t\tavgZ = 0,\n\t\t\t\tavgVis = 0;\n\n\t\t\tfor (const idx of indices) {\n\t\t\t\tconst i = (faceIdx * LANDMARK_COUNT + idx) * 4;\n\t\t\t\tconst x = data[i],\n\t\t\t\t\ty = data[i + 1];\n\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t\tavgZ += data[i + 2];\n\t\t\t\tavgVis += data[i + 3];\n\t\t\t}\n\t\t\treturn [(minX + maxX) / 2, (minY + maxY) / 2, avgZ / indices.length, avgVis / indices.length];\n\t\t}\n\n\t\tfunction fillRegion(faceIdx: number, indices: readonly number[] | number[], r: number, g: number, b: number) {\n\t\t\tif (!landmarksDataArray) return;\n\n\t\t\tconst { width, height } = faceMaskCanvas;\n\t\t\tfaceMaskCtx.fillStyle = `rgba(${r}, ${g}, ${b}, 255)`;\n\t\t\tfaceMaskCtx.beginPath();\n\t\t\tconst first = (faceIdx * LANDMARK_COUNT + indices[0]) * 4;\n\t\t\tfaceMaskCtx.moveTo(landmarksDataArray[first] * width, landmarksDataArray[first + 1] * height);\n\t\t\tfor (let i = 1; i < indices.length; ++i) {\n\t\t\t\tconst idx = (faceIdx * LANDMARK_COUNT + indices[i]) * 4;\n\t\t\t\tfaceMaskCtx.lineTo(landmarksDataArray[idx] * width, landmarksDataArray[idx + 1] * height);\n\t\t\t}\n\t\t\tfaceMaskCtx.closePath();\n\t\t\tfaceMaskCtx.fill();\n\t\t}\n\n\t\tfunction updateMaskTexture(nFaces: number) {\n\t\t\tif (!landmarksDataArray || !faceTesselationIndices || !faceOvalIndices) return;\n\n\t\t\tconst { width, height } = faceMaskCanvas;\n\t\t\tfaceMaskCtx.clearRect(0, 0, width, height);\n\n\t\t\tfaceMaskCtx.save();\n\t\t\tfaceMaskCtx.globalCompositeOperation = 'lighten';\n\n\t\t\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\t\t\tconst b = Math.round(((faceIdx + 1) / maxFaces) * 255);\n\n\t\t\t\t// G channel: face mesh (0.5) and oval (1.0)\n\t\t\t\tfillRegion(faceIdx, faceTesselationIndices, 0, 128, b);\n\t\t\t\tfillRegion(faceIdx, faceOvalIndices, 0, 255, b);\n\n\t\t\t\t// R channel: feature regions (drawn on top)\n\t\t\t\tfillRegion(faceIdx, LEFT_EYEBROW_INDICES, Math.round(FACE_REGION.LEFT_EYEBROW * 255), 0, b);\n\t\t\t\tfillRegion(faceIdx, RIGHT_EYEBROW_INDICES, Math.round(FACE_REGION.RIGHT_EYEBROW * 255), 0, b);\n\t\t\t\tfillRegion(faceIdx, LEFT_EYE_INDICES, Math.round(FACE_REGION.LEFT_EYE * 255), 0, b);\n\t\t\t\tfillRegion(faceIdx, RIGHT_EYE_INDICES, Math.round(FACE_REGION.RIGHT_EYE * 255), 0, b);\n\t\t\t\tfillRegion(faceIdx, OUTER_MOUTH_INDICES, Math.round(FACE_REGION.OUTER_MOUTH * 255), 0, b);\n\t\t\t\tfillRegion(faceIdx, INNER_MOUTH_INDICES, Math.round(FACE_REGION.INNER_MOUTH * 255), 0, b);\n\t\t\t}\n\n\t\t\tfaceMaskCtx.restore();\n\t\t\tshaderPad.updateTextures({ u_faceMask: faceMaskCanvas });\n\t\t}\n\n\t\tfunction updateLandmarksTexture(faces: NormalizedLandmark[][]) {\n\t\t\tif (!landmarksDataArray) return;\n\n\t\t\tconst nFaces = faces.length;\n\t\t\tconst totalLandmarks = nFaces * LANDMARK_COUNT;\n\n\t\t\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\t\t\tconst landmarks = faces[faceIdx];\n\t\t\t\tfor (let lmIdx = 0; lmIdx < STANDARD_LANDMARK_COUNT; ++lmIdx) {\n\t\t\t\t\tconst landmark = landmarks[lmIdx];\n\t\t\t\t\tconst dataIdx = (faceIdx * LANDMARK_COUNT + lmIdx) * 4;\n\t\t\t\t\tlandmarksDataArray[dataIdx] = landmark.x;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 1] = 1 - landmark.y;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 2] = landmark.z ?? 0;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 3] = landmark.visibility ?? 1;\n\t\t\t\t}\n\n\t\t\t\tconst faceCenter = calculateBoundingBoxCenter(landmarksDataArray, faceIdx, ALL_STANDARD_INDICES);\n\t\t\t\tconst faceCenterIdx = (faceIdx * LANDMARK_COUNT + LANDMARK_INDICES.FACE_CENTER) * 4;\n\t\t\t\tlandmarksDataArray.set(faceCenter, faceCenterIdx);\n\n\t\t\t\tconst mouthCenter = calculateBoundingBoxCenter(landmarksDataArray, faceIdx, INNER_MOUTH_INDICES);\n\t\t\t\tconst mouthCenterIdx = (faceIdx * LANDMARK_COUNT + LANDMARK_INDICES.MOUTH_CENTER) * 4;\n\t\t\t\tlandmarksDataArray.set(mouthCenter, mouthCenterIdx);\n\t\t\t}\n\n\t\t\tconst rowsToUpdate = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tshaderPad.updateTextures({\n\t\t\t\tu_faceLandmarksTex: {\n\t\t\t\t\tdata: landmarksDataArray,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: rowsToUpdate,\n\t\t\t\t\tisPartial: true,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tfunction processFaceResults(result: FaceLandmarkerResult) {\n\t\t\tif (!result.faceLandmarks || !landmarksDataArray) return;\n\n\t\t\tfaceMaskCanvas.width = mediaPipeCanvas.width;\n\t\t\tfaceMaskCanvas.height = mediaPipeCanvas.height;\n\n\t\t\tconst nFaces = result.faceLandmarks.length;\n\t\t\tupdateLandmarksTexture(result.faceLandmarks);\n\t\t\tupdateMaskTexture(nFaces);\n\t\t\tshaderPad.updateUniforms({ u_nFaces: nFaces });\n\n\t\t\toptions?.onResults?.(result);\n\t\t}\n\n\t\tshaderPad.registerHook('init', async () => {\n\t\t\tshaderPad.initializeTexture('u_faceMask', faceMaskCanvas, {\n\t\t\t\tpreserveY: true,\n\t\t\t\tminFilter: gl.NEAREST,\n\t\t\t\tmagFilter: gl.NEAREST,\n\t\t\t});\n\t\t\tshaderPad.initializeUniform('u_maxFaces', 'int', maxFaces);\n\t\t\tshaderPad.initializeUniform('u_nFaces', 'int', 0);\n\n\t\t\tconst totalLandmarks = maxFaces * LANDMARK_COUNT;\n\t\t\tlandmarksTextureHeight = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tlandmarksDataArray = new Float32Array(LANDMARKS_TEXTURE_WIDTH * landmarksTextureHeight * 4);\n\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{ data: landmarksDataArray, width: LANDMARKS_TEXTURE_WIDTH, height: landmarksTextureHeight },\n\t\t\t\t{ internalFormat: gl.RGBA32F, type: gl.FLOAT, minFilter: gl.NEAREST, magFilter: gl.NEAREST }\n\t\t\t);\n\n\t\t\tawait initializeFaceLandmarker();\n\t\t});\n\n\t\tshaderPad.registerHook('updateTextures', async (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (!source) return;\n\n\t\t\tconst previousSource = textureSources.get(textureName);\n\t\t\tif (previousSource !== source) lastVideoTime = -1;\n\t\t\ttextureSources.set(textureName, source);\n\t\t\tif (!faceLandmarker) return;\n\n\t\t\ttry {\n\t\t\t\tconst requiredMode = source instanceof HTMLVideoElement ? 'VIDEO' : 'IMAGE';\n\t\t\t\tif (runningMode !== requiredMode) {\n\t\t\t\t\trunningMode = requiredMode;\n\t\t\t\t\tawait faceLandmarker.setOptions({ runningMode });\n\t\t\t\t}\n\n\t\t\t\tif (source instanceof HTMLVideoElement) {\n\t\t\t\t\tif (source.videoWidth === 0 || source.videoHeight === 0 || source.readyState < 2) return;\n\t\t\t\t\tif (source.currentTime !== lastVideoTime) {\n\t\t\t\t\t\tlastVideoTime = source.currentTime;\n\t\t\t\t\t\tprocessFaceResults(faceLandmarker.detectForVideo(source, performance.now()));\n\t\t\t\t\t}\n\t\t\t\t} else if (source instanceof HTMLImageElement || source instanceof HTMLCanvasElement) {\n\t\t\t\t\tif (source.width === 0 || source.height === 0) return;\n\t\t\t\t\tprocessFaceResults(faceLandmarker.detect(source));\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Face Plugin] Detection error:', error);\n\t\t\t}\n\t\t});\n\n\t\tshaderPad.registerHook('destroy', () => {\n\t\t\tfaceLandmarker?.close();\n\t\t\tfaceLandmarker = null;\n\t\t\tvision = null;\n\t\t\ttextureSources.clear();\n\t\t\tfaceMaskCanvas.remove();\n\t\t\tlandmarksDataArray = null;\n\t\t});\n\n\t\tconst checkAt = (regionMin: keyof typeof FACE_REGION, regionMax: keyof typeof FACE_REGION = regionMin) =>\n\t\t\t`vec4 mask = texture(u_faceMask, pos);\n\tif (mask.a < 0.9) return vec2(0.0, -1.0);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn (mask.r > ${(FACE_REGION[regionMin] - HALF_GAP).toFixed(4)} && mask.r < ${(\n\t\t\t\tFACE_REGION[regionMax] + HALF_GAP\n\t\t\t).toFixed(4)}) ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`;\n\n\t\tinjectGLSL(`\nuniform int u_maxFaces;\nuniform int u_nFaces;\nuniform sampler2D u_faceLandmarksTex;\nuniform sampler2D u_faceMask;\n\n#define FACE_LANDMARK_L_EYE_CENTER ${LANDMARK_INDICES.LEFT_EYE_CENTER}\n#define FACE_LANDMARK_R_EYE_CENTER ${LANDMARK_INDICES.RIGHT_EYE_CENTER}\n#define FACE_LANDMARK_NOSE_TIP ${LANDMARK_INDICES.NOSE_TIP}\n#define FACE_LANDMARK_FACE_CENTER ${LANDMARK_INDICES.FACE_CENTER}\n#define FACE_LANDMARK_MOUTH_CENTER ${LANDMARK_INDICES.MOUTH_CENTER}\n\nvec4 faceLandmark(int faceIndex, int landmarkIndex) {\n\tint i = faceIndex * ${LANDMARK_COUNT} + landmarkIndex;\n\tint x = i % ${LANDMARKS_TEXTURE_WIDTH};\n\tint y = i / ${LANDMARKS_TEXTURE_WIDTH};\n\treturn texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);\n}\n\nvec2 leftEyebrowAt(vec2 pos) {\n\t${checkAt('LEFT_EYEBROW')}\n}\n\nvec2 rightEyebrowAt(vec2 pos) {\n\t${checkAt('RIGHT_EYEBROW')}\n}\n\nvec2 leftEyeAt(vec2 pos) {\n\t${checkAt('LEFT_EYE')}\n}\n\nvec2 rightEyeAt(vec2 pos) {\n\t${checkAt('RIGHT_EYE')}\n}\n\nvec2 lipsAt(vec2 pos) {\n\t${checkAt('OUTER_MOUTH')}\n}\n\nvec2 outerMouthAt(vec2 pos) {\n\t${checkAt('OUTER_MOUTH', 'INNER_MOUTH')}\n}\n\nvec2 innerMouthAt(vec2 pos) {\n\t${checkAt('INNER_MOUTH')}\n}\n\nvec2 faceOvalAt(vec2 pos) {\n\tvec4 mask = texture(u_faceMask, pos);\n\tif (mask.a < 0.9) return vec2(0.0, -1.0);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn mask.g > 0.75 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);\n}\n\n// Includes face mesh and oval.\nvec2 faceAt(vec2 pos) {\n\tvec4 mask = texture(u_faceMask, pos);\n\tif (mask.a < 0.9) return vec2(0.0, -1.0);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn mask.g > 0.25 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);\n}\n\nvec2 eyeAt(vec2 pos) {\n\tvec2 left = leftEyeAt(pos);\n\treturn left.x > 0.0 ? left : rightEyeAt(pos);\n}\n\nvec2 eyebrowAt(vec2 pos) {\n\tvec2 left = leftEyebrowAt(pos);\n\treturn left.x > 0.0 ? left : rightEyebrowAt(pos);\n}\n\nfloat inEyebrow(vec2 pos) { return eyebrowAt(pos).x; }\nfloat inEye(vec2 pos) { return eyeAt(pos).x; }\nfloat inOuterMouth(vec2 pos) { return outerMouthAt(pos).x; }\nfloat inInnerMouth(vec2 pos) { return innerMouthAt(pos).x; }\nfloat inLips(vec2 pos) { return lipsAt(pos).x; }\nfloat inFace(vec2 pos) { return faceAt(pos).x; }`);\n\t};\n}\n\nexport default face;\n"],"mappings":"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","names":["face_exports","__export","face_default","__toCommonJS","STANDARD_LANDMARK_COUNT","CUSTOM_LANDMARK_COUNT","LANDMARK_COUNT","LANDMARKS_TEXTURE_WIDTH","LEFT_EYEBROW_INDICES","LEFT_EYE_INDICES","RIGHT_EYEBROW_INDICES","RIGHT_EYE_INDICES","OUTER_MOUTH_INDICES","INNER_MOUTH_INDICES","ALL_STANDARD_INDICES","_","i","LANDMARK_INDICES","FACE_REGION_NAMES","nFaceRegions","FACE_REGION","name","HALF_GAP","face","config","textureName","options","defaultModelPath","shaderPad","context","injectGLSL","gl","faceLandmarker","vision","lastVideoTime","runningMode","textureSources","maxFaces","landmarksTextureHeight","landmarksDataArray","mediaPipeCanvas","faceMaskCanvas","faceMaskCtx","faceTesselationIndices","faceOvalIndices","initializeFaceLandmarker","FilesetResolver","FaceLandmarker","start","error","calculateBoundingBoxCenter","data","faceIdx","indices","minX","maxX","minY","maxY","avgZ","avgVis","idx","x","y","fillRegion","r","g","b","width","height","first","updateMaskTexture","nFaces","updateLandmarksTexture","faces","totalLandmarks","landmarks","lmIdx","landmark","dataIdx","faceCenter","faceCenterIdx","mouthCenter","mouthCenterIdx","rowsToUpdate","processFaceResults","result","updates","source","requiredMode","checkAt","regionMin","regionMax"]}
1
+ {"version":3,"sources":["../../src/plugins/face.ts"],"sourcesContent":["import ShaderPad, { PluginContext, TextureSource } from '../index';\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\tonReady?: () => void;\n\tonResults?: (results: FaceLandmarkerResult) => void;\n}\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;\n\nconst LEFT_EYEBROW_INDICES = [336, 296, 334, 293, 300, 276, 283, 282, 295, 285] as const;\nconst LEFT_EYE_INDICES = [362, 398, 384, 385, 386, 387, 388, 466, 263, 249, 390, 373, 374, 380, 381, 382] as const;\nconst RIGHT_EYEBROW_INDICES = [70, 63, 105, 66, 107, 55, 65, 52, 53, 46] as const;\nconst RIGHT_EYE_INDICES = [33, 246, 161, 160, 159, 158, 157, 173, 133, 155, 154, 153, 145, 144, 163, 7] as const;\nconst OUTER_MOUTH_INDICES = [\n\t61, 185, 40, 39, 37, 0, 267, 269, 270, 409, 291, 375, 321, 405, 314, 17, 84, 181, 91, 146,\n] as const;\nconst INNER_MOUTH_INDICES = [\n\t78, 191, 80, 81, 82, 13, 312, 311, 310, 415, 308, 324, 318, 402, 317, 14, 87, 178, 88, 95,\n] as const;\nconst ALL_STANDARD_INDICES = Array.from({ length: STANDARD_LANDMARK_COUNT }, (_, i) => i);\nconst LANDMARK_INDICES = {\n\tLEFT_EYEBROW: LEFT_EYEBROW_INDICES,\n\tLEFT_EYE: LEFT_EYE_INDICES,\n\tLEFT_EYE_CENTER: 473,\n\tRIGHT_EYEBROW: RIGHT_EYEBROW_INDICES,\n\tRIGHT_EYE: RIGHT_EYE_INDICES,\n\tRIGHT_EYE_CENTER: 468,\n\tNOSE_TIP: 4,\n\tOUTER_MOUTH: OUTER_MOUTH_INDICES,\n\tINNER_MOUTH: INNER_MOUTH_INDICES,\n\t// Custom landmarks.\n\tFACE_CENTER: STANDARD_LANDMARK_COUNT,\n\tMOUTH_CENTER: STANDARD_LANDMARK_COUNT + 1,\n};\n\nconst REGION_NAMES = [\n\t'BACKGROUND',\n\t'LEFT_EYEBROW',\n\t'RIGHT_EYEBROW',\n\t'LEFT_EYE',\n\t'RIGHT_EYE',\n\t'OUTER_MOUTH',\n\t'INNER_MOUTH',\n] as const;\nconst nFaceRegions = REGION_NAMES.length - 1;\nconst RED_CHANNEL_VALUES = Object.fromEntries(REGION_NAMES.map((name, i) => [name, i / nFaceRegions])) as Record<\n\t(typeof REGION_NAMES)[number],\n\tnumber\n>;\nconst HALF_GAP = 0.5 / nFaceRegions;\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 face(config: { textureName: string; options?: FacePluginOptions }) {\n\tconst { textureName, options } = config;\n\tconst defaultModelPath =\n\t\t'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task';\n\n\treturn function (shaderPad: ShaderPad, context: PluginContext) {\n\t\tconst { injectGLSL, gl } = context;\n\n\t\tlet faceLandmarker: FaceLandmarker | null = null;\n\t\tlet vision: any = null;\n\t\tlet lastVideoTime = -1;\n\t\tlet runningMode: 'IMAGE' | 'VIDEO' = 'VIDEO';\n\t\tconst textureSources = new Map<string, TextureSource>();\n\t\tconst maxFaces = options?.maxFaces ?? 1;\n\n\t\tlet landmarksTextureHeight = 0;\n\t\tlet landmarksDataArray: Float32Array | null = null;\n\n\t\tconst mediaPipeCanvas = new OffscreenCanvas(1, 1);\n\t\tconst maskCanvas = new OffscreenCanvas(1, 1);\n\n\t\t// WebGL resources for triangle rendering (no antialiasing).\n\t\tlet maskGl: WebGL2RenderingContext | null = null;\n\t\tlet maskProgram: WebGLProgram | null = null;\n\t\tlet positionBuffer: WebGLBuffer | null = null;\n\t\tlet colorLocation: WebGLUniformLocation | null = null;\n\n\t\tconst regionTriangles: Record<string, number[]> = {\n\t\t\tLEFT_EYEBROW: fanTriangulate(LEFT_EYEBROW_INDICES),\n\t\t\tRIGHT_EYEBROW: fanTriangulate(RIGHT_EYEBROW_INDICES),\n\t\t\tLEFT_EYE: fanTriangulate(LEFT_EYE_INDICES),\n\t\t\tRIGHT_EYE: fanTriangulate(RIGHT_EYE_INDICES),\n\t\t\tOUTER_MOUTH: fanTriangulate(OUTER_MOUTH_INDICES),\n\t\t\tINNER_MOUTH: fanTriangulate(INNER_MOUTH_INDICES),\n\t\t\t// Populated after FaceLandmarker loads.\n\t\t\tTESSELATION: [],\n\t\t\tOVAL: [],\n\t\t};\n\n\t\tfunction initMaskRenderer() {\n\t\t\tmaskGl = maskCanvas.getContext('webgl2', { antialias: false, preserveDrawingBuffer: true });\n\t\t\tif (!maskGl) throw new Error('Failed to get WebGL2 context for mask');\n\n\t\t\tconst vertexShader = maskGl.createShader(maskGl.VERTEX_SHADER)!;\n\t\t\tmaskGl.shaderSource(\n\t\t\t\tvertexShader,\n\t\t\t\t`#version 300 es\nin vec2 a_pos;\nvoid main() {\n\tgl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0);\n}`\n\t\t\t);\n\t\t\tmaskGl.compileShader(vertexShader);\n\n\t\t\tconst fragmentShader = maskGl.createShader(maskGl.FRAGMENT_SHADER)!;\n\t\t\tmaskGl.shaderSource(\n\t\t\t\tfragmentShader,\n\t\t\t\t`#version 300 es\nprecision mediump float;\nuniform vec4 u_color;\nout vec4 outColor;\nvoid main() { outColor = u_color; }`\n\t\t\t);\n\t\t\tmaskGl.compileShader(fragmentShader);\n\n\t\t\tmaskProgram = maskGl.createProgram()!;\n\t\t\tmaskGl.attachShader(maskProgram, vertexShader);\n\t\t\tmaskGl.attachShader(maskProgram, fragmentShader);\n\t\t\tmaskGl.linkProgram(maskProgram);\n\t\t\tmaskGl.deleteShader(vertexShader);\n\t\t\tmaskGl.deleteShader(fragmentShader);\n\n\t\t\tpositionBuffer = maskGl.createBuffer();\n\t\t\tmaskGl.bindBuffer(maskGl.ARRAY_BUFFER, positionBuffer);\n\t\t\tconst positionLocation = maskGl.getAttribLocation(maskProgram, 'a_pos');\n\t\t\tmaskGl.enableVertexAttribArray(positionLocation);\n\t\t\tmaskGl.vertexAttribPointer(positionLocation, 2, maskGl.FLOAT, false, 0, 0);\n\n\t\t\tcolorLocation = maskGl.getUniformLocation(maskProgram, 'u_color');\n\t\t\tmaskGl.useProgram(maskProgram);\n\n\t\t\t// Enable blending to handle overlapping faces (set once, never disabled).\n\t\t\tmaskGl.enable(maskGl.BLEND);\n\t\t\tmaskGl.blendEquation(maskGl.MAX);\n\t\t}\n\n\t\tfunction drawTriangles(triangleIndices: number[], faceIdx: number, r: number, g: number, b: number) {\n\t\t\tif (!maskGl || !landmarksDataArray || triangleIndices.length === 0) return;\n\n\t\t\tconst vertices = new Float32Array(triangleIndices.length * 2);\n\t\t\tfor (let i = 0; i < triangleIndices.length; ++i) {\n\t\t\t\tconst landmarkIdx = (faceIdx * LANDMARK_COUNT + triangleIndices[i]) * 4;\n\t\t\t\tvertices[i * 2] = landmarksDataArray[landmarkIdx];\n\t\t\t\tvertices[i * 2 + 1] = landmarksDataArray[landmarkIdx + 1];\n\t\t\t}\n\n\t\t\tmaskGl.bufferData(maskGl.ARRAY_BUFFER, vertices, maskGl.DYNAMIC_DRAW);\n\t\t\tmaskGl.uniform4f(colorLocation, r, g, b, 1.0);\n\t\t\tmaskGl.drawArrays(maskGl.TRIANGLES, 0, triangleIndices.length);\n\t\t}\n\n\t\tasync function initializeFaceLandmarker() {\n\t\t\ttry {\n\t\t\t\tconst { FilesetResolver, FaceLandmarker } = await import('@mediapipe/tasks-vision');\n\t\t\t\tvision = await FilesetResolver.forVisionTasks(\n\t\t\t\t\t'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm'\n\t\t\t\t);\n\n\t\t\t\tfaceLandmarker = await FaceLandmarker.createFromOptions(vision, {\n\t\t\t\t\tbaseOptions: {\n\t\t\t\t\t\tmodelAssetPath: options?.modelPath || defaultModelPath,\n\t\t\t\t\t\tdelegate: 'GPU',\n\t\t\t\t\t},\n\t\t\t\t\tcanvas: mediaPipeCanvas,\n\t\t\t\t\trunningMode: runningMode,\n\t\t\t\t\tnumFaces: options?.maxFaces ?? 1,\n\t\t\t\t\tminFaceDetectionConfidence: options?.minFaceDetectionConfidence ?? 0.5,\n\t\t\t\t\tminFacePresenceConfidence: options?.minFacePresenceConfidence ?? 0.5,\n\t\t\t\t\tminTrackingConfidence: options?.minTrackingConfidence ?? 0.5,\n\t\t\t\t\toutputFaceBlendshapes: options?.outputFaceBlendshapes ?? false,\n\t\t\t\t\toutputFacialTransformationMatrixes: options?.outputFacialTransformationMatrixes ?? false,\n\t\t\t\t});\n\n\t\t\t\tconst tesselationConnections = FaceLandmarker.FACE_LANDMARKS_TESSELATION;\n\t\t\t\tregionTriangles.TESSELATION = [];\n\t\t\t\tfor (let i = 0; i < tesselationConnections.length - 2; i += 3) {\n\t\t\t\t\tregionTriangles.TESSELATION.push(\n\t\t\t\t\t\ttesselationConnections[i].start,\n\t\t\t\t\t\ttesselationConnections[i + 1].start,\n\t\t\t\t\t\ttesselationConnections[i + 2].start\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst ovalIndices = FaceLandmarker.FACE_LANDMARKS_FACE_OVAL.map(({ start }) => start);\n\t\t\t\tregionTriangles.OVAL = fanTriangulate(ovalIndices);\n\n\t\t\t\tinitMaskRenderer();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Face Plugin] Failed to initialize:', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tfunction calculateBoundingBoxCenter(\n\t\t\tdata: Float32Array,\n\t\t\tfaceIdx: number,\n\t\t\tindices: readonly number[] | number[]\n\t\t): [number, number, number, number] {\n\t\t\tlet minX = Infinity,\n\t\t\t\tmaxX = -Infinity,\n\t\t\t\tminY = Infinity,\n\t\t\t\tmaxY = -Infinity,\n\t\t\t\tavgZ = 0,\n\t\t\t\tavgVisibility = 0;\n\n\t\t\tfor (const idx of indices) {\n\t\t\t\tconst i = (faceIdx * LANDMARK_COUNT + idx) * 4;\n\t\t\t\tconst x = data[i],\n\t\t\t\t\ty = data[i + 1];\n\t\t\t\tminX = Math.min(minX, x);\n\t\t\t\tmaxX = Math.max(maxX, x);\n\t\t\t\tminY = Math.min(minY, y);\n\t\t\t\tmaxY = Math.max(maxY, y);\n\t\t\t\tavgZ += data[i + 2];\n\t\t\t\tavgVisibility += data[i + 3];\n\t\t\t}\n\t\t\treturn [(minX + maxX) / 2, (minY + maxY) / 2, avgZ / indices.length, avgVisibility / indices.length];\n\t\t}\n\n\t\tfunction updateLandmarksTexture(faces: NormalizedLandmark[][]) {\n\t\t\tif (!landmarksDataArray) return;\n\n\t\t\tconst nFaces = faces.length;\n\t\t\tconst totalLandmarks = nFaces * LANDMARK_COUNT;\n\n\t\t\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\t\t\tconst landmarks = faces[faceIdx];\n\t\t\t\tfor (let landmarkIdx = 0; landmarkIdx < STANDARD_LANDMARK_COUNT; ++landmarkIdx) {\n\t\t\t\t\tconst landmark = landmarks[landmarkIdx];\n\t\t\t\t\tconst dataIdx = (faceIdx * LANDMARK_COUNT + landmarkIdx) * 4;\n\t\t\t\t\tlandmarksDataArray[dataIdx] = landmark.x;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 1] = 1 - landmark.y;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 2] = landmark.z ?? 0;\n\t\t\t\t\tlandmarksDataArray[dataIdx + 3] = landmark.visibility ?? 1;\n\t\t\t\t}\n\n\t\t\t\tconst faceCenter = calculateBoundingBoxCenter(landmarksDataArray, faceIdx, ALL_STANDARD_INDICES);\n\t\t\t\tlandmarksDataArray.set(faceCenter, (faceIdx * LANDMARK_COUNT + LANDMARK_INDICES.FACE_CENTER) * 4);\n\n\t\t\t\tconst mouthCenter = calculateBoundingBoxCenter(landmarksDataArray, faceIdx, INNER_MOUTH_INDICES);\n\t\t\t\tlandmarksDataArray.set(mouthCenter, (faceIdx * LANDMARK_COUNT + LANDMARK_INDICES.MOUTH_CENTER) * 4);\n\t\t\t}\n\n\t\t\tconst rowsToUpdate = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tshaderPad.updateTextures({\n\t\t\t\tu_faceLandmarksTex: {\n\t\t\t\t\tdata: landmarksDataArray,\n\t\t\t\t\twidth: LANDMARKS_TEXTURE_WIDTH,\n\t\t\t\t\theight: rowsToUpdate,\n\t\t\t\t\tisPartial: true,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tfunction updateMaskTexture(nFaces: number) {\n\t\t\tif (!maskGl || !landmarksDataArray) return;\n\n\t\t\t// Resize and clear.\n\t\t\tmaskCanvas.width = mediaPipeCanvas.width;\n\t\t\tmaskCanvas.height = mediaPipeCanvas.height;\n\t\t\tmaskGl.viewport(0, 0, maskCanvas.width, maskCanvas.height);\n\t\t\tmaskGl.clearColor(0, 0, 0, 0);\n\t\t\tmaskGl.clear(maskGl.COLOR_BUFFER_BIT);\n\n\t\t\tfor (let faceIdx = 0; faceIdx < nFaces; ++faceIdx) {\n\t\t\t\tconst b = (faceIdx + 1) / maxFaces;\n\n\t\t\t\t// G channel: face mesh (0.5) and oval (1.0)\n\t\t\t\tdrawTriangles(regionTriangles.TESSELATION, faceIdx, 0, 0.5, b);\n\t\t\t\tdrawTriangles(regionTriangles.OVAL, faceIdx, 0, 1.0, b);\n\n\t\t\t\t// R channel: feature regions\n\t\t\t\tdrawTriangles(regionTriangles.LEFT_EYEBROW, faceIdx, RED_CHANNEL_VALUES.LEFT_EYEBROW, 0, b);\n\t\t\t\tdrawTriangles(regionTriangles.RIGHT_EYEBROW, faceIdx, RED_CHANNEL_VALUES.RIGHT_EYEBROW, 0, b);\n\t\t\t\tdrawTriangles(regionTriangles.LEFT_EYE, faceIdx, RED_CHANNEL_VALUES.LEFT_EYE, 0, b);\n\t\t\t\tdrawTriangles(regionTriangles.RIGHT_EYE, faceIdx, RED_CHANNEL_VALUES.RIGHT_EYE, 0, b);\n\t\t\t\tdrawTriangles(regionTriangles.OUTER_MOUTH, faceIdx, RED_CHANNEL_VALUES.OUTER_MOUTH, 0, b);\n\t\t\t\tdrawTriangles(regionTriangles.INNER_MOUTH, faceIdx, RED_CHANNEL_VALUES.INNER_MOUTH, 0, b);\n\t\t\t}\n\n\t\t\tshaderPad.updateTextures({ u_faceMask: maskCanvas });\n\t\t}\n\n\t\tfunction processFaceResults(result: FaceLandmarkerResult) {\n\t\t\tif (!result.faceLandmarks || !landmarksDataArray) return;\n\n\t\t\tconst nFaces = result.faceLandmarks.length;\n\t\t\tupdateLandmarksTexture(result.faceLandmarks);\n\t\t\tupdateMaskTexture(nFaces);\n\t\t\tshaderPad.updateUniforms({ u_nFaces: nFaces });\n\n\t\t\toptions?.onResults?.(result);\n\t\t}\n\n\t\tasync function detectFaces(source: TextureSource) {\n\t\t\tconst previousSource = textureSources.get(textureName);\n\t\t\tif (previousSource !== source) lastVideoTime = -1;\n\t\t\ttextureSources.set(textureName, source);\n\t\t\tif (!faceLandmarker) return;\n\n\t\t\ttry {\n\t\t\t\tconst requiredMode = source instanceof HTMLVideoElement ? 'VIDEO' : 'IMAGE';\n\t\t\t\tif (runningMode !== requiredMode) {\n\t\t\t\t\trunningMode = requiredMode;\n\t\t\t\t\tawait faceLandmarker.setOptions({ runningMode });\n\t\t\t\t}\n\n\t\t\t\tif (source instanceof HTMLVideoElement) {\n\t\t\t\t\tif (source.videoWidth === 0 || source.videoHeight === 0 || source.readyState < 2) return;\n\t\t\t\t\tif (source.currentTime !== lastVideoTime) {\n\t\t\t\t\t\tlastVideoTime = source.currentTime;\n\t\t\t\t\t\tprocessFaceResults(faceLandmarker.detectForVideo(source, performance.now()));\n\t\t\t\t\t}\n\t\t\t\t} else if (source instanceof HTMLImageElement || source instanceof HTMLCanvasElement) {\n\t\t\t\t\tif (source.width === 0 || source.height === 0) return;\n\t\t\t\t\tprocessFaceResults(faceLandmarker.detect(source));\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[Face Plugin] Detection error:', error);\n\t\t\t}\n\t\t}\n\n\t\tshaderPad.registerHook('init', async () => {\n\t\t\tshaderPad.initializeTexture('u_faceMask', maskCanvas, {\n\t\t\t\tminFilter: gl.NEAREST,\n\t\t\t\tmagFilter: gl.NEAREST,\n\t\t\t});\n\t\t\tshaderPad.initializeUniform('u_maxFaces', 'int', maxFaces);\n\t\t\tshaderPad.initializeUniform('u_nFaces', 'int', 0);\n\n\t\t\tconst totalLandmarks = maxFaces * LANDMARK_COUNT;\n\t\t\tlandmarksTextureHeight = Math.ceil(totalLandmarks / LANDMARKS_TEXTURE_WIDTH);\n\t\t\tlandmarksDataArray = new Float32Array(LANDMARKS_TEXTURE_WIDTH * landmarksTextureHeight * 4);\n\n\t\t\tshaderPad.initializeTexture(\n\t\t\t\t'u_faceLandmarksTex',\n\t\t\t\t{ data: landmarksDataArray, width: LANDMARKS_TEXTURE_WIDTH, height: landmarksTextureHeight },\n\t\t\t\t{ internalFormat: gl.RGBA32F, type: gl.FLOAT, minFilter: gl.NEAREST, magFilter: gl.NEAREST }\n\t\t\t);\n\n\t\t\tawait initializeFaceLandmarker();\n\t\t\toptions?.onReady?.();\n\t\t});\n\n\t\tshaderPad.registerHook('initializeTexture', (name: string, source: TextureSource) => {\n\t\t\tif (name === textureName) detectFaces(source);\n\t\t});\n\n\t\tshaderPad.registerHook('updateTextures', (updates: Record<string, TextureSource>) => {\n\t\t\tconst source = updates[textureName];\n\t\t\tif (source) detectFaces(source);\n\t\t});\n\n\t\tshaderPad.registerHook('destroy', () => {\n\t\t\tfaceLandmarker?.close();\n\t\t\tfaceLandmarker = null;\n\t\t\tif (maskGl && maskProgram) {\n\t\t\t\tmaskGl.deleteProgram(maskProgram);\n\t\t\t\tmaskGl.deleteBuffer(positionBuffer);\n\t\t\t}\n\t\t\tmaskGl = null;\n\t\t\tmaskProgram = null;\n\t\t\tvision = null;\n\t\t\ttextureSources.clear();\n\t\t\tlandmarksDataArray = null;\n\t\t});\n\n\t\tconst checkAt = (\n\t\t\tregionMin: keyof typeof RED_CHANNEL_VALUES,\n\t\t\tregionMax: keyof typeof RED_CHANNEL_VALUES = regionMin\n\t\t) =>\n\t\t\t`vec4 mask = texture(u_faceMask, pos);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn (mask.r > ${(RED_CHANNEL_VALUES[regionMin] - HALF_GAP).toFixed(4)} && mask.r < ${(\n\t\t\t\tRED_CHANNEL_VALUES[regionMax] + HALF_GAP\n\t\t\t).toFixed(4)}) ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`;\n\n\t\tinjectGLSL(`\nuniform int u_maxFaces;\nuniform int u_nFaces;\nuniform sampler2D u_faceLandmarksTex;\nuniform sampler2D u_faceMask;\n\n#define FACE_LANDMARK_L_EYE_CENTER ${LANDMARK_INDICES.LEFT_EYE_CENTER}\n#define FACE_LANDMARK_R_EYE_CENTER ${LANDMARK_INDICES.RIGHT_EYE_CENTER}\n#define FACE_LANDMARK_NOSE_TIP ${LANDMARK_INDICES.NOSE_TIP}\n#define FACE_LANDMARK_FACE_CENTER ${LANDMARK_INDICES.FACE_CENTER}\n#define FACE_LANDMARK_MOUTH_CENTER ${LANDMARK_INDICES.MOUTH_CENTER}\n\nvec4 faceLandmark(int faceIndex, int landmarkIndex) {\n\tint i = faceIndex * ${LANDMARK_COUNT} + landmarkIndex;\n\tint x = i % ${LANDMARKS_TEXTURE_WIDTH};\n\tint y = i / ${LANDMARKS_TEXTURE_WIDTH};\n\treturn texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);\n}\n\nvec2 leftEyebrowAt(vec2 pos) {\n\t${checkAt('LEFT_EYEBROW')}\n}\n\nvec2 rightEyebrowAt(vec2 pos) {\n\t${checkAt('RIGHT_EYEBROW')}\n}\n\nvec2 leftEyeAt(vec2 pos) {\n\t${checkAt('LEFT_EYE')}\n}\n\nvec2 rightEyeAt(vec2 pos) {\n\t${checkAt('RIGHT_EYE')}\n}\n\nvec2 lipsAt(vec2 pos) {\n\t${checkAt('OUTER_MOUTH')}\n}\n\nvec2 outerMouthAt(vec2 pos) {\n\t${checkAt('OUTER_MOUTH', 'INNER_MOUTH')}\n}\n\nvec2 innerMouthAt(vec2 pos) {\n\t${checkAt('INNER_MOUTH')}\n}\n\nvec2 faceOvalAt(vec2 pos) {\n\tvec4 mask = texture(u_faceMask, pos);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn mask.g > 0.75 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);\n}\n\n// Includes face mesh and oval.\nvec2 faceAt(vec2 pos) {\n\tvec4 mask = texture(u_faceMask, pos);\n\tfloat faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;\n\treturn mask.g > 0.25 ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);\n}\n\nvec2 eyeAt(vec2 pos) {\n\tvec2 left = leftEyeAt(pos);\n\treturn left.x > 0.0 ? left : rightEyeAt(pos);\n}\n\nvec2 eyebrowAt(vec2 pos) {\n\tvec2 left = leftEyebrowAt(pos);\n\treturn left.x > 0.0 ? left : rightEyebrowAt(pos);\n}\n\nfloat inEyebrow(vec2 pos) { return eyebrowAt(pos).x; }\nfloat inEye(vec2 pos) { return eyeAt(pos).x; }\nfloat inOuterMouth(vec2 pos) { return outerMouthAt(pos).x; }\nfloat inInnerMouth(vec2 pos) { return innerMouthAt(pos).x; }\nfloat inLips(vec2 pos) { return lipsAt(pos).x; }\nfloat inFace(vec2 pos) { return faceAt(pos).x; }`);\n\t};\n}\n\nexport default face;\n"],"mappings":"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","names":["face_exports","__export","face_default","__toCommonJS","STANDARD_LANDMARK_COUNT","CUSTOM_LANDMARK_COUNT","LANDMARK_COUNT","LANDMARKS_TEXTURE_WIDTH","LEFT_EYEBROW_INDICES","LEFT_EYE_INDICES","RIGHT_EYEBROW_INDICES","RIGHT_EYE_INDICES","OUTER_MOUTH_INDICES","INNER_MOUTH_INDICES","ALL_STANDARD_INDICES","_","LANDMARK_INDICES","REGION_NAMES","nFaceRegions","RED_CHANNEL_VALUES","name","HALF_GAP","fanTriangulate","indices","tris","i","face","config","textureName","options","defaultModelPath","shaderPad","context","injectGLSL","gl","faceLandmarker","vision","lastVideoTime","runningMode","textureSources","maxFaces","landmarksTextureHeight","landmarksDataArray","mediaPipeCanvas","maskCanvas","maskGl","maskProgram","positionBuffer","colorLocation","regionTriangles","initMaskRenderer","vertexShader","fragmentShader","positionLocation","drawTriangles","triangleIndices","faceIdx","r","g","b","vertices","landmarkIdx","initializeFaceLandmarker","FilesetResolver","FaceLandmarker","tesselationConnections","ovalIndices","start","error","calculateBoundingBoxCenter","data","minX","maxX","minY","maxY","avgZ","avgVisibility","idx","x","y","updateLandmarksTexture","faces","nFaces","totalLandmarks","landmarks","landmark","dataIdx","faceCenter","mouthCenter","rowsToUpdate","updateMaskTexture","processFaceResults","result","detectFaces","source","requiredMode","updates","checkAt","regionMin","regionMax"]}