shaderpad 1.0.0-beta.66 → 1.0.0-beta.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-BWFX3DVI.mjs → chunk-Q5SJ2PJL.mjs} +1 -1
- package/dist/{chunk-BWFX3DVI.mjs.map → chunk-Q5SJ2PJL.mjs.map} +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/plugins/autosize.d.mts +1 -1
- package/dist/plugins/autosize.d.ts +1 -1
- package/dist/plugins/autosize.js +1 -1
- package/dist/plugins/autosize.js.map +1 -1
- package/dist/plugins/autosize.mjs +1 -1
- package/dist/plugins/autosize.mjs.map +1 -1
- package/dist/plugins/face.js +36 -36
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +31 -31
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +1 -1
- package/dist/plugins/segmenter.js.map +1 -1
- package/dist/plugins/segmenter.mjs +1 -1
- package/package.json +6 -12
- package/LICENSE +0 -21
- package/README.md +0 -821
|
@@ -7,4 +7,4 @@ void main() {
|
|
|
7
7
|
}`,N=[["8UI","UNSIGNED_BYTE"],["8I","BYTE"],["16UI","UNSIGNED_SHORT"],["16I","SHORT"],["16F","HALF_FLOAT"],["32UI","UNSIGNED_INT"],["32I","INT"],["32F","FLOAT"],["8","UNSIGNED_BYTE"]],w={float:"f",int:"i",uint:"ui"};function D(h){return h&&N.find(([t])=>h.endsWith(t))?.[1]}var I=Symbol("u_history"),p=Symbol("__SHADERPAD_BUFFER"),A=new WeakMap;function C(h,t){if(!t?.length)return h;let e=h.split(`
|
|
8
8
|
`),r=e.findLastIndex(i=>{let s=i.trimStart();return s.startsWith("precision ")||s.startsWith("#version ")})+1;return e.splice(r,0,...t),e.join(`
|
|
9
9
|
`)}function G(h){return h instanceof WebGLTexture?{width:0,height:0}:h instanceof _?{width:h.canvas.width,height:h.canvas.height}:h instanceof HTMLVideoElement?{width:h.videoWidth,height:h.videoHeight}:h instanceof HTMLImageElement?{width:h.naturalWidth??h.width,height:h.naturalHeight??h.height}:{width:h.width,height:h.height}}function E(h){return typeof h=="symbol"?h.description??"":h}var _=class h{isHeadless=!1;isTouchDevice=!1;gl;glHelpers;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;vao=null;program=null;animationFrameId;eventListeners=new Map;frame=0;startTime=Number.NaN;isPlaying=!1;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;resolutionObserver=null;hooks=new Map;historyDepth=0;textureOptions;debug;cursorTarget;intermediateFbo=null;constructor(t,{canvas:e,plugins:r,history:i,debug:s,cursorTarget:a,...o}={}){if(e&&"getContext"in e)this.canvas=e;else{let{width:f=1,height:m=1}=e||{};this.canvas=new OffscreenCanvas(f,m),this.isHeadless=!0}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.glHelpers={typeToArray:new Map([[n.FLOAT,Float32Array],[n.HALF_FLOAT,Uint16Array],[n.UNSIGNED_SHORT,Uint16Array],[n.SHORT,Int16Array],[n.BYTE,Int8Array],[n.UNSIGNED_INT,Uint32Array],[n.INT,Int32Array]]),typeToInternalFormatString:new Map([[n.FLOAT,"RGBA32F"],[n.HALF_FLOAT,"RGBA16F"],[n.UNSIGNED_SHORT,"RGBA32UI"],[n.SHORT,"RGBA32I"],[n.BYTE,"RGBA32I"],[n.UNSIGNED_INT,"RGBA32UI"],[n.INT,"RGBA32I"]]),unsignedIntTypes:new Set([n.UNSIGNED_BYTE,n.UNSIGNED_SHORT,n.UNSIGNED_INT])};let u=A.get(this.canvas);u||(u={textureUnitPool:{free:[],next:0,max:n.getParameter(n.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},instances:new Set([this])},A.set(this.canvas,u)),this.textureUnitPool=u.textureUnitPool,u.instances.add(this),this.textureOptions=o,i&&(this.historyDepth=i),this.debug=s??(typeof process<"u"&&!1),this.cursorTarget=a??(this.canvas instanceof HTMLCanvasElement?this.canvas:void 0),this.animationFrameId=null;let g=[];r&&r.forEach(f=>f(this,{gl:n,canvas:this.canvas,injectGLSL:m=>{g.push(m)},emitHook:this.emitHook.bind(this),updateTexturesInternal:this.updateTexturesInternal.bind(this)}));let l=this.gl.createProgram();if(!l)throw new Error("Failed to create WebGL program");this.program=l;let T=this.createShader(this.gl.VERTEX_SHADER,O),v=this.createShader(n.FRAGMENT_SHADER,C(t,g));if(n.attachShader(l,T),n.attachShader(l,v),n.bindAttribLocation(l,0,"a_position"),n.linkProgram(l),n.deleteShader(T),n.deleteShader(v),!n.getProgramParameter(l,n.LINK_STATUS))throw console.error("Program link error:",n.getProgramInfoLog(l)),n.deleteProgram(l),new Error("Failed to link WebGL program");if(this.vao=n.createVertexArray(),n.bindVertexArray(this.vao),this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.buffer),n.bufferData(n.ARRAY_BUFFER,new Float32Array([-1,-1,3,-1,-1,3]),n.STATIC_DRAW),n.enableVertexAttribArray(0),n.vertexAttribPointer(0,2,n.FLOAT,!1,0,0),n.viewport(0,0,n.drawingBufferWidth,n.drawingBufferHeight),n.useProgram(l),this.canvas instanceof HTMLCanvasElement)this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]});else{let f=m=>{let c=Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype,m),d=this.canvas;Object.defineProperty(d,m,{get:()=>c.get.call(d),set:x=>{c.set.call(d,x);let b=A.get(d);if(b)for(let y of b.instances)y.updateResolution()},configurable:c.configurable,enumerable:c.enumerable})};f("width"),f("height")}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(p,this.canvas,{...this.textureOptions}),this.intermediateFbo=n.createFramebuffer(),this.bindIntermediate(),n.bindFramebuffer(n.FRAMEBUFFER,null),this.historyDepth>0&&this._initializeTexture(I,this.canvas,{history:this.historyDepth,...this.textureOptions}),this.cursorTarget&&this.addEventListeners(),this.emitHook("_init")}resolveGLConstant(t){let e=this.gl[t];if(e===void 0)throw new Error(`Unknown GL constant: ${t}`);return e}emitHook(t,...e){this.hooks.get(t)?.forEach(r=>r.call(this,...e))}on(t,e){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(e)}off(t,e){let r=this.hooks.get(t);if(r){let i=r.indexOf(e);i>=0&&r.splice(i,1)}}createShader(t,e){let r=this.gl.createShader(t);if(this.gl.shaderSource(r,e),this.gl.compileShader(r),!this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",e),console.error(this.gl.getShaderInfoLog(r)),this.gl.deleteShader(r),new Error("Shader compilation failed");return r}getCursorTargetRect(){let t=this.cursorTarget;return t===window?{left:0,top:0,width:window.innerWidth,height:window.innerHeight}:t.getBoundingClientRect()}addEventListeners(){if(!this.cursorTarget)return;let t=(r,i)=>{if(!this.uniforms.has("u_cursor"))return;let s=this.getCursorTargetRect(),a=(r-s.left)/s.width,o=1-(i-s.top)/s.height;this.cursorPosition[0]=Math.max(0,Math.min(1,a)),this.cursorPosition[1]=Math.max(0,Math.min(1,o)),this.updateUniforms({u_cursor:this.cursorPosition})},e=(r,i,s)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=r,r){let a=this.getCursorTargetRect(),o=i,n=s;this.clickPosition[0]=Math.max(0,Math.min(1,(o-a.left)/a.width)),this.clickPosition[1]=Math.max(0,Math.min(1,1-(n-a.top)/a.height))}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",r=>{let i=r;this.isTouchDevice||t(i.clientX,i.clientY)}),this.eventListeners.set("mousedown",r=>{let i=r;this.isTouchDevice||i.button===0&&(this.isMouseDown=!0,e(!0,i.clientX,i.clientY))}),this.eventListeners.set("mouseup",r=>{let i=r;this.isTouchDevice||i.button===0&&e(!1)}),this.eventListeners.set("touchmove",r=>{let i=r;i.touches.length>0&&t(i.touches[0].clientX,i.touches[0].clientY)}),this.eventListeners.set("touchstart",r=>{let i=r;this.isTouchDevice=!0,i.touches.length>0&&(t(i.touches[0].clientX,i.touches[0].clientY),e(!0,i.touches[0].clientX,i.touches[0].clientY))}),this.eventListeners.set("touchend",r=>{r.touches.length===0&&e(!1)}),this.eventListeners.forEach((r,i)=>{this.cursorTarget.addEventListener(i,r)})}updateResolution(){let t=[this.gl.drawingBufferWidth,this.gl.drawingBufferHeight];this.gl.viewport(0,0,...t),this.uniforms.has("u_resolution")?this.updateUniforms({u_resolution:t}):this.initializeUniform("u_resolution","float",t),this.resizeTexture(p,...t),this.historyDepth>0&&this.resizeTexture(I,...t),this.emitHook("updateResolution",...t)}resizeTexture(t,e,r){let i=this.textures.get(t);if(!i||i.width===e&&i.height===r)return;this.gl.deleteTexture(i.texture),i.width=e,i.height=r;let{texture:s}=this.createTexture(t,i);i.texture=s,i.history&&(i.history.writeIndex=0,this.clearHistoryTextureLayers(i))}reserveTextureUnit(t){let e=this.textures.get(t);if(e)return e.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}resolveTextureOptions(t){let{gl:e}=this,r=t?.internalFormat,i=t?.type??D(r)??"UNSIGNED_BYTE",s=this.resolveGLConstant(i),a=r??this.glHelpers.typeToInternalFormatString.get(s)??"RGBA8",o=/^(R|RG|RGB|RGBA)(8|16|32)(UI|I)$/.test(a),n=t?.format??(o?"RGBA_INTEGER":"RGBA"),u={type:s,format:this.resolveGLConstant(n),internalFormat:this.resolveGLConstant(a),minFilter:this.resolveGLConstant(t?.minFilter??"LINEAR"),magFilter:this.resolveGLConstant(t?.magFilter??"LINEAR"),wrapS:this.resolveGLConstant(t?.wrapS??"CLAMP_TO_EDGE"),wrapT:this.resolveGLConstant(t?.wrapT??"CLAMP_TO_EDGE"),preserveY:t?.preserveY,isIntegerColorFormat:o};if((u.internalFormat===e.RGBA16F||u.internalFormat===e.RGBA32F)&&!e.getExtension("EXT_color_buffer_float"))throw new Error("Missing EXT_color_buffer_float.");return u}getPixelArray(t,e){let r=this.glHelpers.typeToArray.get(t)??Uint8Array;return new r(e)}isNotRgba(t){return t!==this.gl.RGBA&&t!==this.gl.RGBA_INTEGER}clearHistoryTextureLayers(t){if(!t.history)return;let e=this.gl,{type:r,format:i}=t.options,s=this.getPixelArray(r,t.width*t.height*4);e.activeTexture(e.TEXTURE0+t.unitIndex),e.bindTexture(e.TEXTURE_2D_ARRAY,t.texture);let a=this.isNotRgba(i),o;a&&(o=e.getParameter(e.UNPACK_ALIGNMENT),e.pixelStorei(e.UNPACK_ALIGNMENT,1));for(let n=0;n<t.history.depth;++n)e.texSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,n,t.width,t.height,1,i,r,s);a&&e.pixelStorei(e.UNPACK_ALIGNMENT,o)}initializeUniform(t,e,r,i){let s=i?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(!w[e])throw new Error(`Invalid uniform type: ${e}. Expected one of: ${Object.keys(w).join(", ")}.`);if(s&&!(Array.isArray(r)&&r.length===s))throw new Error(`${t} array length mismatch: must initialize with ${s} elements.`);let a=this.gl.getUniformLocation(this.program,t);if(!a&&s&&(a=this.gl.getUniformLocation(this.program,`${t}[0]`)),!a){this.log(`${t} not in shader. Skipping initialization.`);return}let o=s?r[0]:r,n=Array.isArray(o)?o.length:1;this.uniforms.set(t,{type:e,length:n,location:a,arrayLength:s});try{this.updateUniforms({[t]:r})}catch(u){throw this.uniforms.delete(t),u}this.emitHook("initializeUniform",...arguments)}log(...t){this.debug&&console.debug(...t)}updateUniforms(t,e){this.gl.useProgram(this.program),Object.entries(t).forEach(([r,i])=>{let s=this.uniforms.get(r);if(!s){this.log(`${r} not in shader. Skipping update.`);return}let a=`uniform${s.length}${w[s.type]}`;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 o=i.length;if(!o)return;if(o>s.arrayLength)throw new Error(`${r} received ${o} values, but maximum length is ${s.arrayLength}.`);if(i.some(l=>(Array.isArray(l)?l.length:1)!==s.length))throw new Error(`Tried to update ${r} with some elements that are not length ${s.length}.`);let n=i.flat(),u=s.type==="float"?new Float32Array(n):s.type==="uint"?new Uint32Array(n):new Int32Array(n),g=s.location;if(e?.startIndex){let l=this.gl.getUniformLocation(this.program,`${r}[${e.startIndex}]`);if(!l)throw new Error(`${r}[${e.startIndex}] not in shader. Did you pass an invalid startIndex?`);g=l}this.gl[a+"v"](g,u)}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[a](s.location,...i)}}),this.emitHook("updateUniforms",...arguments)}createTexture(t,e){let{width:r,height:i}=e,s=e.history?.depth??0,a=this.gl.createTexture();if(!a)throw new Error("Failed to create texture");let o=e.unitIndex;if(typeof o!="number")try{o=this.reserveTextureUnit(t)}catch(l){throw this.gl.deleteTexture(a),l}let n=s>0,u=n?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D,{options:g}=e;return this.gl.activeTexture(this.gl.TEXTURE0+o),this.gl.bindTexture(u,a),this.gl.texParameteri(u,this.gl.TEXTURE_WRAP_S,g.wrapS),this.gl.texParameteri(u,this.gl.TEXTURE_WRAP_T,g.wrapT),this.gl.texParameteri(u,this.gl.TEXTURE_MIN_FILTER,g.minFilter),this.gl.texParameteri(u,this.gl.TEXTURE_MAG_FILTER,g.magFilter),n?this.gl.texStorage3D(u,1,g.internalFormat,r,i,s):t===p&&this.gl.texImage2D(this.gl.TEXTURE_2D,0,g.internalFormat,r,i,0,g.format,g.type,null),{texture:a,unitIndex:o}}_initializeTexture(t,e,r){if(this.textures.has(t))throw new Error(`Texture '${E(t)}' is already initialized.`);let{history:i=0,...s}=r??{},{width:a,height:o}=G(e);if(!a||!o)throw new Error("Texture source must have valid dimensions");let n={width:a,height:o,options:e instanceof h&&Object.keys(s).length===0&&e.textures.has(p)?e.textures.get(p).options:this.resolveTextureOptions(s)};i>0&&(n.history={depth:i,writeIndex:0});let{texture:u,unitIndex:g}=this.createTexture(t,n),l={texture:u,unitIndex:g,...n};i>0&&(this.initializeUniform(`${E(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(l)),this.textures.set(t,l),t!==p&&t!==I&&this.updateTexture(t,e),this.gl.useProgram(this.program);let T=this.gl.getUniformLocation(this.program,E(t));T&&this.gl.uniform1i(T,g)}initializeTexture(t,e,r){let i=r?.history!=null&&r.history>0?{...r,history:r.history+1}:r;this._initializeTexture(t,e,i),this.emitHook("initializeTexture",...arguments)}updateTextures(t,e){this.updateTexturesInternal(t,e),this.emitHook("updateTextures",...arguments)}updateTexturesInternal(t,e){Object.entries(t).forEach(([r,i])=>{this.updateTexture(r,i,e)})}updateTexture(t,e,r){let i=this.textures.get(t);if(!i)throw new Error(`Texture '${E(t)}' is not initialized.`);if(e instanceof WebGLTexture){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e);return}let s=e;if(e instanceof h){let f=e.textures.get(p),m=f.width,c=f.height;if(e.gl===this.gl){if(!i.history){this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,f.texture);return}let{depth:U}=i.history,S=r?.historyWriteIndex===void 0?[i.history.writeIndex]:Array.isArray(r?.historyWriteIndex)?r.historyWriteIndex.map(L=>F(L,U)):[F(r.historyWriteIndex,U)];this.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER,e.intermediateFbo),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture);for(let L of S)this.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,L,0,0,m,c);this.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER,null),this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture);let P=`${E(t)}FrameOffset`;this.updateUniforms({[P]:S[S.length-1]}),r?.historyWriteIndex===void 0&&(i.history.writeIndex=(i.history.writeIndex+1)%U);return}let{width:d,height:x,options:{format:b,type:y}}=f,R=this.getPixelArray(y,d*x*4);e.gl.bindFramebuffer(e.gl.FRAMEBUFFER,e.intermediateFbo),e.gl.readPixels(0,0,d,x,b,y,R),e.gl.bindFramebuffer(e.gl.FRAMEBUFFER,null),s={data:R,width:d,height:x}}let{width:a,height:o}=G(s);if(!a||!o)return;let n="isPartial"in s&&s.isPartial;n||this.resizeTexture(t,a,o);let u="data"in s&&s.data,g=!u&&!i.options?.preserveY,l=this.gl.getParameter(this.gl.UNPACK_FLIP_Y_WEBGL),T=u&&this.isNotRgba(i.options.format),v;if(T&&(v=this.gl.getParameter(this.gl.UNPACK_ALIGNMENT),this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT,1)),i.history){if(this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,i.texture),!r?.skipHistoryWrite){let{depth:f}=i.history,m=r?.historyWriteIndex===void 0?[i.history.writeIndex]:Array.isArray(r.historyWriteIndex)?r.historyWriteIndex.map(R=>F(R,f)):[F(r.historyWriteIndex,f)];this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,g);let c=s,d=c.data??s,x=n?c.x??0:0,b=n?c.y??0:0;for(let R of m)this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,x,b,R,a,o,1,i.options.format,i.options.type,d);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l);let y=`${E(t)}FrameOffset`;this.updateUniforms({[y]:m[m.length-1]}),r?.historyWriteIndex===void 0&&(i.history.writeIndex=(i.history.writeIndex+1)%f)}}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,g),n){let f=s;this.gl.texSubImage2D(this.gl.TEXTURE_2D,0,f.x??0,f.y??0,a,o,i.options.format,i.options.type,f.data)}else this.gl.texImage2D(this.gl.TEXTURE_2D,0,i.options.internalFormat,a,o,0,i.options.format,i.options.type,s.data??s);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,l)}T&&this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT,v)}bindIntermediate(){let t=this.gl,e=this.textures.get(p);t.bindFramebuffer(t.FRAMEBUFFER,this.intermediateFbo),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e.texture,0)}clear(){this.bindIntermediate();let t=this.gl,e=this.textures.get(p);if(e.options.isIntegerColorFormat){let r=e.options.type;this.glHelpers.unsignedIntTypes.has(r)?t.clearBufferuiv(t.COLOR,0,new Uint32Array(4)):t.clearBufferiv(t.COLOR,0,new Int32Array(4))}else t.clear(t.COLOR_BUFFER_BIT)}draw(t){this.emitHook("beforeDraw",...arguments);let e=this.gl,r=e.drawingBufferWidth,i=e.drawingBufferHeight;t?.skipClear?this.bindIntermediate():this.clear(),e.useProgram(this.program),e.bindVertexArray(this.vao),e.viewport(0,0,r,i),e.drawArrays(e.TRIANGLES,0,3),this.isHeadless||this.textures.get(p).options.isIntegerColorFormat||(e.bindFramebuffer(e.READ_FRAMEBUFFER,this.intermediateFbo),e.bindFramebuffer(e.DRAW_FRAMEBUFFER,null),e.blitFramebuffer(0,0,r,i,0,0,r,i,e.COLOR_BUFFER_BIT,e.NEAREST),e.bindFramebuffer(e.FRAMEBUFFER,null)),this.emitHook("afterDraw",...arguments)}step(t){Number.isFinite(this.startTime)||(this.startTime=performance.now()),this._step((performance.now()-this.startTime)/1e3,t)}_step(t,e){this.emitHook("beforeStep",t,this.frame,e);let r={};this.uniforms.has("u_time")&&(r.u_time=t),this.uniforms.has("u_frame")&&(r.u_frame=this.frame),this.updateUniforms(r),this.draw(e);let i=this.textures.get(I);if(i&&!e?.skipHistoryWrite){let{writeIndex:s,depth:a}=i.history,o=this.gl;o.bindFramebuffer(o.READ_FRAMEBUFFER,this.intermediateFbo),o.bindTexture(o.TEXTURE_2D_ARRAY,i.texture),o.copyTexSubImage3D(o.TEXTURE_2D_ARRAY,0,0,0,s,0,0,o.drawingBufferWidth,o.drawingBufferHeight),o.bindFramebuffer(o.READ_FRAMEBUFFER,null);let n=(s+1)%a;this.updateUniforms({[`${E(I)}FrameOffset`]:n}),i.history.writeIndex=n}++this.frame,this.emitHook("afterStep",t,this.frame,e)}play(t){this._pause(),Number.isFinite(this.startTime)||(this.startTime=performance.now()),this.isPlaying=!0;let e=r=>{r=(r-this.startTime)/1e3;let i=t?.(r,this.frame)??void 0;this._step(r,i),this.isPlaying&&(this.animationFrameId=requestAnimationFrame(e))};this.animationFrameId=requestAnimationFrame(e),this.emitHook("play")}_pause(){let t=this.isPlaying;return this.isPlaying=!1,this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),t}pause(){this._pause()&&this.emitHook("pause")}resetFrame(){this.frame=0,this.startTime=performance.now()}reset(){this.resetFrame(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.clear(),this.emitHook("reset")}destroy(){this.emitHook("destroy"),this._pause(),this.cursorTarget&&(this.eventListeners.forEach((e,r)=>{this.cursorTarget.removeEventListener(r,e)}),this.eventListeners.clear()),this.resolutionObserver&&(this.resolutionObserver.disconnect(),this.resolutionObserver=null),this.program&&(this.gl.deleteProgram(this.program),this.program=null),this.intermediateFbo&&(this.gl.deleteFramebuffer(this.intermediateFbo),this.intermediateFbo=null),this.textures.forEach(e=>{this.textureUnitPool.free.push(e.unitIndex),this.gl.deleteTexture(e.texture)}),this.textures.clear();let t=A.get(this.canvas);t&&(t.instances.delete(this),t.instances.size===0&&A.delete(this.canvas)),this.vao&&(this.gl.deleteVertexArray(this.vao),this.vao=null),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.uniforms.clear(),this.hooks.clear()}},B=_;export{B as a};
|
|
10
|
-
//# sourceMappingURL=chunk-
|
|
10
|
+
//# sourceMappingURL=chunk-Q5SJ2PJL.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { safeMod } from './util.js';\n\nconst DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n v_uv = a_position * 0.5 + 0.5;\n}`;\n\ninterface Uniform {\n\ttype: 'float' | 'int' | 'uint';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\ntype GLInternalFormatChannels = 'R' | 'RG' | 'RGB' | 'RGBA';\ntype GLInternalFormatDepth = '8' | '16F' | '32F' | '8UI' | '8I' | '16UI' | '16I' | '32UI' | '32I';\nexport type GLInternalFormatString = `${GLInternalFormatChannels}${GLInternalFormatDepth}`;\n\nexport type GLFormatString =\n\t| 'RED'\n\t| 'RG'\n\t| 'RGB'\n\t| 'RGBA'\n\t| 'RED_INTEGER'\n\t| 'RG_INTEGER'\n\t| 'RGB_INTEGER'\n\t| 'RGBA_INTEGER';\nexport type GLTypeString =\n\t| 'UNSIGNED_BYTE'\n\t| 'BYTE'\n\t| 'FLOAT'\n\t| 'HALF_FLOAT'\n\t| 'UNSIGNED_SHORT'\n\t| 'SHORT'\n\t| 'UNSIGNED_INT'\n\t| 'INT';\nexport type GLFilterString = 'LINEAR' | 'NEAREST';\nexport type GLWrapString = 'CLAMP_TO_EDGE' | 'REPEAT' | 'MIRRORED_REPEAT';\n\nconst FORMAT_TYPE_SUFFIXES: [string, GLTypeString][] = [\n\t['8UI', 'UNSIGNED_BYTE'],\n\t['8I', 'BYTE'],\n\t['16UI', 'UNSIGNED_SHORT'],\n\t['16I', 'SHORT'],\n\t['16F', 'HALF_FLOAT'],\n\t['32UI', 'UNSIGNED_INT'],\n\t['32I', 'INT'],\n\t['32F', 'FLOAT'],\n\t['8', 'UNSIGNED_BYTE'],\n];\n\nconst UNIFORM_TYPE_SUFFIXES: Record<Uniform['type'], string> = {\n\tfloat: 'f',\n\tint: 'i',\n\tuint: 'ui',\n};\n\nfunction typeFromInternalFormatString(internalFormatString?: GLInternalFormatString): GLTypeString | undefined {\n\treturn internalFormatString && FORMAT_TYPE_SUFFIXES.find(([suffix]) => internalFormatString.endsWith(suffix))?.[1];\n}\n\ntype GLConstantString = GLInternalFormatString | GLFormatString | GLTypeString | GLFilterString | GLWrapString;\n\nexport interface TextureOptions {\n\tinternalFormat?: GLInternalFormatString;\n\tformat?: GLFormatString;\n\ttype?: GLTypeString;\n\tminFilter?: GLFilterString;\n\tmagFilter?: GLFilterString;\n\twrapS?: GLWrapString;\n\twrapT?: GLWrapString;\n\tpreserveY?: boolean;\n}\ntype ResolvedTextureOptions = {\n\ttype: number;\n\tformat: number;\n\tinternalFormat: number;\n\tminFilter: number;\n\tmagFilter: number;\n\twrapS: number;\n\twrapT: number;\n\tpreserveY?: boolean;\n\tisIntegerColorFormat: boolean;\n};\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n\twidth: number;\n\theight: number;\n\thistory?: {\n\t\tdepth: number;\n\t\twriteIndex: number;\n\t};\n\toptions: 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\tupdateTexturesInternal: (\n\t\tupdates: Record<string, UpdateTextureSource>,\n\t\toptions?: InternalUpdateTexturesOptions,\n\t) => 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| 'play'\n\t| 'pause'\n\t| 'reset'\n\t| 'destroy'\n\t| `${string}:${string}`;\n\nexport type RenderTextureOptions = Omit<TextureOptions, 'preserveY'>;\n\nexport interface Options extends RenderTextureOptions {\n\tcanvas?: HTMLCanvasElement | OffscreenCanvas | { width: number; height: number } | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n\tdebug?: boolean;\n\tcursorTarget?: Window | Element;\n}\n\nexport interface StepOptions {\n\tskipClear?: boolean;\n\tskipHistoryWrite?: boolean;\n}\n\nexport interface UpdateTexturesOptions {\n\tskipHistoryWrite?: boolean;\n}\n\ntype InternalUpdateTexturesOptions = UpdateTexturesOptions & {\n\thistoryWriteIndex?: number | number[];\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\nconst canvasRegistry = new WeakMap<\n\tHTMLCanvasElement | OffscreenCanvas,\n\t{ textureUnitPool: TextureUnitPool; instances: Set<ShaderPad> }\n>();\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): {\n\twidth: number;\n\theight: number;\n} {\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 {\n\t\t\twidth: source.naturalWidth ?? source.width,\n\t\t\theight: source.naturalHeight ?? source.height,\n\t\t};\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 isHeadless = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate glHelpers!: {\n\t\ttypeToArray: Map<number, new (length: number) => ArrayBufferView>;\n\t\ttypeToInternalFormatString: Map<number, GLInternalFormatString>;\n\t\tunsignedIntTypes: Set<number>;\n\t};\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 vao: WebGLVertexArrayObject | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = Number.NaN;\n\tprivate isPlaying = false;\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 resolutionObserver: MutationObserver | null = null;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth = 0;\n\tprivate textureOptions: TextureOptions;\n\tprivate debug: boolean;\n\tprivate cursorTarget: Window | Element | undefined;\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(\n\t\tfragmentShaderSrc: string,\n\t\t{ canvas, plugins, history, debug, cursorTarget, ...textureOptions }: Options = {},\n\t) {\n\t\tif (canvas && 'getContext' in canvas) {\n\t\t\tthis.canvas = canvas;\n\t\t} else {\n\t\t\tconst { width = 1, height = 1 } = canvas || {};\n\t\t\tthis.canvas = new OffscreenCanvas(width, height);\n\t\t\tthis.isHeadless = true;\n\t\t}\n\n\t\tconst gl = this.canvas.getContext('webgl2', {\n\t\t\tantialias: false,\n\t\t}) 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\t\tthis.glHelpers = {\n\t\t\ttypeToArray: new Map<number, new (length: number) => ArrayBufferView>([\n\t\t\t\t[gl.FLOAT, Float32Array],\n\t\t\t\t[gl.HALF_FLOAT, Uint16Array],\n\t\t\t\t[gl.UNSIGNED_SHORT, Uint16Array],\n\t\t\t\t[gl.SHORT, Int16Array],\n\t\t\t\t[gl.BYTE, Int8Array],\n\t\t\t\t[gl.UNSIGNED_INT, Uint32Array],\n\t\t\t\t[gl.INT, Int32Array],\n\t\t\t]),\n\t\t\ttypeToInternalFormatString: new Map<number, GLInternalFormatString>([\n\t\t\t\t[gl.FLOAT, 'RGBA32F'],\n\t\t\t\t[gl.HALF_FLOAT, 'RGBA16F'],\n\t\t\t\t[gl.UNSIGNED_SHORT, 'RGBA32UI'],\n\t\t\t\t[gl.SHORT, 'RGBA32I'],\n\t\t\t\t[gl.BYTE, 'RGBA32I'],\n\t\t\t\t[gl.UNSIGNED_INT, 'RGBA32UI'],\n\t\t\t\t[gl.INT, 'RGBA32I'],\n\t\t\t]),\n\t\t\tunsignedIntTypes: new Set([gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT]),\n\t\t};\n\n\t\tlet registryEntry = canvasRegistry.get(this.canvas);\n\t\tif (!registryEntry) {\n\t\t\tregistryEntry = {\n\t\t\t\ttextureUnitPool: {\n\t\t\t\t\tfree: [],\n\t\t\t\t\tnext: 0,\n\t\t\t\t\tmax: gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t\t\t},\n\t\t\t\tinstances: new Set([this]),\n\t\t\t};\n\t\t\tcanvasRegistry.set(this.canvas, registryEntry);\n\t\t}\n\t\tthis.textureUnitPool = registryEntry.textureUnitPool;\n\t\tregistryEntry.instances.add(this);\n\n\t\tthis.textureOptions = textureOptions;\n\n\t\tif (history) this.historyDepth = history;\n\t\tthis.debug = debug ?? (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');\n\t\tthis.cursorTarget = cursorTarget ?? (this.canvas instanceof HTMLCanvasElement ? this.canvas : undefined);\n\t\tthis.animationFrameId = null;\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\tupdateTexturesInternal: this.updateTexturesInternal.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.bindAttribLocation(program, 0, 'a_position');\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.vao = gl.createVertexArray();\n\t\tgl.bindVertexArray(this.vao);\n\t\tthis.buffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);\n\t\tgl.enableVertexAttribArray(0);\n\t\tgl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\n\t\tgl.useProgram(program);\n\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\t\tthis.resolutionObserver.observe(this.canvas, {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: ['width', 'height'],\n\t\t\t});\n\t\t} else {\n\t\t\tconst wrapDimension = (dimension: 'width' | 'height') => {\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype, dimension)!;\n\t\t\t\tconst canvas = this.canvas;\n\t\t\t\tObject.defineProperty(canvas, dimension, {\n\t\t\t\t\tget: () => descriptor.get!.call(canvas),\n\t\t\t\t\tset: v => {\n\t\t\t\t\t\tdescriptor.set!.call(canvas, v);\n\t\t\t\t\t\tconst entry = canvasRegistry.get(canvas);\n\t\t\t\t\t\tif (entry) {\n\t\t\t\t\t\t\tfor (const instance of entry.instances) {\n\t\t\t\t\t\t\t\tinstance.updateResolution();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\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\t\tthis.updateResolution();\n\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\t\tthis.bindIntermediate();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\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.cursorTarget) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t\tthis.emitHook('_init');\n\t}\n\n\tprivate resolveGLConstant(value: GLConstantString): number {\n\t\tconst resolved = this.gl[value];\n\t\tif (resolved === undefined) {\n\t\t\tthrow new Error(`Unknown GL constant: ${value}`);\n\t\t}\n\t\treturn resolved;\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\tconst index = hooks.indexOf(fn);\n\t\t\tif (index >= 0) {\n\t\t\t\thooks.splice(index, 1);\n\t\t\t}\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 getCursorTargetRect(): {\n\t\tleft: number;\n\t\ttop: number;\n\t\twidth: number;\n\t\theight: number;\n\t} {\n\t\tconst target = this.cursorTarget!;\n\t\tif (target === window) {\n\t\t\treturn {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\twidth: window.innerWidth,\n\t\t\t\theight: window.innerHeight,\n\t\t\t};\n\t\t}\n\t\treturn (target as Element).getBoundingClientRect();\n\t}\n\n\tprivate addEventListeners() {\n\t\tif (!this.cursorTarget) return;\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.getCursorTargetRect();\n\t\t\tconst u = (x - rect.left) / rect.width;\n\t\t\tconst v = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.cursorPosition[0] = Math.max(0, Math.min(1, u));\n\t\t\tthis.cursorPosition[1] = Math.max(0, Math.min(1, v));\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 = this.getCursorTargetRect();\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] = Math.max(0, Math.min(1, (xVal - rect.left) / rect.width));\n\t\t\t\tthis.clickPosition[1] = Math.max(0, Math.min(1, 1 - (yVal - rect.top) / rect.height)); // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({\n\t\t\t\tu_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\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\tthis.cursorTarget!.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tupdateResolution() {\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 resolveTextureOptions(options?: TextureOptions): ResolvedTextureOptions {\n\t\tconst { gl } = this;\n\t\tconst internalFormatOption = options?.internalFormat;\n\t\tconst typeString = options?.type ?? typeFromInternalFormatString(internalFormatOption) ?? 'UNSIGNED_BYTE';\n\t\tconst type = this.resolveGLConstant(typeString);\n\t\tconst internalFormatString =\n\t\t\tinternalFormatOption ?? this.glHelpers.typeToInternalFormatString.get(type) ?? 'RGBA8';\n\t\tconst isIntegerColorFormat = /^(R|RG|RGB|RGBA)(8|16|32)(UI|I)$/.test(internalFormatString);\n\t\tconst formatString = options?.format ?? (isIntegerColorFormat ? 'RGBA_INTEGER' : 'RGBA');\n\t\tconst result: ResolvedTextureOptions = {\n\t\t\ttype,\n\t\t\tformat: this.resolveGLConstant(formatString),\n\t\t\tinternalFormat: this.resolveGLConstant(internalFormatString),\n\t\t\tminFilter: this.resolveGLConstant(options?.minFilter ?? 'LINEAR'),\n\t\t\tmagFilter: this.resolveGLConstant(options?.magFilter ?? 'LINEAR'),\n\t\t\twrapS: this.resolveGLConstant(options?.wrapS ?? 'CLAMP_TO_EDGE'),\n\t\t\twrapT: this.resolveGLConstant(options?.wrapT ?? 'CLAMP_TO_EDGE'),\n\t\t\tpreserveY: options?.preserveY,\n\t\t\tisIntegerColorFormat,\n\t\t};\n\t\tconst isFloatColorFormat = result.internalFormat === gl.RGBA16F || result.internalFormat === gl.RGBA32F;\n\t\t// gl.getExtension isn’t just a check, it’s a required side-effect to enable floats.\n\t\tif (isFloatColorFormat && !gl.getExtension('EXT_color_buffer_float')) {\n\t\t\tthrow new Error('Missing EXT_color_buffer_float.');\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate getPixelArray(type: number, size: number): ArrayBufferView {\n\t\tconst ArrayType = this.glHelpers.typeToArray.get(type) ?? Uint8Array;\n\t\treturn new ArrayType(size);\n\t}\n\n\tprivate isNotRgba(format: number): boolean {\n\t\treturn format !== this.gl.RGBA && format !== this.gl.RGBA_INTEGER;\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\tconst needsAlignmentFix = this.isNotRgba(format);\n\t\tlet previousAlignment;\n\t\tif (needsAlignmentFix) {\n\t\t\tpreviousAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);\n\t\t\tgl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\n\t\t}\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\tif (needsAlignmentFix) gl.pixelStorei(gl.UNPACK_ALIGNMENT, previousAlignment);\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: Uniform['type'],\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 (!UNIFORM_TYPE_SUFFIXES[type]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid uniform type: ${type}. Expected one of: ${Object.keys(UNIFORM_TYPE_SUFFIXES).join(', ')}.`,\n\t\t\t);\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\t\t\tlet glFunctionName = `uniform${uniform.length}${UNIFORM_TYPE_SUFFIXES[uniform.type]}`;\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 flat = newValue.flat();\n\t\t\t\tconst typedArray =\n\t\t\t\t\tuniform.type === 'float'\n\t\t\t\t\t\t? new Float32Array(flat)\n\t\t\t\t\t\t: uniform.type === 'uint'\n\t\t\t\t\t\t\t? new Uint32Array(flat)\n\t\t\t\t\t\t\t: new Int32Array(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:\n\t\t\t\tsource instanceof ShaderPad &&\n\t\t\t\tObject.keys(textureOptions).length === 0 &&\n\t\t\t\tsource.textures.has(INTERMEDIATE_TEXTURE_KEY)\n\t\t\t\t\t? source.textures.get(INTERMEDIATE_TEXTURE_KEY)!.options\n\t\t\t\t\t: 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 = {\n\t\t\ttexture,\n\t\t\tunitIndex,\n\t\t\t...textureInfo,\n\t\t};\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\tif (name !== INTERMEDIATE_TEXTURE_KEY && name !== HISTORY_TEXTURE_KEY) {\n\t\t\tthis.updateTexture(name, source);\n\t\t}\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tthis.gl.useProgram(this.program!);\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\t// Since history[0] is the current frame, add 1 to history depth to allow history[maxHistory].\n\t\tconst opts =\n\t\t\toptions?.history != null && options.history > 0 ? { ...options, history: options.history + 1 } : options;\n\t\tthis._initializeTexture(name, source, opts);\n\t\tthis.emitHook('initializeTexture', ...arguments);\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: UpdateTexturesOptions) {\n\t\tthis.updateTexturesInternal(updates, options);\n\t\tthis.emitHook('updateTextures', ...arguments);\n\t}\n\n\tprivate updateTexturesInternal(\n\t\tupdates: Record<string, UpdateTextureSource>,\n\t\toptions?: InternalUpdateTexturesOptions,\n\t) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: UpdateTextureSource, options?: InternalUpdateTexturesOptions) {\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\t\t\tconst srcW = sourceIntermediateInfo.width;\n\t\t\tconst srcH = sourceIntermediateInfo.height;\n\n\t\t\tif (source.gl === this.gl) {\n\t\t\t\tif (!info.history) {\n\t\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, sourceIntermediateInfo.texture);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst { depth } = info.history;\n\t\t\t\tconst targetSlots =\n\t\t\t\t\toptions?.historyWriteIndex === undefined\n\t\t\t\t\t\t? [info.history.writeIndex]\n\t\t\t\t\t\t: Array.isArray(options?.historyWriteIndex)\n\t\t\t\t\t\t\t? options.historyWriteIndex.map(i => safeMod(i, depth))\n\t\t\t\t\t\t\t: [safeMod(options.historyWriteIndex, depth)];\n\t\t\t\tthis.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, source.intermediateFbo);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\t\tfor (const slot of targetSlots) {\n\t\t\t\t\tthis.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY, 0, 0, 0, slot, 0, 0, srcW, srcH);\n\t\t\t\t}\n\t\t\t\tthis.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, null);\n\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({\n\t\t\t\t\t[frameOffsetUniformName]: targetSlots[targetSlots.length - 1],\n\t\t\t\t});\n\t\t\t\tif (options?.historyWriteIndex === undefined) {\n\t\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % depth;\n\t\t\t\t}\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\t\tconst needsAlignmentFix = isTypedArray && this.isNotRgba(info.options.format);\n\t\tlet previousAlignment;\n\t\tif (needsAlignmentFix) {\n\t\t\tpreviousAlignment = this.gl.getParameter(this.gl.UNPACK_ALIGNMENT);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1);\n\t\t}\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\tconst { depth } = info.history;\n\t\t\t\tconst targetSlots =\n\t\t\t\t\toptions?.historyWriteIndex === undefined\n\t\t\t\t\t\t? [info.history.writeIndex]\n\t\t\t\t\t\t: Array.isArray(options.historyWriteIndex)\n\t\t\t\t\t\t\t? options.historyWriteIndex.map(i => safeMod(i, depth))\n\t\t\t\t\t\t\t: [safeMod(options.historyWriteIndex, depth)];\n\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\t\t\t\tconst partialSource = nonShaderPadSource as PartialCustomTexture;\n\t\t\t\tconst sourceData =\n\t\t\t\t\tpartialSource.data ??\n\t\t\t\t\t(nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>);\n\t\t\t\tconst xOffset = isPartial ? (partialSource.x ?? 0) : 0;\n\t\t\t\tconst yOffset = isPartial ? (partialSource.y ?? 0) : 0;\n\n\t\t\t\tfor (const slot of targetSlots) {\n\t\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\txOffset,\n\t\t\t\t\t\tyOffset,\n\t\t\t\t\t\tslot,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\tinfo.options.format,\n\t\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t\tsourceData as any,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({\n\t\t\t\t\t[frameOffsetUniformName]: targetSlots[targetSlots.length - 1],\n\t\t\t\t});\n\n\t\t\t\tif (options?.historyWriteIndex === undefined) {\n\t\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % depth;\n\t\t\t\t}\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\tif (needsAlignmentFix) this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, previousAlignment);\n\t}\n\n\tprivate bindIntermediate() {\n\t\tconst gl = this.gl;\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\t}\n\n\tclear() {\n\t\tthis.bindIntermediate();\n\t\tconst gl = this.gl;\n\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\tif (intermediateInfo.options.isIntegerColorFormat) {\n\t\t\tconst t = intermediateInfo.options.type;\n\t\t\tif (this.glHelpers.unsignedIntTypes.has(t)) {\n\t\t\t\tgl.clearBufferuiv(gl.COLOR, 0, new Uint32Array(4));\n\t\t\t} else {\n\t\t\t\tgl.clearBufferiv(gl.COLOR, 0, new Int32Array(4));\n\t\t\t}\n\t\t} else {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\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\n\t\tif (options?.skipClear) {\n\t\t\tthis.bindIntermediate();\n\t\t} else {\n\t\t\tthis.clear();\n\t\t}\n\n\t\tgl.useProgram(this.program);\n\t\tgl.bindVertexArray(this.vao);\n\t\tgl.viewport(0, 0, w, h);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 3);\n\n\t\tif (!this.isHeadless) {\n\t\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\t\tif (!intermediateInfo.options.isIntegerColorFormat) {\n\t\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\t\t\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n\t\t\t\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\t\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\t}\n\t\t}\n\t\tthis.emitHook('afterDraw', ...arguments);\n\t}\n\n\tstep(options?: StepOptions) {\n\t\tif (!Number.isFinite(this.startTime)) {\n\t\t\tthis.startTime = performance.now();\n\t\t}\n\t\tthis._step((performance.now() - this.startTime) / 1000, options);\n\t}\n\n\tprivate _step(time: number, options?: StepOptions) {\n\t\tthis.emitHook('beforeStep', time, this.frame, options);\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\tconst gl = this.gl;\n\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, historyInfo.texture);\n\t\t\tgl.copyTexSubImage3D(\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\twriteIndex,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tgl.drawingBufferWidth,\n\t\t\t\tgl.drawingBufferHeight,\n\t\t\t);\n\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);\n\t\t\tconst nextWriteIndex = (writeIndex + 1) % depth;\n\t\t\tthis.updateUniforms({\n\t\t\t\t[`${stringFrom(HISTORY_TEXTURE_KEY)}FrameOffset`]: nextWriteIndex,\n\t\t\t});\n\t\t\thistoryInfo.history!.writeIndex = nextWriteIndex;\n\t\t}\n\t\t++this.frame;\n\t\tthis.emitHook('afterStep', time, this.frame, options);\n\t}\n\n\tplay(onBeforeStep?: (time: number, frame: number) => StepOptions | void) {\n\t\tthis._pause();\n\t\tif (!Number.isFinite(this.startTime)) {\n\t\t\tthis.startTime = performance.now();\n\t\t}\n\t\tthis.isPlaying = true;\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tconst options = onBeforeStep?.(time, this.frame) ?? undefined;\n\t\t\tthis._step(time, options);\n\t\t\tif (this.isPlaying) this.animationFrameId = requestAnimationFrame(loop);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\tthis.emitHook('play');\n\t}\n\n\tprivate _pause() {\n\t\tconst wasPlaying = this.isPlaying;\n\t\tthis.isPlaying = false;\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t\treturn wasPlaying;\n\t}\n\n\tpause() {\n\t\tif (this._pause()) {\n\t\t\tthis.emitHook('pause');\n\t\t}\n\t}\n\n\tresetFrame() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t}\n\n\treset() {\n\t\tthis.resetFrame();\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.clear();\n\t\tthis.emitHook('reset');\n\t}\n\n\tdestroy() {\n\t\tthis.emitHook('destroy');\n\n\t\tthis._pause();\n\n\t\tif (this.cursorTarget) {\n\t\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\t\tthis.cursorTarget!.removeEventListener(event, listener);\n\t\t\t});\n\t\t\tthis.eventListeners.clear();\n\t\t}\n\n\t\tif (this.resolutionObserver) {\n\t\t\tthis.resolutionObserver.disconnect();\n\t\t\tthis.resolutionObserver = null;\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthis.program = null;\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.textureUnitPool.free.push(texture.unitIndex);\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textures.clear();\n\t\tconst entry = canvasRegistry.get(this.canvas);\n\t\tif (entry) {\n\t\t\tentry.instances.delete(this);\n\t\t\tif (entry.instances.size === 0) {\n\t\t\t\tcanvasRegistry.delete(this.canvas);\n\t\t\t}\n\t\t}\n\n\t\tif (this.vao) {\n\t\t\tthis.gl.deleteVertexArray(this.vao);\n\t\t\tthis.vao = null;\n\t\t}\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.uniforms.clear();\n\t\tthis.hooks.clear();\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["DEFAULT_VERTEX_SHADER_SRC","FORMAT_TYPE_SUFFIXES","UNIFORM_TYPE_SUFFIXES","typeFromInternalFormatString","internalFormatString","suffix","HISTORY_TEXTURE_KEY","INTERMEDIATE_TEXTURE_KEY","canvasRegistry","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","ShaderPad","stringFrom","name","_ShaderPad","fragmentShaderSrc","canvas","plugins","history","debug","cursorTarget","textureOptions","width","height","gl","registryEntry","glslInjections","plugin","code","program","vertexShader","fragmentShader","wrapDimension","dimension","descriptor","v","entry","instance","value","resolved","args","hook","fn","hooks","index","type","target","updateCursor","x","y","rect","u","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","options","internalFormatOption","typeString","isIntegerColorFormat","formatString","result","size","ArrayType","format","textureInfo","transparent","needsAlignmentFix","previousAlignment","layer","arrayLength","location","probeValue","length","error","updates","newValue","uniform","glFunctionName","nValues","item","flat","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","opts","nonShaderPadSource","sourceIntermediateInfo","srcW","srcH","depth","targetSlots","i","safeMod","slot","frameOffsetUniformName","pixels","isPartial","isTypedArray","shouldFlipY","previousFlipY","partialSource","sourceData","xOffset","yOffset","intermediateInfo","t","w","h","time","historyInfo","writeIndex","nextWriteIndex","onBeforeStep","loop","wasPlaying","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { safeMod } from './util.js';\n\nconst DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 a_position;\nout vec2 v_uv;\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n v_uv = a_position * 0.5 + 0.5;\n}`;\n\ninterface Uniform {\n\ttype: 'float' | 'int' | 'uint';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\ntype GLInternalFormatChannels = 'R' | 'RG' | 'RGB' | 'RGBA';\ntype GLInternalFormatDepth = '8' | '16F' | '32F' | '8UI' | '8I' | '16UI' | '16I' | '32UI' | '32I';\nexport type GLInternalFormatString = `${GLInternalFormatChannels}${GLInternalFormatDepth}`;\n\nexport type GLFormatString =\n\t| 'RED'\n\t| 'RG'\n\t| 'RGB'\n\t| 'RGBA'\n\t| 'RED_INTEGER'\n\t| 'RG_INTEGER'\n\t| 'RGB_INTEGER'\n\t| 'RGBA_INTEGER';\nexport type GLTypeString =\n\t| 'UNSIGNED_BYTE'\n\t| 'BYTE'\n\t| 'FLOAT'\n\t| 'HALF_FLOAT'\n\t| 'UNSIGNED_SHORT'\n\t| 'SHORT'\n\t| 'UNSIGNED_INT'\n\t| 'INT';\nexport type GLFilterString = 'LINEAR' | 'NEAREST';\nexport type GLWrapString = 'CLAMP_TO_EDGE' | 'REPEAT' | 'MIRRORED_REPEAT';\n\nconst FORMAT_TYPE_SUFFIXES: [string, GLTypeString][] = [\n\t['8UI', 'UNSIGNED_BYTE'],\n\t['8I', 'BYTE'],\n\t['16UI', 'UNSIGNED_SHORT'],\n\t['16I', 'SHORT'],\n\t['16F', 'HALF_FLOAT'],\n\t['32UI', 'UNSIGNED_INT'],\n\t['32I', 'INT'],\n\t['32F', 'FLOAT'],\n\t['8', 'UNSIGNED_BYTE'],\n];\n\nconst UNIFORM_TYPE_SUFFIXES: Record<Uniform['type'], string> = {\n\tfloat: 'f',\n\tint: 'i',\n\tuint: 'ui',\n};\n\nfunction typeFromInternalFormatString(internalFormatString?: GLInternalFormatString): GLTypeString | undefined {\n\treturn internalFormatString && FORMAT_TYPE_SUFFIXES.find(([suffix]) => internalFormatString.endsWith(suffix))?.[1];\n}\n\ntype GLConstantString = GLInternalFormatString | GLFormatString | GLTypeString | GLFilterString | GLWrapString;\n\nexport interface TextureOptions {\n\tinternalFormat?: GLInternalFormatString;\n\tformat?: GLFormatString;\n\ttype?: GLTypeString;\n\tminFilter?: GLFilterString;\n\tmagFilter?: GLFilterString;\n\twrapS?: GLWrapString;\n\twrapT?: GLWrapString;\n\tpreserveY?: boolean;\n}\ntype ResolvedTextureOptions = {\n\ttype: number;\n\tformat: number;\n\tinternalFormat: number;\n\tminFilter: number;\n\tmagFilter: number;\n\twrapS: number;\n\twrapT: number;\n\tpreserveY?: boolean;\n\tisIntegerColorFormat: boolean;\n};\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n\twidth: number;\n\theight: number;\n\thistory?: {\n\t\tdepth: number;\n\t\twriteIndex: number;\n\t};\n\toptions: 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\tupdateTexturesInternal: (\n\t\tupdates: Record<string, UpdateTextureSource>,\n\t\toptions?: InternalUpdateTexturesOptions,\n\t) => 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| 'play'\n\t| 'pause'\n\t| 'reset'\n\t| 'destroy'\n\t| `${string}:${string}`;\n\nexport type RenderTextureOptions = Omit<TextureOptions, 'preserveY'>;\n\nexport interface Options extends RenderTextureOptions {\n\tcanvas?: HTMLCanvasElement | OffscreenCanvas | { width: number; height: number } | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n\tdebug?: boolean;\n\tcursorTarget?: Window | Element;\n}\n\nexport interface StepOptions {\n\tskipClear?: boolean;\n\tskipHistoryWrite?: boolean;\n}\n\nexport interface UpdateTexturesOptions {\n\tskipHistoryWrite?: boolean;\n}\n\ntype InternalUpdateTexturesOptions = UpdateTexturesOptions & {\n\thistoryWriteIndex?: number | number[];\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\nconst canvasRegistry = new WeakMap<\n\tHTMLCanvasElement | OffscreenCanvas,\n\t{ textureUnitPool: TextureUnitPool; instances: Set<ShaderPad> }\n>();\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): {\n\twidth: number;\n\theight: number;\n} {\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 {\n\t\t\twidth: source.naturalWidth ?? source.width,\n\t\t\theight: source.naturalHeight ?? source.height,\n\t\t};\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 isHeadless = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate glHelpers!: {\n\t\ttypeToArray: Map<number, new (length: number) => ArrayBufferView>;\n\t\ttypeToInternalFormatString: Map<number, GLInternalFormatString>;\n\t\tunsignedIntTypes: Set<number>;\n\t};\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 vao: WebGLVertexArrayObject | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = Number.NaN;\n\tprivate isPlaying = false;\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 resolutionObserver: MutationObserver | null = null;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth = 0;\n\tprivate textureOptions: TextureOptions;\n\tprivate debug: boolean;\n\tprivate cursorTarget: Window | Element | undefined;\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(\n\t\tfragmentShaderSrc: string,\n\t\t{ canvas, plugins, history, debug, cursorTarget, ...textureOptions }: Options = {},\n\t) {\n\t\tif (canvas && 'getContext' in canvas) {\n\t\t\tthis.canvas = canvas;\n\t\t} else {\n\t\t\tconst { width = 1, height = 1 } = canvas || {};\n\t\t\tthis.canvas = new OffscreenCanvas(width, height);\n\t\t\tthis.isHeadless = true;\n\t\t}\n\n\t\tconst gl = this.canvas.getContext('webgl2', {\n\t\t\tantialias: false,\n\t\t}) 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\t\tthis.glHelpers = {\n\t\t\ttypeToArray: new Map<number, new (length: number) => ArrayBufferView>([\n\t\t\t\t[gl.FLOAT, Float32Array],\n\t\t\t\t[gl.HALF_FLOAT, Uint16Array],\n\t\t\t\t[gl.UNSIGNED_SHORT, Uint16Array],\n\t\t\t\t[gl.SHORT, Int16Array],\n\t\t\t\t[gl.BYTE, Int8Array],\n\t\t\t\t[gl.UNSIGNED_INT, Uint32Array],\n\t\t\t\t[gl.INT, Int32Array],\n\t\t\t]),\n\t\t\ttypeToInternalFormatString: new Map<number, GLInternalFormatString>([\n\t\t\t\t[gl.FLOAT, 'RGBA32F'],\n\t\t\t\t[gl.HALF_FLOAT, 'RGBA16F'],\n\t\t\t\t[gl.UNSIGNED_SHORT, 'RGBA32UI'],\n\t\t\t\t[gl.SHORT, 'RGBA32I'],\n\t\t\t\t[gl.BYTE, 'RGBA32I'],\n\t\t\t\t[gl.UNSIGNED_INT, 'RGBA32UI'],\n\t\t\t\t[gl.INT, 'RGBA32I'],\n\t\t\t]),\n\t\t\tunsignedIntTypes: new Set([gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT, gl.UNSIGNED_INT]),\n\t\t};\n\n\t\tlet registryEntry = canvasRegistry.get(this.canvas);\n\t\tif (!registryEntry) {\n\t\t\tregistryEntry = {\n\t\t\t\ttextureUnitPool: {\n\t\t\t\t\tfree: [],\n\t\t\t\t\tnext: 0,\n\t\t\t\t\tmax: gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t\t\t},\n\t\t\t\tinstances: new Set([this]),\n\t\t\t};\n\t\t\tcanvasRegistry.set(this.canvas, registryEntry);\n\t\t}\n\t\tthis.textureUnitPool = registryEntry.textureUnitPool;\n\t\tregistryEntry.instances.add(this);\n\n\t\tthis.textureOptions = textureOptions;\n\n\t\tif (history) this.historyDepth = history;\n\t\tthis.debug = debug ?? (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');\n\t\tthis.cursorTarget = cursorTarget ?? (this.canvas instanceof HTMLCanvasElement ? this.canvas : undefined);\n\t\tthis.animationFrameId = null;\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\tupdateTexturesInternal: this.updateTexturesInternal.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.bindAttribLocation(program, 0, 'a_position');\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.vao = gl.createVertexArray();\n\t\tgl.bindVertexArray(this.vao);\n\t\tthis.buffer = gl.createBuffer();\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);\n\t\tgl.enableVertexAttribArray(0);\n\t\tgl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n\n\t\tgl.useProgram(program);\n\n\t\tif (this.canvas instanceof HTMLCanvasElement) {\n\t\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\t\tthis.resolutionObserver.observe(this.canvas, {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: ['width', 'height'],\n\t\t\t});\n\t\t} else {\n\t\t\tconst wrapDimension = (dimension: 'width' | 'height') => {\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(OffscreenCanvas.prototype, dimension)!;\n\t\t\t\tconst canvas = this.canvas;\n\t\t\t\tObject.defineProperty(canvas, dimension, {\n\t\t\t\t\tget: () => descriptor.get!.call(canvas),\n\t\t\t\t\tset: v => {\n\t\t\t\t\t\tdescriptor.set!.call(canvas, v);\n\t\t\t\t\t\tconst entry = canvasRegistry.get(canvas);\n\t\t\t\t\t\tif (entry) {\n\t\t\t\t\t\t\tfor (const instance of entry.instances) {\n\t\t\t\t\t\t\t\tinstance.updateResolution();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\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\t\tthis.updateResolution();\n\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\t\tthis.bindIntermediate();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\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.cursorTarget) {\n\t\t\tthis.addEventListeners();\n\t\t}\n\t\tthis.emitHook('_init');\n\t}\n\n\tprivate resolveGLConstant(value: GLConstantString): number {\n\t\tconst resolved = this.gl[value];\n\t\tif (resolved === undefined) {\n\t\t\tthrow new Error(`Unknown GL constant: ${value}`);\n\t\t}\n\t\treturn resolved;\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\tconst index = hooks.indexOf(fn);\n\t\t\tif (index >= 0) {\n\t\t\t\thooks.splice(index, 1);\n\t\t\t}\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 getCursorTargetRect(): {\n\t\tleft: number;\n\t\ttop: number;\n\t\twidth: number;\n\t\theight: number;\n\t} {\n\t\tconst target = this.cursorTarget!;\n\t\tif (target === window) {\n\t\t\treturn {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\twidth: window.innerWidth,\n\t\t\t\theight: window.innerHeight,\n\t\t\t};\n\t\t}\n\t\treturn (target as Element).getBoundingClientRect();\n\t}\n\n\tprivate addEventListeners() {\n\t\tif (!this.cursorTarget) return;\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.getCursorTargetRect();\n\t\t\tconst u = (x - rect.left) / rect.width;\n\t\t\tconst v = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.cursorPosition[0] = Math.max(0, Math.min(1, u));\n\t\t\tthis.cursorPosition[1] = Math.max(0, Math.min(1, v));\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 = this.getCursorTargetRect();\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] = Math.max(0, Math.min(1, (xVal - rect.left) / rect.width));\n\t\t\t\tthis.clickPosition[1] = Math.max(0, Math.min(1, 1 - (yVal - rect.top) / rect.height)); // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({\n\t\t\t\tu_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\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\tthis.cursorTarget!.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tupdateResolution() {\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 resolveTextureOptions(options?: TextureOptions): ResolvedTextureOptions {\n\t\tconst { gl } = this;\n\t\tconst internalFormatOption = options?.internalFormat;\n\t\tconst typeString = options?.type ?? typeFromInternalFormatString(internalFormatOption) ?? 'UNSIGNED_BYTE';\n\t\tconst type = this.resolveGLConstant(typeString);\n\t\tconst internalFormatString =\n\t\t\tinternalFormatOption ?? this.glHelpers.typeToInternalFormatString.get(type) ?? 'RGBA8';\n\t\tconst isIntegerColorFormat = /^(R|RG|RGB|RGBA)(8|16|32)(UI|I)$/.test(internalFormatString);\n\t\tconst formatString = options?.format ?? (isIntegerColorFormat ? 'RGBA_INTEGER' : 'RGBA');\n\t\tconst result: ResolvedTextureOptions = {\n\t\t\ttype,\n\t\t\tformat: this.resolveGLConstant(formatString),\n\t\t\tinternalFormat: this.resolveGLConstant(internalFormatString),\n\t\t\tminFilter: this.resolveGLConstant(options?.minFilter ?? 'LINEAR'),\n\t\t\tmagFilter: this.resolveGLConstant(options?.magFilter ?? 'LINEAR'),\n\t\t\twrapS: this.resolveGLConstant(options?.wrapS ?? 'CLAMP_TO_EDGE'),\n\t\t\twrapT: this.resolveGLConstant(options?.wrapT ?? 'CLAMP_TO_EDGE'),\n\t\t\tpreserveY: options?.preserveY,\n\t\t\tisIntegerColorFormat,\n\t\t};\n\t\tconst isFloatColorFormat = result.internalFormat === gl.RGBA16F || result.internalFormat === gl.RGBA32F;\n\t\t// gl.getExtension isn’t just a check, it’s a required side-effect to enable floats.\n\t\tif (isFloatColorFormat && !gl.getExtension('EXT_color_buffer_float')) {\n\t\t\tthrow new Error('Missing EXT_color_buffer_float.');\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate getPixelArray(type: number, size: number): ArrayBufferView {\n\t\tconst ArrayType = this.glHelpers.typeToArray.get(type) ?? Uint8Array;\n\t\treturn new ArrayType(size);\n\t}\n\n\tprivate isNotRgba(format: number): boolean {\n\t\treturn format !== this.gl.RGBA && format !== this.gl.RGBA_INTEGER;\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\tconst needsAlignmentFix = this.isNotRgba(format);\n\t\tlet previousAlignment;\n\t\tif (needsAlignmentFix) {\n\t\t\tpreviousAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);\n\t\t\tgl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\n\t\t}\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\tif (needsAlignmentFix) gl.pixelStorei(gl.UNPACK_ALIGNMENT, previousAlignment);\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: Uniform['type'],\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 (!UNIFORM_TYPE_SUFFIXES[type]) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid uniform type: ${type}. Expected one of: ${Object.keys(UNIFORM_TYPE_SUFFIXES).join(', ')}.`,\n\t\t\t);\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\t\t\tlet glFunctionName = `uniform${uniform.length}${UNIFORM_TYPE_SUFFIXES[uniform.type]}`;\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 flat = newValue.flat();\n\t\t\t\tconst typedArray =\n\t\t\t\t\tuniform.type === 'float'\n\t\t\t\t\t\t? new Float32Array(flat)\n\t\t\t\t\t\t: uniform.type === 'uint'\n\t\t\t\t\t\t\t? new Uint32Array(flat)\n\t\t\t\t\t\t\t: new Int32Array(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:\n\t\t\t\tsource instanceof ShaderPad &&\n\t\t\t\tObject.keys(textureOptions).length === 0 &&\n\t\t\t\tsource.textures.has(INTERMEDIATE_TEXTURE_KEY)\n\t\t\t\t\t? source.textures.get(INTERMEDIATE_TEXTURE_KEY)!.options\n\t\t\t\t\t: 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 = {\n\t\t\ttexture,\n\t\t\tunitIndex,\n\t\t\t...textureInfo,\n\t\t};\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\tif (name !== INTERMEDIATE_TEXTURE_KEY && name !== HISTORY_TEXTURE_KEY) {\n\t\t\tthis.updateTexture(name, source);\n\t\t}\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tthis.gl.useProgram(this.program!);\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\t// Since history[0] is the current frame, add 1 to history depth to allow history[maxHistory].\n\t\tconst opts =\n\t\t\toptions?.history != null && options.history > 0 ? { ...options, history: options.history + 1 } : options;\n\t\tthis._initializeTexture(name, source, opts);\n\t\tthis.emitHook('initializeTexture', ...arguments);\n\t}\n\n\tupdateTextures(updates: Record<string, UpdateTextureSource>, options?: UpdateTexturesOptions) {\n\t\tthis.updateTexturesInternal(updates, options);\n\t\tthis.emitHook('updateTextures', ...arguments);\n\t}\n\n\tprivate updateTexturesInternal(\n\t\tupdates: Record<string, UpdateTextureSource>,\n\t\toptions?: InternalUpdateTexturesOptions,\n\t) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source, options);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: UpdateTextureSource, options?: InternalUpdateTexturesOptions) {\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\t\t\tconst srcW = sourceIntermediateInfo.width;\n\t\t\tconst srcH = sourceIntermediateInfo.height;\n\n\t\t\tif (source.gl === this.gl) {\n\t\t\t\tif (!info.history) {\n\t\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, sourceIntermediateInfo.texture);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst { depth } = info.history;\n\t\t\t\tconst targetSlots =\n\t\t\t\t\toptions?.historyWriteIndex === undefined\n\t\t\t\t\t\t? [info.history.writeIndex]\n\t\t\t\t\t\t: Array.isArray(options?.historyWriteIndex)\n\t\t\t\t\t\t\t? options.historyWriteIndex.map(i => safeMod(i, depth))\n\t\t\t\t\t\t\t: [safeMod(options.historyWriteIndex, depth)];\n\t\t\t\tthis.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, source.intermediateFbo);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\t\tfor (const slot of targetSlots) {\n\t\t\t\t\tthis.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY, 0, 0, 0, slot, 0, 0, srcW, srcH);\n\t\t\t\t}\n\t\t\t\tthis.gl.bindFramebuffer(this.gl.READ_FRAMEBUFFER, null);\n\t\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({\n\t\t\t\t\t[frameOffsetUniformName]: targetSlots[targetSlots.length - 1],\n\t\t\t\t});\n\t\t\t\tif (options?.historyWriteIndex === undefined) {\n\t\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % depth;\n\t\t\t\t}\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\t\tconst needsAlignmentFix = isTypedArray && this.isNotRgba(info.options.format);\n\t\tlet previousAlignment;\n\t\tif (needsAlignmentFix) {\n\t\t\tpreviousAlignment = this.gl.getParameter(this.gl.UNPACK_ALIGNMENT);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1);\n\t\t}\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\tconst { depth } = info.history;\n\t\t\t\tconst targetSlots =\n\t\t\t\t\toptions?.historyWriteIndex === undefined\n\t\t\t\t\t\t? [info.history.writeIndex]\n\t\t\t\t\t\t: Array.isArray(options.historyWriteIndex)\n\t\t\t\t\t\t\t? options.historyWriteIndex.map(i => safeMod(i, depth))\n\t\t\t\t\t\t\t: [safeMod(options.historyWriteIndex, depth)];\n\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, shouldFlipY);\n\t\t\t\tconst partialSource = nonShaderPadSource as PartialCustomTexture;\n\t\t\t\tconst sourceData =\n\t\t\t\t\tpartialSource.data ?? (nonShaderPadSource as Exclude<TextureSource, CustomTexture | ShaderPad>);\n\t\t\t\tconst xOffset = isPartial ? (partialSource.x ?? 0) : 0;\n\t\t\t\tconst yOffset = isPartial ? (partialSource.y ?? 0) : 0;\n\n\t\t\t\tfor (const slot of targetSlots) {\n\t\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\txOffset,\n\t\t\t\t\t\tyOffset,\n\t\t\t\t\t\tslot,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\tinfo.options.format,\n\t\t\t\t\t\tinfo.options.type,\n\t\t\t\t\t\tsourceData as any,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, previousFlipY);\n\n\t\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\t\tthis.updateUniforms({\n\t\t\t\t\t[frameOffsetUniformName]: targetSlots[targetSlots.length - 1],\n\t\t\t\t});\n\n\t\t\t\tif (options?.historyWriteIndex === undefined) {\n\t\t\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % depth;\n\t\t\t\t}\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\tif (needsAlignmentFix) this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, previousAlignment);\n\t}\n\n\tprivate bindIntermediate() {\n\t\tconst gl = this.gl;\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\t}\n\n\tclear() {\n\t\tthis.bindIntermediate();\n\t\tconst gl = this.gl;\n\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\tif (intermediateInfo.options.isIntegerColorFormat) {\n\t\t\tconst t = intermediateInfo.options.type;\n\t\t\tif (this.glHelpers.unsignedIntTypes.has(t)) {\n\t\t\t\tgl.clearBufferuiv(gl.COLOR, 0, new Uint32Array(4));\n\t\t\t} else {\n\t\t\t\tgl.clearBufferiv(gl.COLOR, 0, new Int32Array(4));\n\t\t\t}\n\t\t} else {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\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\n\t\tif (options?.skipClear) {\n\t\t\tthis.bindIntermediate();\n\t\t} else {\n\t\t\tthis.clear();\n\t\t}\n\n\t\tgl.useProgram(this.program);\n\t\tgl.bindVertexArray(this.vao);\n\t\tgl.viewport(0, 0, w, h);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 3);\n\n\t\tif (!this.isHeadless) {\n\t\t\tconst intermediateInfo = this.textures.get(INTERMEDIATE_TEXTURE_KEY)!;\n\t\t\tif (!intermediateInfo.options.isIntegerColorFormat) {\n\t\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\t\t\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);\n\t\t\t\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, gl.COLOR_BUFFER_BIT, gl.NEAREST);\n\t\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\t}\n\t\t}\n\t\tthis.emitHook('afterDraw', ...arguments);\n\t}\n\n\tstep(options?: StepOptions) {\n\t\tif (!Number.isFinite(this.startTime)) {\n\t\t\tthis.startTime = performance.now();\n\t\t}\n\t\tthis._step((performance.now() - this.startTime) / 1000, options);\n\t}\n\n\tprivate _step(time: number, options?: StepOptions) {\n\t\tthis.emitHook('beforeStep', time, this.frame, options);\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\tconst gl = this.gl;\n\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.intermediateFbo);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, historyInfo.texture);\n\t\t\tgl.copyTexSubImage3D(\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\twriteIndex,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tgl.drawingBufferWidth,\n\t\t\t\tgl.drawingBufferHeight,\n\t\t\t);\n\t\t\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);\n\t\t\tconst nextWriteIndex = (writeIndex + 1) % depth;\n\t\t\tthis.updateUniforms({\n\t\t\t\t[`${stringFrom(HISTORY_TEXTURE_KEY)}FrameOffset`]: nextWriteIndex,\n\t\t\t});\n\t\t\thistoryInfo.history!.writeIndex = nextWriteIndex;\n\t\t}\n\t\t++this.frame;\n\t\tthis.emitHook('afterStep', time, this.frame, options);\n\t}\n\n\tplay(onBeforeStep?: (time: number, frame: number) => StepOptions | void) {\n\t\tthis._pause();\n\t\tif (!Number.isFinite(this.startTime)) {\n\t\t\tthis.startTime = performance.now();\n\t\t}\n\t\tthis.isPlaying = true;\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tconst options = onBeforeStep?.(time, this.frame) ?? undefined;\n\t\t\tthis._step(time, options);\n\t\t\tif (this.isPlaying) this.animationFrameId = requestAnimationFrame(loop);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\tthis.emitHook('play');\n\t}\n\n\tprivate _pause() {\n\t\tconst wasPlaying = this.isPlaying;\n\t\tthis.isPlaying = false;\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t\treturn wasPlaying;\n\t}\n\n\tpause() {\n\t\tif (this._pause()) {\n\t\t\tthis.emitHook('pause');\n\t\t}\n\t}\n\n\tresetFrame() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t}\n\n\treset() {\n\t\tthis.resetFrame();\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.clear();\n\t\tthis.emitHook('reset');\n\t}\n\n\tdestroy() {\n\t\tthis.emitHook('destroy');\n\n\t\tthis._pause();\n\n\t\tif (this.cursorTarget) {\n\t\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\t\tthis.cursorTarget!.removeEventListener(event, listener);\n\t\t\t});\n\t\t\tthis.eventListeners.clear();\n\t\t}\n\n\t\tif (this.resolutionObserver) {\n\t\t\tthis.resolutionObserver.disconnect();\n\t\t\tthis.resolutionObserver = null;\n\t\t}\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthis.program = null;\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.textureUnitPool.free.push(texture.unitIndex);\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textures.clear();\n\t\tconst entry = canvasRegistry.get(this.canvas);\n\t\tif (entry) {\n\t\t\tentry.instances.delete(this);\n\t\t\tif (entry.instances.size === 0) {\n\t\t\t\tcanvasRegistry.delete(this.canvas);\n\t\t\t}\n\t\t}\n\n\t\tif (this.vao) {\n\t\t\tthis.gl.deleteVertexArray(this.vao);\n\t\t\tthis.vao = null;\n\t\t}\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.uniforms.clear();\n\t\tthis.hooks.clear();\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["DEFAULT_VERTEX_SHADER_SRC","FORMAT_TYPE_SUFFIXES","UNIFORM_TYPE_SUFFIXES","typeFromInternalFormatString","internalFormatString","suffix","HISTORY_TEXTURE_KEY","INTERMEDIATE_TEXTURE_KEY","canvasRegistry","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","ShaderPad","stringFrom","name","_ShaderPad","fragmentShaderSrc","canvas","plugins","history","debug","cursorTarget","textureOptions","width","height","gl","registryEntry","glslInjections","plugin","code","program","vertexShader","fragmentShader","wrapDimension","dimension","descriptor","v","entry","instance","value","resolved","args","hook","fn","hooks","index","type","target","updateCursor","x","y","rect","u","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","info","texture","existing","options","internalFormatOption","typeString","isIntegerColorFormat","formatString","result","size","ArrayType","format","textureInfo","transparent","needsAlignmentFix","previousAlignment","layer","arrayLength","location","probeValue","length","error","updates","newValue","uniform","glFunctionName","nValues","item","flat","typedArray","newLocation","historyDepth","unitIndex","hasHistory","textureTarget","completeTextureInfo","uSampler","opts","nonShaderPadSource","sourceIntermediateInfo","srcW","srcH","depth","targetSlots","i","safeMod","slot","frameOffsetUniformName","pixels","isPartial","isTypedArray","shouldFlipY","previousFlipY","partialSource","sourceData","xOffset","yOffset","intermediateInfo","t","w","h","time","historyInfo","writeIndex","nextWriteIndex","onBeforeStep","loop","wasPlaying","index_default"]}
|