shaderpad 1.0.0-beta.41 → 1.0.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -56
- package/dist/chunk-5CBGNOA3.mjs +10 -0
- package/dist/chunk-5CBGNOA3.mjs.map +1 -0
- package/dist/chunk-JRSBIGBN.mjs +7 -0
- package/dist/chunk-JRSBIGBN.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/face.d.mts +1 -0
- package/dist/plugins/face.d.ts +1 -0
- package/dist/plugins/face.js +53 -76
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +51 -79
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/hands.d.mts +1 -0
- package/dist/plugins/hands.d.ts +1 -0
- package/dist/plugins/hands.js +20 -16
- package/dist/plugins/hands.js.map +1 -1
- package/dist/plugins/hands.mjs +15 -16
- package/dist/plugins/hands.mjs.map +1 -1
- package/dist/plugins/helpers.js +1 -1
- package/dist/plugins/helpers.js.map +1 -1
- package/dist/plugins/helpers.mjs +1 -1
- package/dist/plugins/helpers.mjs.map +1 -1
- package/dist/plugins/mediapipe-common.d.mts +18 -0
- package/dist/plugins/mediapipe-common.d.ts +18 -0
- package/dist/plugins/mediapipe-common.js +7 -0
- package/dist/plugins/mediapipe-common.js.map +1 -0
- package/dist/plugins/mediapipe-common.mjs +2 -0
- package/dist/plugins/mediapipe-common.mjs.map +1 -0
- package/dist/plugins/pose.d.mts +1 -0
- package/dist/plugins/pose.d.ts +1 -0
- package/dist/plugins/pose.js +54 -49
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +46 -46
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/save.d.mts +1 -1
- package/dist/plugins/save.d.ts +1 -1
- package/dist/plugins/save.js +1 -1
- package/dist/plugins/save.js.map +1 -1
- package/dist/plugins/save.mjs.map +1 -1
- package/dist/plugins/segmenter.d.mts +1 -0
- package/dist/plugins/segmenter.d.ts +1 -0
- package/dist/plugins/segmenter.js +16 -11
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +10 -10
- package/dist/plugins/segmenter.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-A3XQBYSC.mjs +0 -10
- package/dist/chunk-A3XQBYSC.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var y=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var _=(a,e)=>{for(var t in e)y(a,t,{get:e[t],enumerable:!0})},U=(a,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of L(e))!A.call(a,i)&&i!==t&&y(a,i,{get:()=>e[i],enumerable:!(s=w(e,i))||s.enumerable});return a};var P=a=>U(y({},"__esModule",{value:!0}),a);var H={};_(H,{default:()=>D});module.exports=P(H);var S=`#version 300 es
|
|
2
2
|
in vec2 aPosition;
|
|
3
3
|
out vec2 v_uv;
|
|
4
4
|
void main() {
|
|
5
5
|
v_uv = aPosition * 0.5 + 0.5;
|
|
6
6
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
7
|
-
}`,I=33.333333333333336,
|
|
8
|
-
`),
|
|
9
|
-
`)}function E(a){return a instanceof WebGLTexture?{width:0,height:0}:a instanceof HTMLVideoElement?{width:a.videoWidth,height:a.videoHeight}:a instanceof HTMLImageElement?{width:a.naturalWidth??a.width,height:a.naturalHeight??a.height}:{width:a.width,height:a.height}}function d(a){return typeof a=="symbol"?a.description??"":a}var x=class{isInternalCanvas=!1;isTouchDevice=!1;gl;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;aPositionLocation=0;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;hooks=new Map;historyDepth=0;textureOptions;debug;intermediateFbo=null;constructor(e,{canvas:t,plugins:r,history:i,debug:s,...o}={}){if(this.canvas=t||document.createElement("canvas"),!t){this.isInternalCanvas=!0;let f=this.canvas;f.style.position="fixed",f.style.inset="0",f.style.height="100dvh",f.style.width="100dvw",document.body.appendChild(f)}let n=this.canvas.getContext("webgl2",{antialias:!1});if(!n)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.gl=n,this.textureUnitPool={free:[],next:0,max:n.getParameter(n.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.textureOptions=o;let{internalFormat:l,type:h}=o;(h===n.FLOAT||h===n.HALF_FLOAT||l===n.RGBA16F||l===n.RGBA32F||l===n.R16F||l===n.R32F||l===n.RG16F||l===n.RG32F)&&!n.getExtension("EXT_color_buffer_float")&&(console.warn("EXT_color_buffer_float not supported, falling back to RGBA8"),delete this.textureOptions?.internalFormat,delete this.textureOptions?.format,delete this.textureOptions?.type),i&&(this.historyDepth=i),this.debug=s??(typeof process<"u"&&!1),this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let m=[];r&&r.forEach(f=>f(this,{gl:n,canvas:this.canvas,injectGLSL:R=>{m.push(R)},emitHook:this.emitHook.bind(this)}));let c=this.gl.createProgram();if(!c)throw new Error("Failed to create WebGL program");this.program=c;let v=this.createShader(this.gl.VERTEX_SHADER,P),b=this.createShader(n.FRAGMENT_SHADER,S(e,m));if(n.attachShader(c,v),n.attachShader(c,b),n.linkProgram(c),n.deleteShader(v),n.deleteShader(b),!n.getProgramParameter(c,n.LINK_STATUS))throw console.error("Program link error:",n.getProgramInfoLog(c)),n.deleteProgram(c),new Error("Failed to link WebGL program");this.aPositionLocation=n.getAttribLocation(c,"aPosition");let y=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.buffer),n.bufferData(n.ARRAY_BUFFER,y,n.STATIC_DRAW),n.viewport(0,0,n.drawingBufferWidth,n.drawingBufferHeight),n.enableVertexAttribArray(this.aPositionLocation),n.vertexAttribPointer(this.aPositionLocation,2,n.FLOAT,!1,0,0),n.useProgram(c),this.canvas instanceof HTMLCanvasElement&&(this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas)),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyDepth>0&&(this._initializeTexture(p,this.canvas,{...this.textureOptions}),this._initializeTexture(g,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.intermediateFbo=n.createFramebuffer()),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners(),this.emitHook("init")}emitHook(e,...t){this.hooks.get(e)?.forEach(r=>r.call(this,...t))}on(e,t){this.hooks.has(e)||this.hooks.set(e,[]),this.hooks.get(e).push(t)}off(e,t){let r=this.hooks.get(e);r&&r.splice(r.indexOf(t),1)}createShader(e,t){let r=this.gl.createShader(e);if(this.gl.shaderSource(r,t),this.gl.compileShader(r),!this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",t),console.error(this.gl.getShaderInfoLog(r)),this.gl.deleteShader(r),new Error("Shader compilation failed");return r}throttledHandleResize(){clearTimeout(this.resizeTimeout);let e=performance.now(),t=this.lastResizeTime+I-e;t<=0?(this.lastResizeTime=e,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),t)}handleResize(){if(!(this.canvas instanceof HTMLCanvasElement))return;let e=window.devicePixelRatio||1,t=this.canvas.clientWidth*e,r=this.canvas.clientHeight*e;this.isInternalCanvas&&(this.canvas.width!==t||this.canvas.height!==r)&&(this.canvas.width=t,this.canvas.height=r),this.emitHook("resize",t,r)}addEventListeners(){let e=this.canvas,t=(i,s)=>{if(!this.uniforms.has("u_cursor"))return;let o=e.getBoundingClientRect();this.cursorPosition[0]=(i-o.left)/o.width,this.cursorPosition[1]=1-(s-o.top)/o.height,this.updateUniforms({u_cursor:this.cursorPosition})},r=(i,s,o)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let n=e.getBoundingClientRect(),l=s,h=o;this.clickPosition[0]=(l-n.left)/n.width,this.clickPosition[1]=1-(h-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let s=i;this.isTouchDevice||t(s.clientX,s.clientY)}),this.eventListeners.set("mousedown",i=>{let s=i;this.isTouchDevice||s.button===0&&(this.isMouseDown=!0,r(!0,s.clientX,s.clientY))}),this.eventListeners.set("mouseup",i=>{let s=i;this.isTouchDevice||s.button===0&&r(!1)}),this.eventListeners.set("touchmove",i=>{let s=i;s.touches.length>0&&t(s.touches[0].clientX,s.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let s=i;this.isTouchDevice=!0,s.touches.length>0&&(t(s.touches[0].clientX,s.touches[0].clientY),r(!0,s.touches[0].clientX,s.touches[0].clientY))}),this.eventListeners.set("touchend",i=>{i.touches.length===0&&r(!1)}),this.eventListeners.forEach((i,s)=>{e.addEventListener(s,i)})}updateResolution(){let e=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...e),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:e}):this.initializeUniform("u_resolution","float",e),this.historyDepth>0&&(this.resizeTexture(g,...e),this.resizeTexture(p,...e)),this.emitHook("updateResolution",...e)}resizeTexture(e,t,r){let i=this.textures.get(e);if(!i||i.width===t&&i.height===r)return;this.gl.deleteTexture(i.texture),i.width=t,i.height=r;let{texture:s}=this.createTexture(e,i);i.texture=s,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(e){let t=this.textures.get(e);if(t)return t.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(e){let t=this.textures.get(e);t&&this.textureUnitPool.free.push(t.unitIndex)}resolveTextureOptions(e){let{gl:t}=this,r=e?.type??t.UNSIGNED_BYTE;return{type:r,format:e?.format??t.RGBA,internalFormat:e?.internalFormat??(r===t.FLOAT?t.RGBA32F:r===t.HALF_FLOAT?t.RGBA16F:t.RGBA8),minFilter:e?.minFilter??t.LINEAR,magFilter:e?.magFilter??t.LINEAR,wrapS:e?.wrapS??t.CLAMP_TO_EDGE,wrapT:e?.wrapT??t.CLAMP_TO_EDGE,preserveY:e?.preserveY}}clearHistoryTextureLayers(e){if(!e.history)return;let t=this.gl,{type:r,format:i}=e.options,s=e.width*e.height*4,o=r===t.FLOAT?new Float32Array(s):r===t.HALF_FLOAT?new Uint16Array(s):new Uint8Array(s);t.activeTexture(t.TEXTURE0+e.unitIndex),t.bindTexture(t.TEXTURE_2D_ARRAY,e.texture);for(let n=0;n<e.history.depth;++n)t.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,n,e.width,e.height,1,i,r,o)}initializeUniform(e,t,r,i){let s=i?.arrayLength;if(this.uniforms.has(e))throw new Error(`${e} is already initialized.`);if(t!=="float"&&t!=="int")throw new Error(`Invalid uniform type: ${t}. Expected 'float' or 'int'.`);if(s&&!(Array.isArray(r)&&r.length===s))throw new Error(`${e} array length mismatch: must initialize with ${s} elements.`);let o=this.gl.getUniformLocation(this.program,e);if(!o&&s&&(o=this.gl.getUniformLocation(this.program,`${e}[0]`)),!o){this.log(`${e} not in shader. Skipping initialization.`);return}let n=s?r[0]:r,l=Array.isArray(n)?n.length:1;this.uniforms.set(e,{type:t,length:l,location:o,arrayLength:s});try{this.updateUniforms({[e]:r})}catch(h){throw this.uniforms.delete(e),h}this.emitHook("initializeUniform",...arguments)}log(...e){this.debug&&console.debug(...e)}updateUniforms(e,t){this.gl.useProgram(this.program),Object.entries(e).forEach(([r,i])=>{let s=this.uniforms.get(r);if(!s){this.log(`${r} not in shader. Skipping update.`);return}let o=`uniform${s.length}${s.type.charAt(0)}`;if(s.arrayLength){if(!Array.isArray(i))throw new Error(`${r} is an array, but the value passed to updateUniforms is not an array.`);let n=i.length;if(!n)return;if(n>s.arrayLength)throw new Error(`${r} received ${n} values, but maximum length is ${s.arrayLength}.`);if(i.some(u=>(Array.isArray(u)?u.length:1)!==s.length))throw new Error(`Tried to update ${r} with some elements that are not length ${s.length}.`);let l=new(s.type==="float"?Float32Array:Int32Array)(i.flat()),h=s.location;if(t?.startIndex){let u=this.gl.getUniformLocation(this.program,`${r}[${t.startIndex}]`);if(!u)throw new Error(`${r}[${t.startIndex}] not in shader. Did you pass an invalid startIndex?`);h=u}this.gl[o+"v"](h,l)}else{if(Array.isArray(i)||(i=[i]),i.length!==s.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${s.length}.`);this.gl[o](s.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(e,t){let{width:r,height:i}=t,s=t.history?.depth??0,o=this.gl.createTexture();if(!o)throw new Error("Failed to create texture");let n=t.unitIndex;if(typeof n!="number")try{n=this.reserveTextureUnit(e)}catch(m){throw this.gl.deleteTexture(o),m}let l=s>0,h=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:u}=t;return this.gl.activeTexture(this.gl.TEXTURE0+n),this.gl.bindTexture(h,o),this.gl.texParameteri(h,this.gl.TEXTURE_WRAP_S,u.wrapS),this.gl.texParameteri(h,this.gl.TEXTURE_WRAP_T,u.wrapT),this.gl.texParameteri(h,this.gl.TEXTURE_MIN_FILTER,u.minFilter),this.gl.texParameteri(h,this.gl.TEXTURE_MAG_FILTER,u.magFilter),l?this.gl.texStorage3D(h,1,u.internalFormat,r,i,s):e===p&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,u.internalFormat,r,i,0,u.format,u.type,null),{texture:o,unitIndex:n}}_initializeTexture(e,t,r){if(this.textures.has(e))throw new Error(`Texture '${d(e)}' is already initialized.`);let{history:i=0,...s}=r??{},{width:o,height:n}=E(t);if(!o||!n)throw new Error("Texture source must have valid dimensions");let l={width:o,height:n,options:this.resolveTextureOptions(s)};i>0&&(l.history={depth:i,writeIndex:0});let{texture:h,unitIndex:u}=this.createTexture(e,l),m={texture:h,unitIndex:u,...l};i>0&&(this.initializeUniform(`${d(e)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(m)),this.textures.set(e,m),this.updateTexture(e,t);let c=this.gl.getUniformLocation(this.program,d(e));c&&this.gl.uniform1i(c,u)}initializeTexture(e,t,r){this._initializeTexture(e,t,r),this.emitHook("initializeTexture",...arguments)}updateTextures(e,t){Object.entries(e).forEach(([r,i])=>{this.updateTexture(r,i,t)}),this.emitHook("updateTextures",...arguments)}updateTexture(e,t,r){let i=this.textures.get(e);if(!i)throw new Error(`Texture '${d(e)}' is not initialized.`);if(t instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,t);return}let{width:s,height:o}=E(t);if(!s||!o)return;let n="isPartial"in t&&t.isPartial;n||this.resizeTexture(e,s,o);let h=!("data"in t&&t.data)&&!i.options?.preserveY,u=this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);if(i.history){if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture),!r?.skipHistoryWrite){this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,h),this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,i.history.writeIndex,s,o,1,i.options.format,i.options.type,t.data??t),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,u);let m=`${d(e)}FrameOffset`;this.updateUniforms({[m]:i.history.writeIndex}),i.history.writeIndex=(i.history.writeIndex+1)%i.history.depth}}else this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,i.texture),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,h),n?this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,t.x??0,t.y??0,s,o,i.options.format,i.options.type,t.data):this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,s,o,0,i.options.format,i.options.type,t.data??t),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,u)}draw(e){this.emitHook("beforeDraw",...arguments);let t=this.gl,r=t.drawingBufferWidth,i=t.drawingBufferHeight,s=this.textures.get(g),o=this.textures.get(p),n=s&&!e?.skipHistoryWrite;n&&(t.bindFramebuffer(t.FRAMEBUFFER,this.intermediateFbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,o.texture,0)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.buffer),t.vertexAttribPointer(this.aPositionLocation,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(this.aPositionLocation),t.viewport(0,0,r,i),e?.skipClear||t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6),n&&(t.bindTexture(t.TEXTURE_2D_ARRAY,s.texture),t.copyTexSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,s.history.writeIndex,0,0,r,i),t.bindFramebuffer(t.READ_FRAMEBUFFER,this.intermediateFbo),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,null),t.blitFramebuffer(0,0,r,i,0,0,r,i,t.COLOR_BUFFER_BIT,t.NEAREST),t.bindFramebuffer(t.FRAMEBUFFER,null)),this.emitHook("afterDraw",...arguments)}step(e,t){this.emitHook("beforeStep",...arguments);let r={};this.uniforms.has("u_time")&&(r.u_time=e),this.uniforms.has("u_frame")&&(r.u_frame=this.frame),this.updateUniforms(r),this.draw(t);let i=this.textures.get(g);if(i&&!t?.skipHistoryWrite){let{writeIndex:s,depth:o}=i.history;this.updateUniforms({[`${d(g)}FrameOffset`]:s}),i.history.writeIndex=(s+1)%o}++this.frame,this.emitHook("afterStep",...arguments)}play(e,t){this.pause();let r=i=>{i=(i-this.startTime)/1e3;let s=t?.(i,this.frame)??void 0;this.step(i,s),this.animationFrameId=requestAnimationFrame(r),e?.(i,this.frame)};this.animationFrameId=requestAnimationFrame(r),this.emitHook("play")}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.emitHook("pause")}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(e=>{e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}),this.emitHook("reset")}destroy(){this.emitHook("destroy"),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.canvas instanceof HTMLCanvasElement&&this.eventListeners.forEach((e,t)=>{this.canvas.removeEventListener(t,e)}),this.program&&this.gl.deleteProgram(this.program),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(e=>{this.gl.deleteTexture(e.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas instanceof HTMLCanvasElement&&this.canvas.remove()}},O=x;
|
|
7
|
+
}`,I=33.333333333333336,O=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),v=Symbol("u_history"),b=Symbol("__SHADERPAD_BUFFER");function C(a,e){if(!e?.length)return a;let t=a.split(`
|
|
8
|
+
`),s=t.findLastIndex(i=>{let r=i.trimStart();return r.startsWith("precision ")||r.startsWith("#version ")})+1;return t.splice(s,0,...e),t.join(`
|
|
9
|
+
`)}function R(a){return a instanceof WebGLTexture?{width:0,height:0}:a instanceof E?{width:a.canvas.width,height:a.canvas.height}:a instanceof HTMLVideoElement?{width:a.videoWidth,height:a.videoHeight}:a instanceof HTMLImageElement?{width:a.naturalWidth??a.width,height:a.naturalHeight??a.height}:{width:a.width,height:a.height}}function x(a){return typeof a=="symbol"?a.description??"":a}var E=class a{isInternalCanvas=!1;isTouchDevice=!1;gl;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;aPositionLocation=0;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;hooks=new Map;historyDepth=0;textureOptions;debug;intermediateFbo=null;constructor(e,{canvas:t,plugins:s,history:i,debug:r,...o}={}){if(this.canvas=t||document.createElement("canvas"),!t){this.isInternalCanvas=!0;let f=this.canvas;f.style.position="fixed",f.style.inset="0",f.style.height="100dvh",f.style.width="100dvw",document.body.appendChild(f)}if(this.canvas instanceof OffscreenCanvas){let f=d=>{let g=Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype,d);Object.defineProperty(this.canvas,d,{get:()=>g.get.call(this.canvas),set:F=>{g.set.call(this.canvas,F),this.updateResolution()},configurable:g.configurable,enumerable:g.enumerable})};f("width"),f("height")}let n=this.canvas.getContext("webgl2",{antialias:!1});if(!n)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.gl=n,this.textureUnitPool={free:[],next:0,max:n.getParameter(n.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.textureOptions=o;let{internalFormat:h,type:c}=o;(c===n.FLOAT||c===n.HALF_FLOAT||h===n.RGBA16F||h===n.RGBA32F||h===n.R16F||h===n.R32F||h===n.RG16F||h===n.RG32F)&&!n.getExtension("EXT_color_buffer_float")&&(console.warn("EXT_color_buffer_float not supported, falling back to RGBA8"),delete this.textureOptions?.internalFormat,delete this.textureOptions?.format,delete this.textureOptions?.type),i&&(this.historyDepth=i),this.debug=r??(typeof process<"u"&&!1),this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let m=[];s&&s.forEach(f=>f(this,{gl:n,canvas:this.canvas,injectGLSL:d=>{m.push(d)},emitHook:this.emitHook.bind(this)}));let u=this.gl.createProgram();if(!u)throw new Error("Failed to create WebGL program");this.program=u;let p=this.createShader(this.gl.VERTEX_SHADER,S),T=this.createShader(n.FRAGMENT_SHADER,C(e,m));if(n.attachShader(u,p),n.attachShader(u,T),n.linkProgram(u),n.deleteShader(p),n.deleteShader(T),!n.getProgramParameter(u,n.LINK_STATUS))throw console.error("Program link error:",n.getProgramInfoLog(u)),n.deleteProgram(u),new Error("Failed to link WebGL program");this.aPositionLocation=n.getAttribLocation(u,"aPosition"),this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.buffer),n.bufferData(n.ARRAY_BUFFER,O,n.STATIC_DRAW),n.viewport(0,0,n.drawingBufferWidth,n.drawingBufferHeight),n.enableVertexAttribArray(this.aPositionLocation),n.vertexAttribPointer(this.aPositionLocation,2,n.FLOAT,!1,0,0),n.useProgram(u),this.canvas instanceof HTMLCanvasElement&&(this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas)),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this._initializeTexture(b,this.canvas,{...this.textureOptions}),this.intermediateFbo=n.createFramebuffer(),this.historyDepth>0&&this._initializeTexture(v,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.canvas instanceof HTMLCanvasElement&&this.addEventListeners(),this.emitHook("init")}emitHook(e,...t){this.hooks.get(e)?.forEach(s=>s.call(this,...t))}on(e,t){this.hooks.has(e)||this.hooks.set(e,[]),this.hooks.get(e).push(t)}off(e,t){let s=this.hooks.get(e);s&&s.splice(s.indexOf(t),1)}createShader(e,t){let s=this.gl.createShader(e);if(this.gl.shaderSource(s,t),this.gl.compileShader(s),!this.gl.getShaderParameter(s,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",t),console.error(this.gl.getShaderInfoLog(s)),this.gl.deleteShader(s),new Error("Shader compilation failed");return s}throttledHandleResize(){clearTimeout(this.resizeTimeout);let e=performance.now(),t=this.lastResizeTime+I-e;t<=0?(this.lastResizeTime=e,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),t)}handleResize(){if(!(this.canvas instanceof HTMLCanvasElement))return;let e=window.devicePixelRatio||1,t=this.canvas.clientWidth*e,s=this.canvas.clientHeight*e;this.isInternalCanvas&&(this.canvas.width!==t||this.canvas.height!==s)&&(this.canvas.width=t,this.canvas.height=s),this.emitHook("resize",t,s)}addEventListeners(){let e=this.canvas,t=(i,r)=>{if(!this.uniforms.has("u_cursor"))return;let o=e.getBoundingClientRect();this.cursorPosition[0]=(i-o.left)/o.width,this.cursorPosition[1]=1-(r-o.top)/o.height,this.updateUniforms({u_cursor:this.cursorPosition})},s=(i,r,o)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let n=e.getBoundingClientRect(),h=r,c=o;this.clickPosition[0]=(h-n.left)/n.width,this.clickPosition[1]=1-(c-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let r=i;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",i=>{let r=i;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,s(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",i=>{let r=i;this.isTouchDevice||r.button===0&&s(!1)}),this.eventListeners.set("touchmove",i=>{let r=i;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let r=i;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),s(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",i=>{i.touches.length===0&&s(!1)}),this.eventListeners.forEach((i,r)=>{e.addEventListener(r,i)})}updateResolution(){let e=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...e),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:e}):this.initializeUniform("u_resolution","float",e),this.resizeTexture(b,...e),this.historyDepth>0&&this.resizeTexture(v,...e),this.emitHook("updateResolution",...e)}resizeTexture(e,t,s){let i=this.textures.get(e);if(!i||i.width===t&&i.height===s)return;this.gl.deleteTexture(i.texture),i.width=t,i.height=s;let{texture:r}=this.createTexture(e,i);i.texture=r,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(e){let t=this.textures.get(e);if(t)return t.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(e){let t=this.textures.get(e);t&&this.textureUnitPool.free.push(t.unitIndex)}resolveTextureOptions(e){let{gl:t}=this,s=e?.type??t.UNSIGNED_BYTE;return{type:s,format:e?.format??t.RGBA,internalFormat:e?.internalFormat??(s===t.FLOAT?t.RGBA32F:s===t.HALF_FLOAT?t.RGBA16F:t.RGBA8),minFilter:e?.minFilter??t.LINEAR,magFilter:e?.magFilter??t.LINEAR,wrapS:e?.wrapS??t.CLAMP_TO_EDGE,wrapT:e?.wrapT??t.CLAMP_TO_EDGE,preserveY:e?.preserveY}}getPixelArray(e,t){return e===this.gl.FLOAT?new Float32Array(t):e===this.gl.HALF_FLOAT?new Uint16Array(t):new Uint8Array(t)}clearHistoryTextureLayers(e){if(!e.history)return;let t=this.gl,{type:s,format:i}=e.options,r=this.getPixelArray(s,e.width*e.height*4);t.activeTexture(t.TEXTURE0+e.unitIndex),t.bindTexture(t.TEXTURE_2D_ARRAY,e.texture);for(let o=0;o<e.history.depth;++o)t.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,o,e.width,e.height,1,i,s,r)}initializeUniform(e,t,s,i){let r=i?.arrayLength;if(this.uniforms.has(e))throw new Error(`${e} is already initialized.`);if(t!=="float"&&t!=="int")throw new Error(`Invalid uniform type: ${t}. Expected 'float' or 'int'.`);if(r&&!(Array.isArray(s)&&s.length===r))throw new Error(`${e} array length mismatch: must initialize with ${r} elements.`);let o=this.gl.getUniformLocation(this.program,e);if(!o&&r&&(o=this.gl.getUniformLocation(this.program,`${e}[0]`)),!o){this.log(`${e} not in shader. Skipping initialization.`);return}let n=r?s[0]:s,h=Array.isArray(n)?n.length:1;this.uniforms.set(e,{type:t,length:h,location:o,arrayLength:r});try{this.updateUniforms({[e]:s})}catch(c){throw this.uniforms.delete(e),c}this.emitHook("initializeUniform",...arguments)}log(...e){this.debug&&console.debug(...e)}updateUniforms(e,t){this.gl.useProgram(this.program),Object.entries(e).forEach(([s,i])=>{let r=this.uniforms.get(s);if(!r){this.log(`${s} not in shader. Skipping update.`);return}let o=`uniform${r.length}${r.type.charAt(0)}`;if(r.arrayLength){if(!Array.isArray(i))throw new Error(`${s} is an array, but the value passed to updateUniforms is not an array.`);let n=i.length;if(!n)return;if(n>r.arrayLength)throw new Error(`${s} received ${n} values, but maximum length is ${r.arrayLength}.`);if(i.some(l=>(Array.isArray(l)?l.length:1)!==r.length))throw new Error(`Tried to update ${s} with some elements that are not length ${r.length}.`);let h=new(r.type==="float"?Float32Array:Int32Array)(i.flat()),c=r.location;if(t?.startIndex){let l=this.gl.getUniformLocation(this.program,`${s}[${t.startIndex}]`);if(!l)throw new Error(`${s}[${t.startIndex}] not in shader. Did you pass an invalid startIndex?`);c=l}this.gl[o+"v"](c,h)}else{if(Array.isArray(i)||(i=[i]),i.length!==r.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${r.length}.`);this.gl[o](r.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(e,t){let{width:s,height:i}=t,r=t.history?.depth??0,o=this.gl.createTexture();if(!o)throw new Error("Failed to create texture");let n=t.unitIndex;if(typeof n!="number")try{n=this.reserveTextureUnit(e)}catch(m){throw this.gl.deleteTexture(o),m}let h=r>0,c=h?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:l}=t;return this.gl.activeTexture(this.gl.TEXTURE0+n),this.gl.bindTexture(c,o),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_S,l.wrapS),this.gl.texParameteri(c,this.gl.TEXTURE_WRAP_T,l.wrapT),this.gl.texParameteri(c,this.gl.TEXTURE_MIN_FILTER,l.minFilter),this.gl.texParameteri(c,this.gl.TEXTURE_MAG_FILTER,l.magFilter),h?this.gl.texStorage3D(c,1,l.internalFormat,s,i,r):e===b&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,l.internalFormat,s,i,0,l.format,l.type,null),{texture:o,unitIndex:n}}_initializeTexture(e,t,s){if(this.textures.has(e))throw new Error(`Texture '${x(e)}' is already initialized.`);let{history:i=0,...r}=s??{},{width:o,height:n}=R(t);if(!o||!n)throw new Error("Texture source must have valid dimensions");let h={width:o,height:n,options:this.resolveTextureOptions(r)};i>0&&(h.history={depth:i,writeIndex:0});let{texture:c,unitIndex:l}=this.createTexture(e,h),m={texture:c,unitIndex:l,...h};i>0&&(this.initializeUniform(`${x(e)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(m)),this.textures.set(e,m),this.updateTexture(e,t);let u=this.gl.getUniformLocation(this.program,x(e));u&&this.gl.uniform1i(u,l)}initializeTexture(e,t,s){this._initializeTexture(e,t,s),this.emitHook("initializeTexture",...arguments)}updateTextures(e,t){Object.entries(e).forEach(([s,i])=>{this.updateTexture(s,i,t)}),this.emitHook("updateTextures",...arguments)}updateTexture(e,t,s){let i=this.textures.get(e);if(!i)throw new Error(`Texture '${x(e)}' is not initialized.`);if(t instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,t);return}let r=t;if(t instanceof a){let u=t.textures.get(b);if(t.gl===this.gl){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,u.texture);return}let{width:p,height:T,options:{format:f,type:d}}=u,g=this.getPixelArray(d,p*T*4);t.gl.bindFramebuffer(t.gl.FRAMEBUFFER,t.intermediateFbo),t.gl.readPixels(0,0,p,T,f,d,g),t.gl.bindFramebuffer(t.gl.FRAMEBUFFER,null),r={data:g,width:p,height:T}}let{width:o,height:n}=R(r);if(!o||!n)return;let h="isPartial"in r&&r.isPartial;h||this.resizeTexture(e,o,n);let l=!("data"in r&&r.data)&&!i.options?.preserveY,m=this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL);if(i.history){if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture),!s?.skipHistoryWrite){this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l),this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,i.history.writeIndex,o,n,1,i.options.format,i.options.type,r.data??r),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,m);let u=`${x(e)}FrameOffset`;this.updateUniforms({[u]:i.history.writeIndex}),i.history.writeIndex=(i.history.writeIndex+1)%i.history.depth}}else{if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,i.texture),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l),h){let u=r;this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,u.x??0,u.y??0,o,n,i.options.format,i.options.type,u.data)}else this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,o,n,0,i.options.format,i.options.type,r.data??r);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,m)}}draw(e){this.emitHook("beforeDraw",...arguments);let t=this.gl,s=t.drawingBufferWidth,i=t.drawingBufferHeight,r=this.textures.get(b);t.bindFramebuffer(t.FRAMEBUFFER,this.intermediateFbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,r.texture,0),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.buffer),t.vertexAttribPointer(this.aPositionLocation,2,t.FLOAT,!1,0,0),t.enableVertexAttribArray(this.aPositionLocation),t.viewport(0,0,s,i),e?.skipClear||t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6);let o=this.textures.get(v);o&&!e?.skipHistoryWrite&&(t.bindTexture(t.TEXTURE_2D_ARRAY,o.texture),t.copyTexSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,o.history.writeIndex,0,0,s,i)),t.bindFramebuffer(t.READ_FRAMEBUFFER,this.intermediateFbo),t.bindFramebuffer(t.DRAW_FRAMEBUFFER,null),t.blitFramebuffer(0,0,s,i,0,0,s,i,t.COLOR_BUFFER_BIT,t.NEAREST),t.bindFramebuffer(t.FRAMEBUFFER,null),this.emitHook("afterDraw",...arguments)}step(e,t){this.emitHook("beforeStep",...arguments);let s={};this.uniforms.has("u_time")&&(s.u_time=e),this.uniforms.has("u_frame")&&(s.u_frame=this.frame),this.updateUniforms(s),this.draw(t);let i=this.textures.get(v);if(i&&!t?.skipHistoryWrite){let{writeIndex:r,depth:o}=i.history;this.updateUniforms({[`${x(v)}FrameOffset`]:r}),i.history.writeIndex=(r+1)%o}++this.frame,this.emitHook("afterStep",...arguments)}play(e,t){this.pause();let s=i=>{i=(i-this.startTime)/1e3;let r=t?.(i,this.frame)??void 0;this.step(i,r),this.animationFrameId=requestAnimationFrame(s),e?.(i,this.frame)};this.animationFrameId=requestAnimationFrame(s),this.emitHook("play")}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.emitHook("pause")}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(e=>{e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}),this.emitHook("reset")}destroy(){this.emitHook("destroy"),this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.canvas instanceof HTMLCanvasElement&&this.eventListeners.forEach((e,t)=>{this.canvas.removeEventListener(t,e)}),this.program&&this.gl.deleteProgram(this.program),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(e=>{this.gl.deleteTexture(e.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas instanceof HTMLCanvasElement&&this.canvas.remove()}},D=E;
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
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}`;\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}\ntype ResolvedTextureOptions = Required<Omit<TextureOptions, 'preserveY'>> & Pick<TextureOptions, 'preserveY'>;\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: ResolvedTextureOptions;\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\tcanvas: HTMLCanvasElement | OffscreenCanvas;\n\tinjectGLSL: (code: string) => void;\n\temitHook: (name: LifecycleMethod, ...args: any[]) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'initializeTexture'\n\t| 'initializeUniform'\n\t| 'updateTextures'\n\t| 'updateUniforms'\n\t| 'beforeStep'\n\t| 'afterStep'\n\t| 'beforeDraw'\n\t| 'afterDraw'\n\t| 'updateResolution'\n\t| 'resize'\n\t| 'play'\n\t| 'pause'\n\t| 'reset'\n\t| 'destroy'\n\t| `${string}:${string}`;\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 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\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\tconst gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: gl.getParameter(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 === gl.FLOAT ||\n\t\t\ttype === gl.HALF_FLOAT ||\n\t\t\tinternalFormat === gl.RGBA16F ||\n\t\t\tinternalFormat === gl.RGBA32F ||\n\t\t\tinternalFormat === gl.R16F ||\n\t\t\tinternalFormat === gl.R32F ||\n\t\t\tinternalFormat === gl.RG16F ||\n\t\t\tinternalFormat === gl.RG32F;\n\t\tif (isFloatFormat && !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\tplugins.forEach(plugin =>\n\t\t\t\tplugin(this, {\n\t\t\t\t\tgl,\n\t\t\t\t\tcanvas: this.canvas,\n\t\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t\t},\n\t\t\t\t\temitHook: this.emitHook.bind(this),\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tconst program = this.gl.createProgram();\n\t\tif (!program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tthis.program = program;\n\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, DEFAULT_VERTEX_SHADER_SRC);\n\t\tconst fragmentShader = this.createShader(\n\t\t\tgl.FRAGMENT_SHADER,\n\t\t\tcombineShaderCode(fragmentShaderSrc, glslInjections)\n\t\t);\n\t\tgl.attachShader(program, vertexShader);\n\t\tgl.attachShader(program, fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tgl.deleteShader(vertexShader);\n\t\tgl.deleteShader(fragmentShader);\n\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', gl.getProgramInfoLog(program));\n\t\t\tgl.deleteProgram(program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tthis.aPositionLocation = gl.getAttribLocation(program, 'aPosition');\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\t\tthis.buffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, quadVertices, gl.STATIC_DRAW);\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.useProgram(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\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(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 = gl.createFramebuffer();\n\t\t}\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t\tthis.emitHook('init');\n\t}\n\n\tprivate emitHook(name: LifecycleMethod, ...args: any[]) {\n\t\tthis.hooks.get(name)?.forEach(hook => hook.call(this, ...args));\n\t}\n\n\ton(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\toff(name: LifecycleMethod, fn: Function) {\n\t\tconst hooks = this.hooks.get(name);\n\t\tif (hooks) {\n\t\t\thooks.splice(hooks.indexOf(fn), 1);\n\t\t}\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 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.emitHook('resize', 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.emitHook('updateResolution', ...resolution);\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 resolveTextureOptions(options?: TextureOptions): ResolvedTextureOptions {\n\t\tconst { gl } = this;\n\t\tconst type = options?.type ?? gl.UNSIGNED_BYTE;\n\t\treturn {\n\t\t\ttype,\n\t\t\tformat: options?.format ?? gl.RGBA,\n\t\t\tinternalFormat:\n\t\t\t\toptions?.internalFormat ??\n\t\t\t\t(type === gl.FLOAT ? gl.RGBA32F : type === gl.HALF_FLOAT ? gl.RGBA16F : gl.RGBA8),\n\t\t\tminFilter: options?.minFilter ?? gl.LINEAR,\n\t\t\tmagFilter: options?.magFilter ?? gl.LINEAR,\n\t\t\twrapS: options?.wrapS ?? gl.CLAMP_TO_EDGE,\n\t\t\twrapT: options?.wrapT ?? gl.CLAMP_TO_EDGE,\n\t\t\tpreserveY: options?.preserveY,\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, format } = textureInfo.options;\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\tformat,\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 in 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.emitHook('initializeUniform', ...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, newValue]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tthis.log(`${name} not in 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(newValue)) {\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 = newValue.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 (newValue.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)(newValue.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 in 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(newValue)) newValue = [newValue];\n\t\t\t\tif (newValue.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${newValue.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...newValue);\n\t\t\t}\n\t\t});\n\t\tthis.emitHook('updateUniforms', ...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);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, options.wrapT);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, options.minFilter);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, options.magFilter);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, options.internalFormat, width, height, historyDepth);\n\t\t} else if (name === INTERMEDIATE_TEXTURE_KEY) {\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\toptions.internalFormat,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\t0,\n\t\t\t\toptions.format,\n\t\t\t\toptions.type,\n\t\t\t\tnull\n\t\t\t);\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: this.resolveTextureOptions(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.emitHook('initializeTexture', ...arguments);\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: { skipHistoryWrite?: boolean }) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t\tthis.emitHook('updateTextures', ...arguments);\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,\n\t\t\t\t\tinfo.options.type,\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\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\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\tsource.data\n\t\t\t\t);\n\t\t\t} else {\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\tinfo.options.internalFormat,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\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\tthis.emitHook('beforeDraw', ...arguments);\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\tthis.emitHook('afterDraw', ...arguments);\n\t}\n\n\tstep(time: number, options?: StepOptions) {\n\t\tthis.emitHook('beforeStep', ...arguments);\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.draw(options);\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\t\t++this.frame;\n\t\tthis.emitHook('afterStep', ...arguments);\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\tthis.emitHook('play');\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\tthis.emitHook('pause');\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.emitHook('reset');\n\t}\n\n\tdestroy() {\n\t\tthis.emitHook('destroy');\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\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","gl","internalFormat","type","glslInjections","plugin","code","program","vertexShader","fragmentShader","quadVertices","args","hook","fn","hooks","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","options","textureInfo","format","size","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","newValue","uniform","glFunctionName","nValues","item","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","isPartial","shouldFlipY","previousFlipY","frameOffsetUniformName","w","h","historyInfo","intermediateInfo","shouldStoreHistory","time","writeIndex","depth","onStepComplete","setStepOptions","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}`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\nconst QUAD_VERTICES = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\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}\ntype ResolvedTextureOptions = Required<Omit<TextureOptions, 'preserveY'>> & Pick<TextureOptions, 'preserveY'>;\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: ResolvedTextureOptions;\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\t| ShaderPad;\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\tcanvas: HTMLCanvasElement | OffscreenCanvas;\n\tinjectGLSL: (code: string) => void;\n\temitHook: (name: LifecycleMethod, ...args: any[]) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'initializeTexture'\n\t| 'initializeUniform'\n\t| 'updateTextures'\n\t| 'updateUniforms'\n\t| 'beforeStep'\n\t| 'afterStep'\n\t| 'beforeDraw'\n\t| 'afterDraw'\n\t| 'updateResolution'\n\t| 'resize'\n\t| 'play'\n\t| 'pause'\n\t| 'reset'\n\t| 'destroy'\n\t| `${string}:${string}`;\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 ShaderPad) {\n\t\treturn { width: source.canvas.width, height: source.canvas.height };\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 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\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\t\tif (this.canvas instanceof OffscreenCanvas) {\n\t\t\tconst wrapDimension = (dimension: 'width' | 'height') => {\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype, dimension)!;\n\t\t\t\tObject.defineProperty(this.canvas, dimension, {\n\t\t\t\t\tget: () => descriptor.get!.call(this.canvas),\n\t\t\t\t\tset: v => {\n\t\t\t\t\t\tdescriptor.set!.call(this.canvas, v);\n\t\t\t\t\t\tthis.updateResolution();\n\t\t\t\t\t},\n\t\t\t\t\tconfigurable: descriptor.configurable,\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t});\n\t\t\t};\n\t\t\twrapDimension('width');\n\t\t\twrapDimension('height');\n\t\t}\n\n\t\tconst gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: gl.getParameter(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 === gl.FLOAT ||\n\t\t\ttype === gl.HALF_FLOAT ||\n\t\t\tinternalFormat === gl.RGBA16F ||\n\t\t\tinternalFormat === gl.RGBA32F ||\n\t\t\tinternalFormat === gl.R16F ||\n\t\t\tinternalFormat === gl.R32F ||\n\t\t\tinternalFormat === gl.RG16F ||\n\t\t\tinternalFormat === gl.RG32F;\n\t\tif (isFloatFormat && !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\tplugins.forEach(plugin =>\n\t\t\t\tplugin(this, {\n\t\t\t\t\tgl,\n\t\t\t\t\tcanvas: this.canvas,\n\t\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t\t},\n\t\t\t\t\temitHook: this.emitHook.bind(this),\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tconst program = this.gl.createProgram();\n\t\tif (!program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tthis.program = program;\n\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, DEFAULT_VERTEX_SHADER_SRC);\n\t\tconst fragmentShader = this.createShader(\n\t\t\tgl.FRAGMENT_SHADER,\n\t\t\tcombineShaderCode(fragmentShaderSrc, glslInjections)\n\t\t);\n\t\tgl.attachShader(program, vertexShader);\n\t\tgl.attachShader(program, fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tgl.deleteShader(vertexShader);\n\t\tgl.deleteShader(fragmentShader);\n\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', gl.getProgramInfoLog(program));\n\t\t\tgl.deleteProgram(program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tthis.aPositionLocation = gl.getAttribLocation(program, 'aPosition');\n\t\tthis.buffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW);\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\t\tgl.enableVertexAttribArray(this.aPositionLocation);\n\t\tgl.vertexAttribPointer(this.aPositionLocation, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.useProgram(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\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\tthis._initializeTexture(INTERMEDIATE_TEXTURE_KEY, this.canvas, {\n\t\t\t...this.textureOptions,\n\t\t});\n\t\tthis.intermediateFbo = gl.createFramebuffer();\n\n\t\tif (this.historyDepth > 0) {\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}\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t\tthis.emitHook('init');\n\t}\n\n\tprivate emitHook(name: LifecycleMethod, ...args: any[]) {\n\t\tthis.hooks.get(name)?.forEach(hook => hook.call(this, ...args));\n\t}\n\n\ton(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\toff(name: LifecycleMethod, fn: Function) {\n\t\tconst hooks = this.hooks.get(name);\n\t\tif (hooks) {\n\t\t\thooks.splice(hooks.indexOf(fn), 1);\n\t\t}\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 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.emitHook('resize', 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.resizeTexture(INTERMEDIATE_TEXTURE_KEY, ...resolution);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis.resizeTexture(HISTORY_TEXTURE_KEY, ...resolution);\n\t\t}\n\t\tthis.emitHook('updateResolution', ...resolution);\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 resolveTextureOptions(options?: TextureOptions): ResolvedTextureOptions {\n\t\tconst { gl } = this;\n\t\tconst type = options?.type ?? gl.UNSIGNED_BYTE;\n\t\treturn {\n\t\t\ttype,\n\t\t\tformat: options?.format ?? gl.RGBA,\n\t\t\tinternalFormat:\n\t\t\t\toptions?.internalFormat ??\n\t\t\t\t(type === gl.FLOAT ? gl.RGBA32F : type === gl.HALF_FLOAT ? gl.RGBA16F : gl.RGBA8),\n\t\t\tminFilter: options?.minFilter ?? gl.LINEAR,\n\t\t\tmagFilter: options?.magFilter ?? gl.LINEAR,\n\t\t\twrapS: options?.wrapS ?? gl.CLAMP_TO_EDGE,\n\t\t\twrapT: options?.wrapT ?? gl.CLAMP_TO_EDGE,\n\t\t\tpreserveY: options?.preserveY,\n\t\t};\n\t}\n\n\tprivate getPixelArray(type: number, size: number): ArrayBufferView {\n\t\treturn type === this.gl.FLOAT\n\t\t\t? new Float32Array(size)\n\t\t\t: type === this.gl.HALF_FLOAT\n\t\t\t? new Uint16Array(size)\n\t\t\t: new Uint8Array(size);\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, format } = textureInfo.options;\n\t\tconst transparent = this.getPixelArray(type, textureInfo.width * textureInfo.height * 4);\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\tformat,\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 in 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.emitHook('initializeUniform', ...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, newValue]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tthis.log(`${name} not in 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(newValue)) {\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 = newValue.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 (newValue.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)(newValue.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 in 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(newValue)) newValue = [newValue];\n\t\t\t\tif (newValue.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${newValue.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...newValue);\n\t\t\t}\n\t\t});\n\t\tthis.emitHook('updateUniforms', ...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);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, options.wrapT);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, options.minFilter);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, options.magFilter);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, options.internalFormat, width, height, historyDepth);\n\t\t} else if (name === INTERMEDIATE_TEXTURE_KEY) {\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\toptions.internalFormat,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\t0,\n\t\t\t\toptions.format,\n\t\t\t\toptions.type,\n\t\t\t\tnull\n\t\t\t);\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: this.resolveTextureOptions(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.emitHook('initializeTexture', ...arguments);\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: { skipHistoryWrite?: boolean }) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t\tthis.emitHook('updateTextures', ...arguments);\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\tlet nonShaderPadSource = source as Exclude<UpdateTextureSource, ShaderPad>;\n\t\tif (source instanceof ShaderPad) {\n\t\t\tconst sourceIntermediateInfo = source.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\n\t\t\tif (source.gl === this.gl) {\n\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, sourceIntermediateInfo.texture);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Different contexts - transfer via readPixels to preserve precision.\n\t\t\tconst {\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\toptions: { format, type },\n\t\t\t} = sourceIntermediateInfo;\n\t\t\tconst pixels = this.getPixelArray(type, width * height * 4);\n\t\t\tsource.gl.bindFramebuffer(source.gl.FRAMEBUFFER, source.intermediateFbo);\n\t\t\tsource.gl.readPixels(0, 0, width, height, format, type, pixels);\n\t\t\tsource.gl.bindFramebuffer(source.gl.FRAMEBUFFER, null);\n\t\t\tnonShaderPadSource = { data: pixels, width, height };\n\t\t}\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(nonShaderPadSource);\n\t\tif (!width || !height) return;\n\n\t\tconst isPartial = 'isPartial' in nonShaderPadSource && nonShaderPadSource.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 nonShaderPadSource && nonShaderPadSource.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,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t((nonShaderPadSource as PartialCustomTexture).data ??\n\t\t\t\t\t\t(nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>)) 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\tif (isPartial) {\n\t\t\t\tconst partialSource = nonShaderPadSource as PartialCustomTexture;\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\tpartialSource.x ?? 0,\n\t\t\t\t\tpartialSource.y ?? 0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\tpartialSource.data\n\t\t\t\t);\n\t\t\t} else {\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\tinfo.options.internalFormat,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.options.format,\n\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t((nonShaderPadSource as PartialCustomTexture).data ??\n\t\t\t\t\t\t(nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>)) 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\tthis.emitHook('beforeDraw', ...arguments);\n\t\tconst gl = this.gl;\n\t\tconst w = gl.drawingBufferWidth;\n\t\tconst h = gl.drawingBufferHeight;\n\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.intermediateFbo);\n\t\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, intermediateInfo.texture, 0);\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\tconst historyInfo = this.textures.get(HISTORY_TEXTURE_KEY);\n\t\tif (historyInfo && !options?.skipHistoryWrite) {\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\t\t}\n\n\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n\t\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\tthis.emitHook('afterDraw', ...arguments);\n\t}\n\n\tstep(time: number, options?: StepOptions) {\n\t\tthis.emitHook('beforeStep', ...arguments);\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.draw(options);\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\t\t++this.frame;\n\t\tthis.emitHook('afterStep', ...arguments);\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\tthis.emitHook('play');\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\tthis.emitHook('pause');\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.emitHook('reset');\n\t}\n\n\tdestroy() {\n\t\tthis.emitHook('destroy');\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\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","QUAD_VERTICES","HISTORY_TEXTURE_KEY","INTERMEDIATE_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","ShaderPad","stringFrom","name","_ShaderPad","fragmentShaderSrc","canvas","plugins","history","debug","textureOptions","htmlCanvas","wrapDimension","dimension","descriptor","v","gl","internalFormat","type","glslInjections","plugin","code","program","vertexShader","fragmentShader","args","hook","fn","hooks","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","options","size","textureInfo","format","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","newValue","uniform","glFunctionName","nValues","item","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","nonShaderPadSource","sourceIntermediateInfo","pixels","isPartial","shouldFlipY","previousFlipY","frameOffsetUniformName","partialSource","w","h","intermediateInfo","historyInfo","time","writeIndex","depth","onStepComplete","setStepOptions","loop"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a}from"./chunk-
|
|
1
|
+
import{a}from"./chunk-5CBGNOA3.mjs";export{a as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/plugins/face.d.mts
CHANGED
package/dist/plugins/face.d.ts
CHANGED
package/dist/plugins/face.js
CHANGED
|
@@ -1,87 +1,64 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var le=Object.create;var D=Object.defineProperty;var ue=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var Ee=Object.getPrototypeOf,de=Object.prototype.hasOwnProperty;var _e=(t,e)=>{for(var n in e)D(t,n,{get:e[n],enumerable:!0})},q=(t,e,n,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of fe(e))!de.call(t,a)&&a!==n&&D(t,a,{get:()=>e[a],enumerable:!(m=ue(e,a))||m.enumerable});return t};var J=(t,e,n)=>(n=t!=null?le(Ee(t)):{},q(e||!t||!t.__esModule?D(n,"default",{value:t,enumerable:!0}):n,t)),Te=t=>q(D({},"__esModule",{value:!0}),t);var he={};_e(he,{default:()=>ve});module.exports=Te(he);var be={data:new Uint8Array(4),width:1,height:1};function U(t){return t instanceof HTMLVideoElement||t instanceof HTMLImageElement||t instanceof HTMLCanvasElement||t instanceof OffscreenCanvas}function Z(t){return JSON.stringify(t,Object.keys(t).sort())}function P(t,e,n,m,a=0){let i=1/0,l=-1/0,c=1/0,s=-1/0,E=0,_=0;for(let T of n){let d=(a+e*m+T)*4,g=t[d],N=t[d+1];i=Math.min(i,g),l=Math.max(l,g),c=Math.min(c,N),s=Math.max(s,N),E+=t[d+2],_+=t[d+3]}return[(i+l)/2,(c+s)/2,E/n.length,_/n.length]}var H=null;function Q(){return H||(H=import("@mediapipe/tasks-vision").then(({FilesetResolver:t})=>t.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.22-rc.20250304/wasm"))),H}function ee(t){return{historyParams:t?", framesAgo":"",fn:t?(m,a,i,l)=>{let c=i.replace(/\w+ /g,""),s=i?`${i}, int framesAgo`:"int framesAgo",E=c?`${c}, 0`:"0";return`${m} ${a}(${s}) {
|
|
2
|
+
${l}
|
|
3
|
+
}
|
|
4
|
+
${m} ${a}(${i}) { return ${a}(${E}); }`}:(m,a,i,l)=>`${m} ${a}(${i}) {
|
|
5
|
+
${l}
|
|
6
|
+
}`}}var pe=`#version 300 es
|
|
2
7
|
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
|
|
8
|
+
void main() { gl_Position = vec4(a_pos * 2.0 - 1.0, 0.0, 1.0); }`,Ae=`#version 300 es
|
|
6
9
|
precision mediump float;
|
|
7
10
|
uniform vec4 u_color;
|
|
8
11
|
out vec4 outColor;
|
|
9
|
-
void main() { outColor = u_color; }
|
|
12
|
+
void main() { outColor = u_color; }`,S=478,Fe=2,F=S+Fe,O=512,M=1,ne=[336,296,334,293,300,276,283,282,295,285],ae=[362,398,384,385,386,387,388,466,263,249,390,373,374,380,381,382],re=[70,63,105,66,107,55,65,52,53,46],se=[33,246,161,160,159,158,157,173,133,155,154,153,145,144,163,7],ie=[61,185,40,39,37,0,267,269,270,409,291,375,321,405,314,17,84,181,91,146],Y=[78,191,80,81,82,13,312,311,310,415,308,324,318,402,317,14,87,178,88,95],ge=Array.from({length:S},(t,e)=>e),h={LEFT_EYEBROW:ne,LEFT_EYE:ae,LEFT_EYE_CENTER:473,RIGHT_EYEBROW:re,RIGHT_EYE:se,RIGHT_EYE_CENTER:468,NOSE_TIP:4,OUTER_MOUTH:ie,INNER_MOUTH:Y,FACE_CENTER:S,MOUTH_CENTER:S+1},oe=["BACKGROUND","LEFT_EYEBROW","RIGHT_EYEBROW","LEFT_EYE","RIGHT_EYE","OUTER_MOUTH","INNER_MOUTH"],ce=oe.length-1,x=Object.fromEntries(oe.map((t,e)=>[t,e/ce])),te=.5/ce,Re={modelPath:"https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task",maxFaces:1,minFaceDetectionConfidence:.5,minFacePresenceConfidence:.5,minTrackingConfidence:.5,outputFaceBlendshapes:!1,outputFacialTransformationMatrixes:!1};function v(t){let e=[];for(let n=1;n<t.length-1;++n)e.push(t[0],t[n],t[n+1]);return e}var p=null;function Le(t){if(!p){let e=t.FACE_LANDMARKS_TESSELATION,n=[];for(let a=0;a<e.length-2;a+=3)n.push(e[a].start,e[a+1].start,e[a+2].start);let m=t.FACE_LANDMARKS_FACE_OVAL.map(({start:a})=>a);p=Object.fromEntries(Object.entries({LEFT_EYEBROW:v(ne),RIGHT_EYEBROW:v(re),LEFT_EYE:v(ae),RIGHT_EYE:v(se),OUTER_MOUTH:v(ie),INNER_MOUTH:v(Y),TESSELATION:n,OVAL:v(m)}).map(([a,i])=>[a,{triangles:i,vertices:new Float32Array(i.length*2)}]))}}var C=new Map;function xe(t){let e=t.mask.canvas.getContext("webgl2",{antialias:!1,preserveDrawingBuffer:!0}),n=e.createShader(e.VERTEX_SHADER);e.shaderSource(n,pe),e.compileShader(n);let m=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(m,Ae),e.compileShader(m);let a=e.createProgram();e.attachShader(a,n),e.attachShader(a,m),e.linkProgram(a),e.deleteShader(n),e.deleteShader(m);let i=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,i);let l=e.getAttribLocation(a,"a_pos");e.enableVertexAttribArray(l),e.vertexAttribPointer(l,2,e.FLOAT,!1,0,0);let c=e.getUniformLocation(a,"u_color");e.useProgram(a),e.enable(e.BLEND),e.blendEquation(e.MAX),t.mask={...t.mask,gl:e,program:a,positionBuffer:i,colorLocation:c}}function L(t,e,n,m,a,i){let{triangles:l,vertices:c}=e,{mask:{gl:s,colorLocation:E},landmarks:_}=t,{data:T}=_;for(let d=0;d<l.length;++d){let g=(M+n*F+l[d])*4;c[d*2]=T[g],c[d*2+1]=T[g+1]}s.bufferData(s.ARRAY_BUFFER,c,s.DYNAMIC_DRAW),s.uniform4f(E,m,a,i,1),s.drawArrays(s.TRIANGLES,0,l.length)}function Me(t,e){let n=t.landmarks.data,m=e.length;n[0]=m;for(let a=0;a<m;++a){let i=e[a];for(let s=0;s<S;++s){let E=i[s],_=(M+a*F+s)*4;n[_]=E.x,n[_+1]=1-E.y,n[_+2]=E.z??0,n[_+3]=E.visibility??1}let l=P(n,a,ge,F,M);n.set(l,(M+a*F+h.FACE_CENTER)*4);let c=P(n,a,Y,F,1);n.set(c,(M+a*F+h.MOUTH_CENTER)*4)}t.state.nFaces=m}function ke(t){if(!p)return;let{mask:e,canvas:n,maxFaces:m,state:{nFaces:a}}=t,{gl:i,canvas:l}=e;l.width=n.width,l.height=n.height,i.viewport(0,0,l.width,l.height),i.clearColor(0,0,0,0),i.clear(i.COLOR_BUFFER_BIT);for(let c=0;c<a;++c){let s=(c+1)/m;L(t,p.TESSELATION,c,0,.5,s),L(t,p.OVAL,c,0,1,s),L(t,p.LEFT_EYEBROW,c,x.LEFT_EYEBROW,0,s),L(t,p.RIGHT_EYEBROW,c,x.RIGHT_EYEBROW,0,s),L(t,p.LEFT_EYE,c,x.LEFT_EYE,0,s),L(t,p.RIGHT_EYE,c,x.RIGHT_EYE,0,s),L(t,p.OUTER_MOUTH,c,x.OUTER_MOUTH,0,s),L(t,p.INNER_MOUTH,c,x.INNER_MOUTH,0,s)}}function Oe(t){let{textureName:e,options:{history:n,...m}={}}=t,a={...Re,...m},i=Z({...a,textureName:e}),l=a.maxFaces*F+M,c=Math.ceil(l/O);return function(s,E){let{injectGLSL:_,gl:T,emitHook:d}=E,g=C.get(i),N=g?.landmarks.data??new Float32Array(O*c*4),B=g?.mask.canvas??new OffscreenCanvas(1,1),r=null,w=!1;function b(){if(!r)return;let o=r.state.nFaces,f=o*F+M,A=Math.ceil(f/O);s.updateTextures({u_faceLandmarksTex:{data:r.landmarks.data,width:O,height:A,isPartial:!0},u_faceMask:r.mask.canvas},{skipHistoryWrite:w}),s.updateUniforms({u_nFaces:o}),d("face:result",r.state.result)}async function me(){if(C.has(i))r=C.get(i);else{let[o,{FaceLandmarker:f}]=await Promise.all([Q(),import("@mediapipe/tasks-vision")]),A=new OffscreenCanvas(1,1);r={landmarker:await f.createFromOptions(o,{baseOptions:{modelAssetPath:a.modelPath,delegate:"GPU"},canvas:A,runningMode:"VIDEO",numFaces:a.maxFaces,minFaceDetectionConfidence:a.minFaceDetectionConfidence,minFacePresenceConfidence:a.minFacePresenceConfidence,minTrackingConfidence:a.minTrackingConfidence,outputFaceBlendshapes:a.outputFaceBlendshapes,outputFacialTransformationMatrixes:a.outputFacialTransformationMatrixes}),canvas:A,subscribers:new Map,maxFaces:a.maxFaces,state:{runningMode:"VIDEO",source:null,videoTime:-1,resultTimestamp:0,result:null,pending:Promise.resolve(),nFaces:0},landmarks:{data:N,textureHeight:c},mask:{canvas:B}},Le(f),xe(r),C.set(i,r)}r.subscribers.set(b,!1)}let G=me(),W=0;async function V(o){let f=performance.now(),A=++W;await G,r&&(r.state.pending=r.state.pending.then(async()=>{if(A!==W||!r)return;let y=o instanceof HTMLVideoElement?"VIDEO":"IMAGE";r.state.runningMode!==y&&(r.state.runningMode=y,await r.landmarker.setOptions({runningMode:y}));let $=!1;if(o!==r.state.source?(r.state.source=o,r.state.videoTime=-1,$=!0):o instanceof HTMLVideoElement?o.currentTime!==r.state.videoTime&&(r.state.videoTime=o.currentTime,$=!0):o instanceof HTMLImageElement||f-r.state.resultTimestamp>2&&($=!0),$){let I;if(o instanceof HTMLVideoElement){if(o.videoWidth===0||o.videoHeight===0||o.readyState<2)return;I=r.landmarker.detectForVideo(o,f)}else{if(o.width===0||o.height===0)return;I=r.landmarker.detect(o)}if(I){r.state.resultTimestamp=f,r.state.result=I,Me(r,I.faceLandmarks),ke(r);for(let X of r.subscribers.keys())X(),r.subscribers.set(X,!0)}}else r.state.result&&!r.subscribers.get(b)&&(b(),r.subscribers.set(b,!0))}),await r.state.pending)}s.on("init",()=>{s.initializeUniform("u_maxFaces","int",a.maxFaces),s.initializeUniform("u_nFaces","int",0),s.initializeTexture("u_faceLandmarksTex",{data:N,width:O,height:c},{internalFormat:T.RGBA32F,type:T.FLOAT,minFilter:T.NEAREST,magFilter:T.NEAREST,history:n}),s.initializeTexture("u_faceMask",B,{minFilter:T.NEAREST,magFilter:T.NEAREST,history:n}),G.then(()=>d("face:ready"))}),s.on("initializeTexture",(o,f)=>{o===e&&U(f)&&V(f)}),s.on("updateTextures",(o,f)=>{let A=o[e];U(A)&&(w=f?.skipHistoryWrite??!1,V(A))}),s.on("destroy",()=>{r&&(r.subscribers.delete(b),r.subscribers.size===0&&(r.landmarker.close(),r.mask.gl.deleteProgram(r.mask.program),r.mask.gl.deleteBuffer(r.mask.positionBuffer),C.delete(i))),r=null});let{fn:u,historyParams:R}=ee(n),K=n?"_sampleFaceMask(pos, framesAgo)":"texture(u_faceMask, pos)",k=(o,f=o)=>`vec4 mask = ${K};
|
|
13
|
+
float faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;
|
|
14
|
+
return (mask.r > ${(x[o]-te).toFixed(4)} && mask.r < ${(x[f]+te).toFixed(4)}) ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`,z=o=>`vec4 mask = ${K};
|
|
10
15
|
float faceIndex = floor(mask.b * float(u_maxFaces) + 0.5) - 1.0;
|
|
11
|
-
return
|
|
16
|
+
return mask.g > ${o.toFixed(2)} ? vec2(1.0, faceIndex) : vec2(0.0, -1.0);`,j=(o,f)=>`vec2 left = ${o}(pos${R});
|
|
17
|
+
return left.x > 0.0 ? left : ${f}(pos${R});`;_(`
|
|
12
18
|
uniform int u_maxFaces;
|
|
13
19
|
uniform int u_nFaces;
|
|
14
|
-
uniform sampler2D u_faceLandmarksTex
|
|
15
|
-
uniform
|
|
16
|
-
|
|
17
|
-
|
|
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}
|
|
22
|
-
|
|
23
|
-
vec4 faceLandmark(int faceIndex, int landmarkIndex) {
|
|
24
|
-
int i = faceIndex * ${A} + landmarkIndex;
|
|
25
|
-
int x = i % ${I};
|
|
26
|
-
int y = i / ${I};
|
|
27
|
-
return texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
vec2 leftEyebrowAt(vec2 pos) {
|
|
31
|
-
${L("LEFT_EYEBROW")}
|
|
32
|
-
}
|
|
20
|
+
uniform highp sampler2D${n?"Array":""} u_faceLandmarksTex;${n?`
|
|
21
|
+
uniform int u_faceLandmarksTexFrameOffset;`:""}
|
|
22
|
+
uniform sampler2D${n?"Array":""} u_faceMask;${n?`
|
|
23
|
+
uniform int u_faceMaskFrameOffset;`:""}
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
${L("LEFT_EYE")}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
vec2 rightEyeAt(vec2 pos) {
|
|
43
|
-
${L("RIGHT_EYE")}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
vec2 lipsAt(vec2 pos) {
|
|
47
|
-
${L("OUTER_MOUTH")}
|
|
48
|
-
}
|
|
25
|
+
#define FACE_LANDMARK_L_EYE_CENTER ${h.LEFT_EYE_CENTER}
|
|
26
|
+
#define FACE_LANDMARK_R_EYE_CENTER ${h.RIGHT_EYE_CENTER}
|
|
27
|
+
#define FACE_LANDMARK_NOSE_TIP ${h.NOSE_TIP}
|
|
28
|
+
#define FACE_LANDMARK_FACE_CENTER ${h.FACE_CENTER}
|
|
29
|
+
#define FACE_LANDMARK_MOUTH_CENTER ${h.MOUTH_CENTER}
|
|
49
30
|
|
|
50
|
-
|
|
51
|
-
${
|
|
31
|
+
${u("int","nFacesAt","",n?`
|
|
32
|
+
int layer = (u_faceLandmarksTexFrameOffset - framesAgo + ${n}) % ${n};
|
|
33
|
+
return int(texelFetch(u_faceLandmarksTex, ivec3(0, 0, layer), 0).r + 0.5);`:`
|
|
34
|
+
return int(texelFetch(u_faceLandmarksTex, ivec2(0, 0), 0).r + 0.5);`)}
|
|
35
|
+
${u("vec4","faceLandmark","int faceIndex, int landmarkIndex",`int i = ${M} + faceIndex * ${F} + landmarkIndex;
|
|
36
|
+
int x = i % ${O};
|
|
37
|
+
int y = i / ${O};${n?`
|
|
38
|
+
int layer = (u_faceLandmarksTexFrameOffset - framesAgo + ${n}) % ${n};
|
|
39
|
+
return texelFetch(u_faceLandmarksTex, ivec3(x, y, layer), 0);`:`
|
|
40
|
+
return texelFetch(u_faceLandmarksTex, ivec2(x, y), 0);`}`)}
|
|
41
|
+
${n?`
|
|
42
|
+
vec4 _sampleFaceMask(vec2 pos, int framesAgo) {
|
|
43
|
+
int layer = (u_faceMaskFrameOffset - framesAgo + ${n}) % ${n};
|
|
44
|
+
return texture(u_faceMask, vec3(pos, float(layer)));
|
|
52
45
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
vec2 eyeAt(vec2 pos) {
|
|
72
|
-
vec2 left = leftEyeAt(pos);
|
|
73
|
-
return left.x > 0.0 ? left : rightEyeAt(pos);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
vec2 eyebrowAt(vec2 pos) {
|
|
77
|
-
vec2 left = leftEyebrowAt(pos);
|
|
78
|
-
return left.x > 0.0 ? left : rightEyebrowAt(pos);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
float inEyebrow(vec2 pos) { return eyebrowAt(pos).x; }
|
|
82
|
-
float inEye(vec2 pos) { return eyeAt(pos).x; }
|
|
83
|
-
float inOuterMouth(vec2 pos) { return outerMouthAt(pos).x; }
|
|
84
|
-
float inInnerMouth(vec2 pos) { return innerMouthAt(pos).x; }
|
|
85
|
-
float inLips(vec2 pos) { return lipsAt(pos).x; }
|
|
86
|
-
float inFace(vec2 pos) { return faceAt(pos).x; }`)}}var Ne=Le;
|
|
46
|
+
`:""}
|
|
47
|
+
${u("vec2","leftEyebrowAt","vec2 pos",k("LEFT_EYEBROW"))}
|
|
48
|
+
${u("vec2","rightEyebrowAt","vec2 pos",k("RIGHT_EYEBROW"))}
|
|
49
|
+
${u("vec2","leftEyeAt","vec2 pos",k("LEFT_EYE"))}
|
|
50
|
+
${u("vec2","rightEyeAt","vec2 pos",k("RIGHT_EYE"))}
|
|
51
|
+
${u("vec2","lipsAt","vec2 pos",k("OUTER_MOUTH"))}
|
|
52
|
+
${u("vec2","outerMouthAt","vec2 pos",k("OUTER_MOUTH","INNER_MOUTH"))}
|
|
53
|
+
${u("vec2","innerMouthAt","vec2 pos",k("INNER_MOUTH"))}
|
|
54
|
+
${u("vec2","faceOvalAt","vec2 pos",z(.75))}
|
|
55
|
+
${u("vec2","faceAt","vec2 pos",z(.25))}
|
|
56
|
+
${u("vec2","eyeAt","vec2 pos",j("leftEyeAt","rightEyeAt"))}
|
|
57
|
+
${u("vec2","eyebrowAt","vec2 pos",j("leftEyebrowAt","rightEyebrowAt"))}
|
|
58
|
+
${u("float","inEyebrow","vec2 pos",`return eyebrowAt(pos${R}).x;`)}
|
|
59
|
+
${u("float","inEye","vec2 pos",`return eyeAt(pos${R}).x;`)}
|
|
60
|
+
${u("float","inOuterMouth","vec2 pos",`return outerMouthAt(pos${R}).x;`)}
|
|
61
|
+
${u("float","inInnerMouth","vec2 pos",`return innerMouthAt(pos${R}).x;`)}
|
|
62
|
+
${u("float","inLips","vec2 pos",`return lipsAt(pos${R}).x;`)}
|
|
63
|
+
${u("float","inFace","vec2 pos",`return faceAt(pos${R}).x;`)}`)}}var ve=Oe;
|
|
87
64
|
//# sourceMappingURL=face.js.map
|