shaderpad 1.0.0-beta.20 → 1.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/plugins/face.d.mts +1 -1
- package/dist/plugins/face.d.ts +1 -1
- package/dist/plugins/face.js +2 -2
- package/dist/plugins/face.js.map +1 -1
- package/dist/plugins/face.mjs +1 -1
- package/dist/plugins/face.mjs.map +1 -1
- package/dist/plugins/hands.d.mts +1 -1
- package/dist/plugins/hands.d.ts +1 -1
- package/dist/plugins/hands.js +2 -2
- package/dist/plugins/hands.js.map +1 -1
- package/dist/plugins/hands.mjs +1 -1
- package/dist/plugins/hands.mjs.map +1 -1
- package/dist/plugins/helpers.d.mts +1 -1
- package/dist/plugins/helpers.d.ts +1 -1
- package/dist/plugins/helpers.js +2 -2
- package/dist/plugins/helpers.js.map +1 -1
- package/dist/plugins/helpers.mjs +1 -1
- package/dist/plugins/helpers.mjs.map +1 -1
- package/dist/plugins/pose.d.mts +1 -1
- package/dist/plugins/pose.d.ts +1 -1
- package/dist/plugins/pose.js +2 -2
- package/dist/plugins/pose.js.map +1 -1
- package/dist/plugins/pose.mjs +1 -1
- package/dist/plugins/pose.mjs.map +1 -1
- package/dist/plugins/save.d.mts +1 -1
- package/dist/plugins/save.d.ts +1 -1
- package/dist/plugins/save.js +1 -1
- package/dist/plugins/save.js.map +1 -1
- package/dist/plugins/save.mjs +1 -1
- package/dist/plugins/save.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -299,7 +299,7 @@ The `helpers` plugin provides convenience functions and constants. See [helpers.
|
|
|
299
299
|
|
|
300
300
|
```typescript
|
|
301
301
|
import ShaderPad from 'shaderpad';
|
|
302
|
-
import
|
|
302
|
+
import helpers from 'shaderpad/plugins/helpers';
|
|
303
303
|
|
|
304
304
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
305
305
|
plugins: [helpers()],
|
|
@@ -312,7 +312,7 @@ The `save` plugin adds a `.save()` method to the shader that saves the current f
|
|
|
312
312
|
|
|
313
313
|
```typescript
|
|
314
314
|
import ShaderPad from 'shaderpad';
|
|
315
|
-
import
|
|
315
|
+
import save, { WithSave } from 'shaderpad/plugins/save';
|
|
316
316
|
|
|
317
317
|
const shader = new ShaderPad(fragmentShaderSrc, { plugins: [save()] }) as WithSave<ShaderPad>;
|
|
318
318
|
shader.save('my-frame');
|
|
@@ -324,7 +324,7 @@ The `face` plugin uses [MediaPipe](https://ai.google.dev/edge/mediapipe/solution
|
|
|
324
324
|
|
|
325
325
|
```typescript
|
|
326
326
|
import ShaderPad from 'shaderpad';
|
|
327
|
-
import
|
|
327
|
+
import face from 'shaderpad/plugins/face';
|
|
328
328
|
|
|
329
329
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
330
330
|
plugins: [
|
|
@@ -358,7 +358,7 @@ The `pose` plugin uses [MediaPipe Pose Landmarker](https://ai.google.dev/edge/me
|
|
|
358
358
|
|
|
359
359
|
```typescript
|
|
360
360
|
import ShaderPad from 'shaderpad';
|
|
361
|
-
import
|
|
361
|
+
import pose from 'shaderpad/plugins/pose';
|
|
362
362
|
|
|
363
363
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
364
364
|
plugins: [pose({ textureName: 'u_video', options: { maxPoses: 3 } })],
|
|
@@ -419,7 +419,7 @@ The `hands` plugin uses [MediaPipe Hand Landmarker](https://ai.google.dev/edge/m
|
|
|
419
419
|
|
|
420
420
|
```typescript
|
|
421
421
|
import ShaderPad from 'shaderpad';
|
|
422
|
-
import
|
|
422
|
+
import hands from 'shaderpad/plugins/hands';
|
|
423
423
|
|
|
424
424
|
const shader = new ShaderPad(fragmentShaderSrc, {
|
|
425
425
|
plugins: [hands({ textureName: 'u_video', options: { maxHands: 2 } })],
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
"use strict";var f=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(n,t)=>{for(var i in t)f(n,i,{get:t[i],enumerable:!0})},b=(n,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of v(t))!x.call(n,r)&&r!==i&&f(n,r,{get:()=>t[r],enumerable:!(e=T(t,r))||e.enumerable});return n};var y=n=>b(f({},"__esModule",{value:!0}),n);var
|
|
1
|
+
"use strict";var f=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var v=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(n,t)=>{for(var i in t)f(n,i,{get:t[i],enumerable:!0})},b=(n,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of v(t))!x.call(n,r)&&r!==i&&f(n,r,{get:()=>t[r],enumerable:!(e=T(t,r))||e.enumerable});return n};var y=n=>b(f({},"__esModule",{value:!0}),n);var U={};E(U,{default:()=>_});module.exports=y(U);var w=`#version 300 es
|
|
2
2
|
in vec2 aPosition;
|
|
3
3
|
out vec2 v_uv;
|
|
4
4
|
void main() {
|
|
5
5
|
v_uv = aPosition * 0.5 + 0.5;
|
|
6
6
|
gl_Position = vec4(aPosition, 0.0, 1.0);
|
|
7
7
|
}
|
|
8
|
-
`,R=33.333333333333336,c=Symbol("u_history");function
|
|
8
|
+
`,R=33.333333333333336,c=Symbol("u_history");function L(n,t){if(!t?.length)return n;let i=n.split(`
|
|
9
9
|
`),e=i.findLastIndex(r=>{let s=r.trimStart();return s.startsWith("precision ")||s.startsWith("#version ")})+1;return i.splice(e,0,...t),i.join(`
|
|
10
|
-
`)}function p(n){if(n instanceof HTMLVideoElement)return{width:n.videoWidth,height:n.videoHeight};if(n instanceof HTMLCanvasElement){let t=n.getContext("webgl2");return t?{width:t.drawingBufferWidth,height:t.drawingBufferHeight}:{width:n.width,height:n.height}}return{width:n.naturalWidth??n.width,height:n.naturalHeight??n.height}}function g(n){return typeof n=="symbol"?n.description??"":n}var m=class{isInternalCanvas=!1;isTouchDevice=!1;gl;fragmentShaderSrc;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;onResize;hooks=new Map;historyDepth;constructor(t,i={}){if(this.canvas=i.canvas||document.createElement("canvas"),i.canvas||(this.isInternalCanvas=!0,this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw",document.body.appendChild(this.canvas)),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.textureUnitPool={free:[],next:0,max:this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.historyDepth=i.history??0,this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let e=[];if(i.plugins){let r={gl:this.gl,uniforms:this.uniforms,textures:this.textures,canvas:this.canvas,reserveTextureUnit:this.reserveTextureUnit.bind(this),releaseTextureUnit:this.releaseTextureUnit.bind(this),injectGLSL:s=>{e.push(s)}};Object.defineProperty(r,"program",{get:()=>this.program,enumerable:!0,configurable:!0}),i.plugins.forEach(s=>s(this,r))}this.fragmentShaderSrc=U(t,e),this.init(),this.addEventListeners()}registerHook(t,i){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(i)}init(){let t=w;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let i=this.createShader(this.gl.VERTEX_SHADER,t),e=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,i),this.gl.attachShader(this.program,e),this.gl.linkProgram(this.program),this.gl.deleteShader(i),this.gl.deleteShader(e),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw console.error("Program link error:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),new Error("Failed to link WebGL program");let r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.gl.useProgram(this.program),this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyDepth>0&&this._initializeTexture(c,this.canvas,{history:this.historyDepth}),this.hooks.get("init")?.forEach(s=>s.call(this))}createShader(t,i){let e=this.gl.createShader(t);if(this.gl.shaderSource(e,i),this.gl.compileShader(e),!this.gl.getShaderParameter(e,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",i),console.error(this.gl.getShaderInfoLog(e)),this.gl.deleteShader(e),new Error("Shader compilation failed");return e}setupBuffer(t){let i=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),i=this.lastResizeTime+R-t;i<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),i)}handleResize(){let t=window.devicePixelRatio||1,i=this.canvas.clientWidth*t,e=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==i||this.canvas.height!==e)&&(this.canvas.width=i,this.canvas.height=e),this.onResize?.(i,e)}addEventListeners(){let t=(e,r)=>{if(!this.uniforms.has("u_cursor"))return;let s=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(e-s.left)/s.width,this.cursorPosition[1]=1-(r-s.top)/s.height,this.updateUniforms({u_cursor:this.cursorPosition})},i=(e,r,s)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=e,e){let o=this.canvas.getBoundingClientRect(),h=r,l=s;this.clickPosition[0]=(h-o.left)/o.width,this.clickPosition[1]=1-(l-o.top)/o.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",e=>{let r=e;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",e=>{let r=e;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,i(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",e=>{let r=e;this.isTouchDevice||r.button===0&&i(!1)}),this.eventListeners.set("touchmove",e=>{let r=e;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",e=>{let r=e;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),i(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",e=>{e.touches.length===0&&i(!1)}),this.eventListeners.forEach((e,r)=>{this.canvas.addEventListener(r,e)})}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.hooks.get("updateResolution")?.forEach(i=>i.call(this))}reserveTextureUnit(t){let i=this.textures.get(t);if(i)return i.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(t){let i=this.textures.get(t);i&&this.textureUnitPool.free.push(i.unitIndex)}clearHistoryTextureLayers(t){if(!t.history)return;let i=new Uint8Array(t.width*t.height*4);this.gl.activeTexture(this.gl.TEXTURE0+t.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,t.texture);for(let e=0;e<t.history.depth;++e)this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e,t.width,t.height,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}initializeUniform(t,i,e,r){let s=r?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(i!=="float"&&i!=="int")throw new Error(`Invalid uniform type: ${i}. Expected 'float' or 'int'.`);if(s&&!(Array.isArray(e)&&e.length===s))throw new Error(`${t} array length mismatch: must initialize with ${s} elements.`);let o=this.gl.getUniformLocation(this.program,t);if(!o&&s&&(o=this.gl.getUniformLocation(this.program,`${t}[0]`)),!o){console.debug(`${t} not found in fragment shader. Skipping initialization.`);return}let h=s?e[0]:e,l=Array.isArray(h)?h.length:1;this.uniforms.set(t,{type:i,length:l,location:o,arrayLength:s});try{this.updateUniforms({[t]:e})}catch(a){throw this.uniforms.delete(t),a}this.hooks.get("initializeUniform")?.forEach(a=>a.call(this,...arguments))}updateUniforms(t,i){Object.entries(t).forEach(([e,r])=>{let s=this.uniforms.get(e);if(!s){console.debug(`${e} not found in fragment shader. Skipping update.`);return}let o=`uniform${s.length}${s.type.charAt(0)}`;if(s.arrayLength){if(!Array.isArray(r))throw new Error(`${e} is an array, but the value passed to updateUniforms is not an array.`);let h=r.length;if(!h)return;if(h>s.arrayLength)throw new Error(`${e} received ${h} values, but maximum length is ${s.arrayLength}.`);if(r.some(u=>(Array.isArray(u)?u.length:1)!==s.length))throw new Error(`Tried to update ${e} with some elements that are not length ${s.length}.`);let l=new(s.type==="float"?Float32Array:Int32Array)(r.flat()),a=s.location;if(i?.startIndex){let u=this.gl.getUniformLocation(this.program,`${e}[${i.startIndex}]`);if(!u)throw new Error(`${e}[${i.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`);a=u}this.gl[o+"v"](s.location,l)}else{if(Array.isArray(r)||(r=[r]),r.length!==s.length)throw new Error(`Invalid uniform value length: ${r.length}. Expected ${s.length}.`);this.gl[o](s.location,...r)}}),this.hooks.get("updateUniforms")?.forEach(e=>e.call(this,...arguments))}createTexture(t,i,e){let{width:r,height:s}=i,o=i.history?.depth??0,h=this.gl.createTexture();if(!h)throw new Error("Failed to create texture");if(typeof e!="number")try{e=this.reserveTextureUnit(t)}catch(u){throw this.gl.deleteTexture(h),u}let l=o>0,a=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D;return this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(a,h),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(a,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),l&&this.gl.texStorage3D(a,1,this.gl.RGBA8,r,s,o),{texture:h,unitIndex:e}}_initializeTexture(t,i,e){if(this.textures.has(t))throw new Error(`Texture '${g(t)}' is already initialized.`);let r=e?.history??0,{width:s,height:o}=p(i);if(!s||!o)throw new Error("Texture source must have valid dimensions");let h={width:s,height:o};r>0&&(h.history={depth:r,writeIndex:0});let{texture:l,unitIndex:a}=this.createTexture(t,h),u={texture:l,unitIndex:a,...h};r>0&&(this.initializeUniform(`${g(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(u)),this.textures.set(t,u),this.updateTexture(t,i);let d=this.gl.getUniformLocation(this.program,g(t));d&&this.gl.uniform1i(d,a)}initializeTexture(t,i,e){this._initializeTexture(t,i,e),this.hooks.get("initializeTexture")?.forEach(r=>r.call(this,...arguments))}updateTextures(t){this.hooks.get("updateTextures")?.forEach(i=>i.call(this,...arguments)),Object.entries(t).forEach(([i,e])=>{this.updateTexture(i,e)})}updateTexture(t,i){let e=this.textures.get(t);if(!e)throw new Error(`Texture '${g(t)}' is not initialized.`);let{width:r,height:s}=p(i);if(e.width!==r||e.height!==s){this.gl.deleteTexture(e.texture),e.width=r,e.height=s;let{texture:o}=this.createTexture(t,e,e.unitIndex);e.texture=o,e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}if(e.history){let o=t===c;this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,e.texture),o?this.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,0,0,r,s):this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,r,s,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);let h=`${g(t)}FrameOffset`;this.updateUniforms({[h]:e.history.writeIndex}),e.history.writeIndex=(e.history.writeIndex+1)%e.history.depth}else this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}draw(){let t=this.gl;t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6)}step(t){this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.draw(),this.textures.get(c)&&this.updateTexture(c,this.canvas),this.hooks.get("step")?.forEach(i=>i.call(this,t,this.frame)),++this.frame}play(t){this.pause();let i=e=>{e=(e-this.startTime)/1e3,this.step(e),this.animationFrameId=requestAnimationFrame(i),t&&t(e,this.frame)};this.animationFrameId=requestAnimationFrame(i)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.hooks.get("reset")?.forEach(t=>t.call(this))}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.eventListeners.forEach((t,i)=>{this.canvas.removeEventListener(i,t)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(t=>{this.gl.deleteTexture(t.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.hooks.get("destroy")?.forEach(t=>t.call(this)),this.isInternalCanvas&&this.canvas.remove()}},L=m;
|
|
10
|
+
`)}function p(n){if(n instanceof HTMLVideoElement)return{width:n.videoWidth,height:n.videoHeight};if(n instanceof HTMLCanvasElement){let t=n.getContext("webgl2");return t?{width:t.drawingBufferWidth,height:t.drawingBufferHeight}:{width:n.width,height:n.height}}return{width:n.naturalWidth??n.width,height:n.naturalHeight??n.height}}function g(n){return typeof n=="symbol"?n.description??"":n}var m=class{isInternalCanvas=!1;isTouchDevice=!1;gl;fragmentShaderSrc;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;onResize;hooks=new Map;historyDepth;constructor(t,i={}){if(this.canvas=i.canvas||document.createElement("canvas"),i.canvas||(this.isInternalCanvas=!0,this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw",document.body.appendChild(this.canvas)),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.textureUnitPool={free:[],next:0,max:this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.historyDepth=i.history??0,this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let e=[];if(i.plugins){let r={gl:this.gl,uniforms:this.uniforms,textures:this.textures,canvas:this.canvas,reserveTextureUnit:this.reserveTextureUnit.bind(this),releaseTextureUnit:this.releaseTextureUnit.bind(this),injectGLSL:s=>{e.push(s)}};Object.defineProperty(r,"program",{get:()=>this.program,enumerable:!0,configurable:!0}),i.plugins.forEach(s=>s(this,r))}this.fragmentShaderSrc=L(t,e),this.init(),this.addEventListeners()}registerHook(t,i){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(i)}init(){let t=w;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let i=this.createShader(this.gl.VERTEX_SHADER,t),e=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,i),this.gl.attachShader(this.program,e),this.gl.linkProgram(this.program),this.gl.deleteShader(i),this.gl.deleteShader(e),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw console.error("Program link error:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),new Error("Failed to link WebGL program");let r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.gl.useProgram(this.program),this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyDepth>0&&this._initializeTexture(c,this.canvas,{history:this.historyDepth}),this.hooks.get("init")?.forEach(s=>s.call(this))}createShader(t,i){let e=this.gl.createShader(t);if(this.gl.shaderSource(e,i),this.gl.compileShader(e),!this.gl.getShaderParameter(e,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",i),console.error(this.gl.getShaderInfoLog(e)),this.gl.deleteShader(e),new Error("Shader compilation failed");return e}setupBuffer(t){let i=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),i=this.lastResizeTime+R-t;i<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),i)}handleResize(){let t=window.devicePixelRatio||1,i=this.canvas.clientWidth*t,e=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==i||this.canvas.height!==e)&&(this.canvas.width=i,this.canvas.height=e),this.onResize?.(i,e)}addEventListeners(){let t=(e,r)=>{if(!this.uniforms.has("u_cursor"))return;let s=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(e-s.left)/s.width,this.cursorPosition[1]=1-(r-s.top)/s.height,this.updateUniforms({u_cursor:this.cursorPosition})},i=(e,r,s)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=e,e){let o=this.canvas.getBoundingClientRect(),h=r,l=s;this.clickPosition[0]=(h-o.left)/o.width,this.clickPosition[1]=1-(l-o.top)/o.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",e=>{let r=e;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",e=>{let r=e;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,i(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",e=>{let r=e;this.isTouchDevice||r.button===0&&i(!1)}),this.eventListeners.set("touchmove",e=>{let r=e;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",e=>{let r=e;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),i(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",e=>{e.touches.length===0&&i(!1)}),this.eventListeners.forEach((e,r)=>{this.canvas.addEventListener(r,e)})}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.hooks.get("updateResolution")?.forEach(i=>i.call(this))}reserveTextureUnit(t){let i=this.textures.get(t);if(i)return i.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(t){let i=this.textures.get(t);i&&this.textureUnitPool.free.push(i.unitIndex)}clearHistoryTextureLayers(t){if(!t.history)return;let i=new Uint8Array(t.width*t.height*4);this.gl.activeTexture(this.gl.TEXTURE0+t.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,t.texture),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1);for(let e=0;e<t.history.depth;++e)this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e,t.width,t.height,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0)}initializeUniform(t,i,e,r){let s=r?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(i!=="float"&&i!=="int")throw new Error(`Invalid uniform type: ${i}. Expected 'float' or 'int'.`);if(s&&!(Array.isArray(e)&&e.length===s))throw new Error(`${t} array length mismatch: must initialize with ${s} elements.`);let o=this.gl.getUniformLocation(this.program,t);if(!o&&s&&(o=this.gl.getUniformLocation(this.program,`${t}[0]`)),!o){console.debug(`${t} not found in fragment shader. Skipping initialization.`);return}let h=s?e[0]:e,l=Array.isArray(h)?h.length:1;this.uniforms.set(t,{type:i,length:l,location:o,arrayLength:s});try{this.updateUniforms({[t]:e})}catch(a){throw this.uniforms.delete(t),a}this.hooks.get("initializeUniform")?.forEach(a=>a.call(this,...arguments))}updateUniforms(t,i){Object.entries(t).forEach(([e,r])=>{let s=this.uniforms.get(e);if(!s){console.debug(`${e} not found in fragment shader. Skipping update.`);return}let o=`uniform${s.length}${s.type.charAt(0)}`;if(s.arrayLength){if(!Array.isArray(r))throw new Error(`${e} is an array, but the value passed to updateUniforms is not an array.`);let h=r.length;if(!h)return;if(h>s.arrayLength)throw new Error(`${e} received ${h} values, but maximum length is ${s.arrayLength}.`);if(r.some(u=>(Array.isArray(u)?u.length:1)!==s.length))throw new Error(`Tried to update ${e} with some elements that are not length ${s.length}.`);let l=new(s.type==="float"?Float32Array:Int32Array)(r.flat()),a=s.location;if(i?.startIndex){let u=this.gl.getUniformLocation(this.program,`${e}[${i.startIndex}]`);if(!u)throw new Error(`${e}[${i.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`);a=u}this.gl[o+"v"](s.location,l)}else{if(Array.isArray(r)||(r=[r]),r.length!==s.length)throw new Error(`Invalid uniform value length: ${r.length}. Expected ${s.length}.`);this.gl[o](s.location,...r)}}),this.hooks.get("updateUniforms")?.forEach(e=>e.call(this,...arguments))}createTexture(t,i,e){let{width:r,height:s}=i,o=i.history?.depth??0,h=this.gl.createTexture();if(!h)throw new Error("Failed to create texture");if(typeof e!="number")try{e=this.reserveTextureUnit(t)}catch(u){throw this.gl.deleteTexture(h),u}let l=o>0,a=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D;return this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(a,h),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(a,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),l&&this.gl.texStorage3D(a,1,this.gl.RGBA8,r,s,o),{texture:h,unitIndex:e}}_initializeTexture(t,i,e){if(this.textures.has(t))throw new Error(`Texture '${g(t)}' is already initialized.`);let r=e?.history??0,{width:s,height:o}=p(i);if(!s||!o)throw new Error("Texture source must have valid dimensions");let h={width:s,height:o};r>0&&(h.history={depth:r,writeIndex:0});let{texture:l,unitIndex:a}=this.createTexture(t,h),u={texture:l,unitIndex:a,...h};r>0&&(this.initializeUniform(`${g(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(u)),this.textures.set(t,u),this.updateTexture(t,i);let d=this.gl.getUniformLocation(this.program,g(t));d&&this.gl.uniform1i(d,a)}initializeTexture(t,i,e){this._initializeTexture(t,i,e),this.hooks.get("initializeTexture")?.forEach(r=>r.call(this,...arguments))}updateTextures(t){this.hooks.get("updateTextures")?.forEach(i=>i.call(this,...arguments)),Object.entries(t).forEach(([i,e])=>{this.updateTexture(i,e)})}updateTexture(t,i){let e=this.textures.get(t);if(!e)throw new Error(`Texture '${g(t)}' is not initialized.`);let{width:r,height:s}=p(i);if(e.width!==r||e.height!==s){this.gl.deleteTexture(e.texture),e.width=r,e.height=s;let{texture:o}=this.createTexture(t,e,e.unitIndex);e.texture=o,e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}if(e.history){let o=t===c;this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,e.texture),o?(this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1),this.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,0,0,r,s),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0)):this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,r,s,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);let h=`${g(t)}FrameOffset`;this.updateUniforms({[h]:e.history.writeIndex}),e.history.writeIndex=(e.history.writeIndex+1)%e.history.depth}else this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}draw(){let t=this.gl;t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6)}step(t){this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.draw(),this.textures.get(c)&&this.updateTexture(c,this.canvas),this.hooks.get("step")?.forEach(i=>i.call(this,t,this.frame)),++this.frame}play(t){this.pause();let i=e=>{e=(e-this.startTime)/1e3,this.step(e),this.animationFrameId=requestAnimationFrame(i),t&&t(e,this.frame)};this.animationFrameId=requestAnimationFrame(i)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.hooks.get("reset")?.forEach(t=>t.call(this))}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.eventListeners.forEach((t,i)=>{this.canvas.removeEventListener(i,t)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(t=>{this.gl.deleteTexture(t.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.hooks.get("destroy")?.forEach(t=>t.call(this)),this.isInternalCanvas&&this.canvas.remove()}},_=m;
|
|
11
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\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}\n\nexport type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options {\n\tcanvas?: HTMLCanvasElement | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource) {\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t} else if (source instanceof HTMLCanvasElement) {\n\t\tconst gl = source.getContext('webgl2');\n\t\treturn gl\n\t\t\t? { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight }\n\t\t\t: { width: source.width, height: source.height };\n\t}\n\t// HTMLImageElement\n\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth: number;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tthis.canvas.style.position = 'fixed';\n\t\t\tthis.canvas.style.inset = '0';\n\t\t\tthis.canvas.style.height = '100dvh';\n\t\t\tthis.canvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(this.canvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.historyDepth = options.history ?? 0;\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (options.plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\toptions.plugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tconst aPosition = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer(aPosition);\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\tthis.resizeObserver.observe(this.canvas);\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, { history: this.historyDepth });\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer(aPosition: number) {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst transparent = new Uint8Array(textureInfo.width * textureInfo.height * 4);\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tthis.gl.texSubImage3D(\n\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](uniform.location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history'>,\n\t\tunitIndex?: 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\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\t// Flip the texture vertically during upload to match WebGL’s coordinate system.\n\t\t// WebGL uses bottom-left origin, while images/videos use top-left origin.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, this.gl.RGBA8, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(name: string | symbol, source: TextureSource, options?: { history?: number }) {\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 historyDepth = options?.history ?? 0;\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history'> = { width, height };\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, TextureSource>) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: TextureSource) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (info.width !== width || info.height !== height) {\n\t\t\tthis.gl.deleteTexture(info.texture);\n\t\t\tinfo.width = width;\n\t\t\tinfo.height = height;\n\t\t\tconst { texture } = this.createTexture(name, info, info.unitIndex);\n\t\t\tinfo.texture = texture;\n\t\t\tif (info.history) {\n\t\t\t\tinfo.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t\t}\n\t\t}\n\n\t\tif (info.history) {\n\t\t\tconst isFramebufferHistory = name === HISTORY_TEXTURE_KEY;\n\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (isFramebufferHistory) {\n\t\t\t\tthis.gl.copyTexSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tthis.gl.RGBA,\n\t\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\t\tsource\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, source);\n\t\t}\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t}\n\n\tstep(time: number) {\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\tthis.draw();\n\n\t\tif (this.textures.get(HISTORY_TEXTURE_KEY)) {\n\t\t\tthis.updateTexture(HISTORY_TEXTURE_KEY, this.canvas);\n\t\t}\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t});\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["index_exports","__export","index_default","__toCommonJS","DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","gl","stringFrom","name","ShaderPad","fragmentShaderSrc","options","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","aPosition","hook","type","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","existing","textureInfo","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","unitIndex","historyDepth","texture","hasHistory","textureTarget","completeTextureInfo","uSampler","info","isFramebufferHistory","frameOffsetUniformName","time","callback","loop"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\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}\n\nexport type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options {\n\tcanvas?: HTMLCanvasElement | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource) {\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t} else if (source instanceof HTMLCanvasElement) {\n\t\tconst gl = source.getContext('webgl2');\n\t\treturn gl\n\t\t\t? { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight }\n\t\t\t: { width: source.width, height: source.height };\n\t}\n\t// HTMLImageElement\n\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth: number;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tthis.canvas.style.position = 'fixed';\n\t\t\tthis.canvas.style.inset = '0';\n\t\t\tthis.canvas.style.height = '100dvh';\n\t\t\tthis.canvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(this.canvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.historyDepth = options.history ?? 0;\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (options.plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\toptions.plugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tconst aPosition = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer(aPosition);\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\tthis.resizeObserver.observe(this.canvas);\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, { history: this.historyDepth });\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer(aPosition: number) {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst transparent = new Uint8Array(textureInfo.width * textureInfo.height * 4);\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tthis.gl.texSubImage3D(\n\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](uniform.location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history'>,\n\t\tunitIndex?: 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\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\t// Flip the texture vertically during upload to match WebGL’s coordinate system.\n\t\t// WebGL uses bottom-left origin, while images/videos use top-left origin.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, this.gl.RGBA8, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(name: string | symbol, source: TextureSource, options?: { history?: number }) {\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 historyDepth = options?.history ?? 0;\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history'> = { width, height };\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, TextureSource>) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: TextureSource) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (info.width !== width || info.height !== height) {\n\t\t\tthis.gl.deleteTexture(info.texture);\n\t\t\tinfo.width = width;\n\t\t\tinfo.height = height;\n\t\t\tconst { texture } = this.createTexture(name, info, info.unitIndex);\n\t\t\tinfo.texture = texture;\n\t\t\tif (info.history) {\n\t\t\t\tinfo.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t\t}\n\t\t}\n\n\t\tif (info.history) {\n\t\t\tconst isFramebufferHistory = name === HISTORY_TEXTURE_KEY;\n\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (isFramebufferHistory) {\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n\t\t\t\tthis.gl.copyTexSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight\n\t\t\t\t);\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\t\t} else {\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tthis.gl.RGBA,\n\t\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\t\tsource\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, source);\n\t\t}\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t}\n\n\tstep(time: number) {\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\tthis.draw();\n\n\t\tif (this.textures.get(HISTORY_TEXTURE_KEY)) {\n\t\t\tthis.updateTexture(HISTORY_TEXTURE_KEY, this.canvas);\n\t\t}\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t});\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["index_exports","__export","index_default","__toCommonJS","DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","gl","stringFrom","name","ShaderPad","fragmentShaderSrc","options","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","aPosition","hook","type","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","existing","textureInfo","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","unitIndex","historyDepth","texture","hasHistory","textureTarget","completeTextureInfo","uSampler","info","isFramebufferHistory","frameOffsetUniformName","time","callback","loop"]}
|
package/dist/index.mjs
CHANGED
|
@@ -7,5 +7,5 @@ void main() {
|
|
|
7
7
|
}
|
|
8
8
|
`,T=33.333333333333336,c=Symbol("u_history");function v(o,t){if(!t?.length)return o;let i=o.split(`
|
|
9
9
|
`),e=i.findLastIndex(r=>{let s=r.trimStart();return s.startsWith("precision ")||s.startsWith("#version ")})+1;return i.splice(e,0,...t),i.join(`
|
|
10
|
-
`)}function d(o){if(o instanceof HTMLVideoElement)return{width:o.videoWidth,height:o.videoHeight};if(o instanceof HTMLCanvasElement){let t=o.getContext("webgl2");return t?{width:t.drawingBufferWidth,height:t.drawingBufferHeight}:{width:o.width,height:o.height}}return{width:o.naturalWidth??o.width,height:o.naturalHeight??o.height}}function g(o){return typeof o=="symbol"?o.description??"":o}var f=class{isInternalCanvas=!1;isTouchDevice=!1;gl;fragmentShaderSrc;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;onResize;hooks=new Map;historyDepth;constructor(t,i={}){if(this.canvas=i.canvas||document.createElement("canvas"),i.canvas||(this.isInternalCanvas=!0,this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw",document.body.appendChild(this.canvas)),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.textureUnitPool={free:[],next:0,max:this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.historyDepth=i.history??0,this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let e=[];if(i.plugins){let r={gl:this.gl,uniforms:this.uniforms,textures:this.textures,canvas:this.canvas,reserveTextureUnit:this.reserveTextureUnit.bind(this),releaseTextureUnit:this.releaseTextureUnit.bind(this),injectGLSL:s=>{e.push(s)}};Object.defineProperty(r,"program",{get:()=>this.program,enumerable:!0,configurable:!0}),i.plugins.forEach(s=>s(this,r))}this.fragmentShaderSrc=v(t,e),this.init(),this.addEventListeners()}registerHook(t,i){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(i)}init(){let t=p;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let i=this.createShader(this.gl.VERTEX_SHADER,t),e=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,i),this.gl.attachShader(this.program,e),this.gl.linkProgram(this.program),this.gl.deleteShader(i),this.gl.deleteShader(e),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw console.error("Program link error:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),new Error("Failed to link WebGL program");let r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.gl.useProgram(this.program),this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyDepth>0&&this._initializeTexture(c,this.canvas,{history:this.historyDepth}),this.hooks.get("init")?.forEach(s=>s.call(this))}createShader(t,i){let e=this.gl.createShader(t);if(this.gl.shaderSource(e,i),this.gl.compileShader(e),!this.gl.getShaderParameter(e,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",i),console.error(this.gl.getShaderInfoLog(e)),this.gl.deleteShader(e),new Error("Shader compilation failed");return e}setupBuffer(t){let i=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),i=this.lastResizeTime+T-t;i<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),i)}handleResize(){let t=window.devicePixelRatio||1,i=this.canvas.clientWidth*t,e=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==i||this.canvas.height!==e)&&(this.canvas.width=i,this.canvas.height=e),this.onResize?.(i,e)}addEventListeners(){let t=(e,r)=>{if(!this.uniforms.has("u_cursor"))return;let s=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(e-s.left)/s.width,this.cursorPosition[1]=1-(r-s.top)/s.height,this.updateUniforms({u_cursor:this.cursorPosition})},i=(e,r,s)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=e,e){let n=this.canvas.getBoundingClientRect(),h=r,l=s;this.clickPosition[0]=(h-n.left)/n.width,this.clickPosition[1]=1-(l-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",e=>{let r=e;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",e=>{let r=e;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,i(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",e=>{let r=e;this.isTouchDevice||r.button===0&&i(!1)}),this.eventListeners.set("touchmove",e=>{let r=e;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",e=>{let r=e;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),i(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",e=>{e.touches.length===0&&i(!1)}),this.eventListeners.forEach((e,r)=>{this.canvas.addEventListener(r,e)})}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.hooks.get("updateResolution")?.forEach(i=>i.call(this))}reserveTextureUnit(t){let i=this.textures.get(t);if(i)return i.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(t){let i=this.textures.get(t);i&&this.textureUnitPool.free.push(i.unitIndex)}clearHistoryTextureLayers(t){if(!t.history)return;let i=new Uint8Array(t.width*t.height*4);this.gl.activeTexture(this.gl.TEXTURE0+t.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,t.texture);for(let e=0;e<t.history.depth;++e)this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e,t.width,t.height,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}initializeUniform(t,i,e,r){let s=r?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(i!=="float"&&i!=="int")throw new Error(`Invalid uniform type: ${i}. Expected 'float' or 'int'.`);if(s&&!(Array.isArray(e)&&e.length===s))throw new Error(`${t} array length mismatch: must initialize with ${s} elements.`);let n=this.gl.getUniformLocation(this.program,t);if(!n&&s&&(n=this.gl.getUniformLocation(this.program,`${t}[0]`)),!n){console.debug(`${t} not found in fragment shader. Skipping initialization.`);return}let h=s?e[0]:e,l=Array.isArray(h)?h.length:1;this.uniforms.set(t,{type:i,length:l,location:n,arrayLength:s});try{this.updateUniforms({[t]:e})}catch(a){throw this.uniforms.delete(t),a}this.hooks.get("initializeUniform")?.forEach(a=>a.call(this,...arguments))}updateUniforms(t,i){Object.entries(t).forEach(([e,r])=>{let s=this.uniforms.get(e);if(!s){console.debug(`${e} not found in fragment shader. Skipping update.`);return}let n=`uniform${s.length}${s.type.charAt(0)}`;if(s.arrayLength){if(!Array.isArray(r))throw new Error(`${e} is an array, but the value passed to updateUniforms is not an array.`);let h=r.length;if(!h)return;if(h>s.arrayLength)throw new Error(`${e} received ${h} values, but maximum length is ${s.arrayLength}.`);if(r.some(u=>(Array.isArray(u)?u.length:1)!==s.length))throw new Error(`Tried to update ${e} with some elements that are not length ${s.length}.`);let l=new(s.type==="float"?Float32Array:Int32Array)(r.flat()),a=s.location;if(i?.startIndex){let u=this.gl.getUniformLocation(this.program,`${e}[${i.startIndex}]`);if(!u)throw new Error(`${e}[${i.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`);a=u}this.gl[n+"v"](s.location,l)}else{if(Array.isArray(r)||(r=[r]),r.length!==s.length)throw new Error(`Invalid uniform value length: ${r.length}. Expected ${s.length}.`);this.gl[n](s.location,...r)}}),this.hooks.get("updateUniforms")?.forEach(e=>e.call(this,...arguments))}createTexture(t,i,e){let{width:r,height:s}=i,n=i.history?.depth??0,h=this.gl.createTexture();if(!h)throw new Error("Failed to create texture");if(typeof e!="number")try{e=this.reserveTextureUnit(t)}catch(u){throw this.gl.deleteTexture(h),u}let l=n>0,a=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D;return this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(a,h),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(a,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),l&&this.gl.texStorage3D(a,1,this.gl.RGBA8,r,s,n),{texture:h,unitIndex:e}}_initializeTexture(t,i,e){if(this.textures.has(t))throw new Error(`Texture '${g(t)}' is already initialized.`);let r=e?.history??0,{width:s,height:n}=d(i);if(!s||!n)throw new Error("Texture source must have valid dimensions");let h={width:s,height:n};r>0&&(h.history={depth:r,writeIndex:0});let{texture:l,unitIndex:a}=this.createTexture(t,h),u={texture:l,unitIndex:a,...h};r>0&&(this.initializeUniform(`${g(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(u)),this.textures.set(t,u),this.updateTexture(t,i);let m=this.gl.getUniformLocation(this.program,g(t));m&&this.gl.uniform1i(m,a)}initializeTexture(t,i,e){this._initializeTexture(t,i,e),this.hooks.get("initializeTexture")?.forEach(r=>r.call(this,...arguments))}updateTextures(t){this.hooks.get("updateTextures")?.forEach(i=>i.call(this,...arguments)),Object.entries(t).forEach(([i,e])=>{this.updateTexture(i,e)})}updateTexture(t,i){let e=this.textures.get(t);if(!e)throw new Error(`Texture '${g(t)}' is not initialized.`);let{width:r,height:s}=d(i);if(e.width!==r||e.height!==s){this.gl.deleteTexture(e.texture),e.width=r,e.height=s;let{texture:n}=this.createTexture(t,e,e.unitIndex);e.texture=n,e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}if(e.history){let n=t===c;this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,e.texture),n?this.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,0,0,r,s):this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,r,s,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);let h=`${g(t)}FrameOffset`;this.updateUniforms({[h]:e.history.writeIndex}),e.history.writeIndex=(e.history.writeIndex+1)%e.history.depth}else this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}draw(){let t=this.gl;t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6)}step(t){this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.draw(),this.textures.get(c)&&this.updateTexture(c,this.canvas),this.hooks.get("step")?.forEach(i=>i.call(this,t,this.frame)),++this.frame}play(t){this.pause();let i=e=>{e=(e-this.startTime)/1e3,this.step(e),this.animationFrameId=requestAnimationFrame(i),t&&t(e,this.frame)};this.animationFrameId=requestAnimationFrame(i)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.hooks.get("reset")?.forEach(t=>t.call(this))}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.eventListeners.forEach((t,i)=>{this.canvas.removeEventListener(i,t)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(t=>{this.gl.deleteTexture(t.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.hooks.get("destroy")?.forEach(t=>t.call(this)),this.isInternalCanvas&&this.canvas.remove()}},x=f;export{x as default};
|
|
10
|
+
`)}function d(o){if(o instanceof HTMLVideoElement)return{width:o.videoWidth,height:o.videoHeight};if(o instanceof HTMLCanvasElement){let t=o.getContext("webgl2");return t?{width:t.drawingBufferWidth,height:t.drawingBufferHeight}:{width:o.width,height:o.height}}return{width:o.naturalWidth??o.width,height:o.naturalHeight??o.height}}function g(o){return typeof o=="symbol"?o.description??"":o}var f=class{isInternalCanvas=!1;isTouchDevice=!1;gl;fragmentShaderSrc;uniforms=new Map;textures=new Map;textureUnitPool;buffer=null;program=null;animationFrameId;resolutionObserver;resizeObserver;resizeTimeout=null;lastResizeTime=-1/0;eventListeners=new Map;frame=0;startTime=0;cursorPosition=[.5,.5];clickPosition=[.5,.5];isMouseDown=!1;canvas;onResize;hooks=new Map;historyDepth;constructor(t,i={}){if(this.canvas=i.canvas||document.createElement("canvas"),i.canvas||(this.isInternalCanvas=!0,this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw",document.body.appendChild(this.canvas)),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.textureUnitPool={free:[],next:0,max:this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS)},this.historyDepth=i.history??0,this.animationFrameId=null,this.resolutionObserver=new MutationObserver(()=>this.updateResolution()),this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize());let e=[];if(i.plugins){let r={gl:this.gl,uniforms:this.uniforms,textures:this.textures,canvas:this.canvas,reserveTextureUnit:this.reserveTextureUnit.bind(this),releaseTextureUnit:this.releaseTextureUnit.bind(this),injectGLSL:s=>{e.push(s)}};Object.defineProperty(r,"program",{get:()=>this.program,enumerable:!0,configurable:!0}),i.plugins.forEach(s=>s(this,r))}this.fragmentShaderSrc=v(t,e),this.init(),this.addEventListeners()}registerHook(t,i){this.hooks.has(t)||this.hooks.set(t,[]),this.hooks.get(t).push(i)}init(){let t=p;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let i=this.createShader(this.gl.VERTEX_SHADER,t),e=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,i),this.gl.attachShader(this.program,e),this.gl.linkProgram(this.program),this.gl.deleteShader(i),this.gl.deleteShader(e),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))throw console.error("Program link error:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),new Error("Failed to link WebGL program");let r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.gl.useProgram(this.program),this.resolutionObserver.observe(this.canvas,{attributes:!0,attributeFilter:["width","height"]}),this.resizeObserver.observe(this.canvas),this.isInternalCanvas||this.updateResolution(),this.initializeUniform("u_cursor","float",this.cursorPosition),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyDepth>0&&this._initializeTexture(c,this.canvas,{history:this.historyDepth}),this.hooks.get("init")?.forEach(s=>s.call(this))}createShader(t,i){let e=this.gl.createShader(t);if(this.gl.shaderSource(e,i),this.gl.compileShader(e),!this.gl.getShaderParameter(e,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",i),console.error(this.gl.getShaderInfoLog(e)),this.gl.deleteShader(e),new Error("Shader compilation failed");return e}setupBuffer(t){let i=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);this.buffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.buffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,i,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),i=this.lastResizeTime+T-t;i<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),i)}handleResize(){let t=window.devicePixelRatio||1,i=this.canvas.clientWidth*t,e=this.canvas.clientHeight*t;this.isInternalCanvas&&(this.canvas.width!==i||this.canvas.height!==e)&&(this.canvas.width=i,this.canvas.height=e),this.onResize?.(i,e)}addEventListeners(){let t=(e,r)=>{if(!this.uniforms.has("u_cursor"))return;let s=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(e-s.left)/s.width,this.cursorPosition[1]=1-(r-s.top)/s.height,this.updateUniforms({u_cursor:this.cursorPosition})},i=(e,r,s)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=e,e){let n=this.canvas.getBoundingClientRect(),h=r,l=s;this.clickPosition[0]=(h-n.left)/n.width,this.clickPosition[1]=1-(l-n.top)/n.height}this.updateUniforms({u_click:[...this.clickPosition,this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",e=>{let r=e;this.isTouchDevice||t(r.clientX,r.clientY)}),this.eventListeners.set("mousedown",e=>{let r=e;this.isTouchDevice||r.button===0&&(this.isMouseDown=!0,i(!0,r.clientX,r.clientY))}),this.eventListeners.set("mouseup",e=>{let r=e;this.isTouchDevice||r.button===0&&i(!1)}),this.eventListeners.set("touchmove",e=>{let r=e;r.touches.length>0&&t(r.touches[0].clientX,r.touches[0].clientY)}),this.eventListeners.set("touchstart",e=>{let r=e;this.isTouchDevice=!0,r.touches.length>0&&(t(r.touches[0].clientX,r.touches[0].clientY),i(!0,r.touches[0].clientX,r.touches[0].clientY))}),this.eventListeners.set("touchend",e=>{e.touches.length===0&&i(!1)}),this.eventListeners.forEach((e,r)=>{this.canvas.addEventListener(r,e)})}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.hooks.get("updateResolution")?.forEach(i=>i.call(this))}reserveTextureUnit(t){let i=this.textures.get(t);if(i)return i.unitIndex;if(this.textureUnitPool.free.length>0)return this.textureUnitPool.free.pop();if(this.textureUnitPool.next>=this.textureUnitPool.max)throw new Error("Exceeded the available texture units for this device.");return this.textureUnitPool.next++}releaseTextureUnit(t){let i=this.textures.get(t);i&&this.textureUnitPool.free.push(i.unitIndex)}clearHistoryTextureLayers(t){if(!t.history)return;let i=new Uint8Array(t.width*t.height*4);this.gl.activeTexture(this.gl.TEXTURE0+t.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,t.texture),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1);for(let e=0;e<t.history.depth;++e)this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e,t.width,t.height,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0)}initializeUniform(t,i,e,r){let s=r?.arrayLength;if(this.uniforms.has(t))throw new Error(`${t} is already initialized.`);if(i!=="float"&&i!=="int")throw new Error(`Invalid uniform type: ${i}. Expected 'float' or 'int'.`);if(s&&!(Array.isArray(e)&&e.length===s))throw new Error(`${t} array length mismatch: must initialize with ${s} elements.`);let n=this.gl.getUniformLocation(this.program,t);if(!n&&s&&(n=this.gl.getUniformLocation(this.program,`${t}[0]`)),!n){console.debug(`${t} not found in fragment shader. Skipping initialization.`);return}let h=s?e[0]:e,l=Array.isArray(h)?h.length:1;this.uniforms.set(t,{type:i,length:l,location:n,arrayLength:s});try{this.updateUniforms({[t]:e})}catch(a){throw this.uniforms.delete(t),a}this.hooks.get("initializeUniform")?.forEach(a=>a.call(this,...arguments))}updateUniforms(t,i){Object.entries(t).forEach(([e,r])=>{let s=this.uniforms.get(e);if(!s){console.debug(`${e} not found in fragment shader. Skipping update.`);return}let n=`uniform${s.length}${s.type.charAt(0)}`;if(s.arrayLength){if(!Array.isArray(r))throw new Error(`${e} is an array, but the value passed to updateUniforms is not an array.`);let h=r.length;if(!h)return;if(h>s.arrayLength)throw new Error(`${e} received ${h} values, but maximum length is ${s.arrayLength}.`);if(r.some(u=>(Array.isArray(u)?u.length:1)!==s.length))throw new Error(`Tried to update ${e} with some elements that are not length ${s.length}.`);let l=new(s.type==="float"?Float32Array:Int32Array)(r.flat()),a=s.location;if(i?.startIndex){let u=this.gl.getUniformLocation(this.program,`${e}[${i.startIndex}]`);if(!u)throw new Error(`${e}[${i.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`);a=u}this.gl[n+"v"](s.location,l)}else{if(Array.isArray(r)||(r=[r]),r.length!==s.length)throw new Error(`Invalid uniform value length: ${r.length}. Expected ${s.length}.`);this.gl[n](s.location,...r)}}),this.hooks.get("updateUniforms")?.forEach(e=>e.call(this,...arguments))}createTexture(t,i,e){let{width:r,height:s}=i,n=i.history?.depth??0,h=this.gl.createTexture();if(!h)throw new Error("Failed to create texture");if(typeof e!="number")try{e=this.reserveTextureUnit(t)}catch(u){throw this.gl.deleteTexture(h),u}let l=n>0,a=l?this.gl.TEXTURE_2D_ARRAY:this.gl.TEXTURE_2D;return this.gl.activeTexture(this.gl.TEXTURE0+e),this.gl.bindTexture(a,h),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(a,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(a,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),l&&this.gl.texStorage3D(a,1,this.gl.RGBA8,r,s,n),{texture:h,unitIndex:e}}_initializeTexture(t,i,e){if(this.textures.has(t))throw new Error(`Texture '${g(t)}' is already initialized.`);let r=e?.history??0,{width:s,height:n}=d(i);if(!s||!n)throw new Error("Texture source must have valid dimensions");let h={width:s,height:n};r>0&&(h.history={depth:r,writeIndex:0});let{texture:l,unitIndex:a}=this.createTexture(t,h),u={texture:l,unitIndex:a,...h};r>0&&(this.initializeUniform(`${g(t)}FrameOffset`,"int",0),this.clearHistoryTextureLayers(u)),this.textures.set(t,u),this.updateTexture(t,i);let m=this.gl.getUniformLocation(this.program,g(t));m&&this.gl.uniform1i(m,a)}initializeTexture(t,i,e){this._initializeTexture(t,i,e),this.hooks.get("initializeTexture")?.forEach(r=>r.call(this,...arguments))}updateTextures(t){this.hooks.get("updateTextures")?.forEach(i=>i.call(this,...arguments)),Object.entries(t).forEach(([i,e])=>{this.updateTexture(i,e)})}updateTexture(t,i){let e=this.textures.get(t);if(!e)throw new Error(`Texture '${g(t)}' is not initialized.`);let{width:r,height:s}=d(i);if(e.width!==r||e.height!==s){this.gl.deleteTexture(e.texture),e.width=r,e.height=s;let{texture:n}=this.createTexture(t,e,e.unitIndex);e.texture=n,e.history&&(e.history.writeIndex=0,this.clearHistoryTextureLayers(e))}if(e.history){let n=t===c;this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY,e.texture),n?(this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1),this.gl.copyTexSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,0,0,r,s),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0)):this.gl.texSubImage3D(this.gl.TEXTURE_2D_ARRAY,0,0,0,e.history.writeIndex,r,s,1,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i);let h=`${g(t)}FrameOffset`;this.updateUniforms({[h]:e.history.writeIndex}),e.history.writeIndex=(e.history.writeIndex+1)%e.history.depth}else this.gl.activeTexture(this.gl.TEXTURE0+e.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,e.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)}draw(){let t=this.gl;t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLES,0,6)}step(t){this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.draw(),this.textures.get(c)&&this.updateTexture(c,this.canvas),this.hooks.get("step")?.forEach(i=>i.call(this,t,this.frame)),++this.frame}play(t){this.pause();let i=e=>{e=(e-this.startTime)/1e3,this.step(e),this.animationFrameId=requestAnimationFrame(i),t&&t(e,this.frame)};this.animationFrameId=requestAnimationFrame(i)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}reset(){this.frame=0,this.startTime=performance.now(),this.textures.forEach(t=>{t.history&&(t.history.writeIndex=0,this.clearHistoryTextureLayers(t))}),this.hooks.get("reset")?.forEach(t=>t.call(this))}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resolutionObserver.disconnect(),this.resizeObserver.disconnect(),this.eventListeners.forEach((t,i)=>{this.canvas.removeEventListener(i,t)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(t=>{this.gl.deleteTexture(t.texture)}),this.textureUnitPool.free=[],this.textureUnitPool.next=0,this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.hooks.get("destroy")?.forEach(t=>t.call(this)),this.isInternalCanvas&&this.canvas.remove()}},x=f;export{x as default};
|
|
11
11
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\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}\n\nexport type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options {\n\tcanvas?: HTMLCanvasElement | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource) {\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t} else if (source instanceof HTMLCanvasElement) {\n\t\tconst gl = source.getContext('webgl2');\n\t\treturn gl\n\t\t\t? { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight }\n\t\t\t: { width: source.width, height: source.height };\n\t}\n\t// HTMLImageElement\n\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth: number;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tthis.canvas.style.position = 'fixed';\n\t\t\tthis.canvas.style.inset = '0';\n\t\t\tthis.canvas.style.height = '100dvh';\n\t\t\tthis.canvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(this.canvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.historyDepth = options.history ?? 0;\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (options.plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\toptions.plugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tconst aPosition = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer(aPosition);\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\tthis.resizeObserver.observe(this.canvas);\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, { history: this.historyDepth });\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer(aPosition: number) {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst transparent = new Uint8Array(textureInfo.width * textureInfo.height * 4);\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tthis.gl.texSubImage3D(\n\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](uniform.location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history'>,\n\t\tunitIndex?: 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\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\t// Flip the texture vertically during upload to match WebGL’s coordinate system.\n\t\t// WebGL uses bottom-left origin, while images/videos use top-left origin.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, this.gl.RGBA8, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(name: string | symbol, source: TextureSource, options?: { history?: number }) {\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 historyDepth = options?.history ?? 0;\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history'> = { width, height };\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, TextureSource>) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: TextureSource) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (info.width !== width || info.height !== height) {\n\t\t\tthis.gl.deleteTexture(info.texture);\n\t\t\tinfo.width = width;\n\t\t\tinfo.height = height;\n\t\t\tconst { texture } = this.createTexture(name, info, info.unitIndex);\n\t\t\tinfo.texture = texture;\n\t\t\tif (info.history) {\n\t\t\t\tinfo.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t\t}\n\t\t}\n\n\t\tif (info.history) {\n\t\t\tconst isFramebufferHistory = name === HISTORY_TEXTURE_KEY;\n\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (isFramebufferHistory) {\n\t\t\t\tthis.gl.copyTexSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tthis.gl.RGBA,\n\t\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\t\tsource\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, source);\n\t\t}\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t}\n\n\tstep(time: number) {\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\tthis.draw();\n\n\t\tif (this.textures.get(HISTORY_TEXTURE_KEY)) {\n\t\t\tthis.updateTexture(HISTORY_TEXTURE_KEY, this.canvas);\n\t\t}\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t});\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"AAAA,IAAMA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ5BC,EAA2B,mBA0D3BC,EAAsB,OAAO,WAAW,EAE9C,SAASC,EAAkBC,EAAgBC,EAA8B,CACxE,GAAI,CAACA,GAAY,OAAQ,OAAOD,EAChC,IAAME,EAAQF,EAAO,MAAM;AAAA,CAAI,EACzBG,EACLD,EAAM,cAAcE,GAAQ,CAC3B,IAAMC,EAAUD,EAAK,UAAU,EAC/B,OAAOC,EAAQ,WAAW,YAAY,GAAKA,EAAQ,WAAW,WAAW,CAC1E,CAAC,EAAI,EACN,OAAAH,EAAM,OAAOC,EAAU,EAAG,GAAGF,CAAU,EAChCC,EAAM,KAAK;AAAA,CAAI,CACvB,CAEA,SAASI,EAAoBC,EAAuB,CACnD,GAAIA,aAAkB,iBACrB,MAAO,CAAE,MAAOA,EAAO,WAAY,OAAQA,EAAO,WAAY,EACxD,GAAIA,aAAkB,kBAAmB,CAC/C,IAAMC,EAAKD,EAAO,WAAW,QAAQ,EACrC,OAAOC,EACJ,CAAE,MAAOA,EAAG,mBAAoB,OAAQA,EAAG,mBAAoB,EAC/D,CAAE,MAAOD,EAAO,MAAO,OAAQA,EAAO,MAAO,CACjD,CAEA,MAAO,CAAE,MAAOA,EAAO,cAAgBA,EAAO,MAAO,OAAQA,EAAO,eAAiBA,EAAO,MAAO,CACpG,CAEA,SAASE,EAAWC,EAAuB,CAC1C,OAAO,OAAOA,GAAS,SAAWA,EAAK,aAAe,GAAKA,CAC5D,CAEA,IAAMC,EAAN,KAAgB,CACP,iBAAmB,GACnB,cAAgB,GAChB,GACA,kBACA,SAAiC,IAAI,IACrC,SAA0C,IAAI,IAC9C,gBACA,OAA6B,KAC7B,QAA+B,KAC/B,iBACA,mBACA,eACA,cAA+C,KAC/C,eAAiB,KACjB,eAA6C,IAAI,IACjD,MAAQ,EACR,UAAY,EACZ,eAAiB,CAAC,GAAK,EAAG,EAC1B,cAAgB,CAAC,GAAK,EAAG,EACzB,YAAc,GACf,OACA,SACC,MAA0C,IAAI,IAC9C,aAER,YAAYC,EAA2BC,EAAmB,CAAC,EAAG,CAY7D,GAXA,KAAK,OAASA,EAAQ,QAAU,SAAS,cAAc,QAAQ,EAC1DA,EAAQ,SACZ,KAAK,iBAAmB,GACxB,KAAK,OAAO,MAAM,SAAW,QAC7B,KAAK,OAAO,MAAM,MAAQ,IAC1B,KAAK,OAAO,MAAM,OAAS,SAC3B,KAAK,OAAO,MAAM,MAAQ,SAC1B,SAAS,KAAK,YAAY,KAAK,MAAM,GAGtC,KAAK,GAAK,KAAK,OAAO,WAAW,SAAU,CAAE,UAAW,EAAM,CAAC,EAC3D,CAAC,KAAK,GACT,MAAM,IAAI,MAAM,kEAAkE,EAGnF,KAAK,gBAAkB,CACtB,KAAM,CAAC,EACP,KAAM,EACN,IAAK,KAAK,GAAG,aAAa,KAAK,GAAG,gCAAgC,CACnE,EACA,KAAK,aAAeA,EAAQ,SAAW,EACvC,KAAK,iBAAmB,KACxB,KAAK,mBAAqB,IAAI,iBAAiB,IAAM,KAAK,iBAAiB,CAAC,EAC5E,KAAK,eAAiB,IAAI,eAAe,IAAM,KAAK,sBAAsB,CAAC,EAE3E,IAAMC,EAA2B,CAAC,EAClC,GAAID,EAAQ,QAAS,CACpB,IAAME,EAAyB,CAC9B,GAAI,KAAK,GACT,SAAU,KAAK,SACf,SAAU,KAAK,SACf,OAAQ,KAAK,OACb,mBAAoB,KAAK,mBAAmB,KAAK,IAAI,EACrD,mBAAoB,KAAK,mBAAmB,KAAK,IAAI,EACrD,WAAaC,GAAiB,CAC7BF,EAAe,KAAKE,CAAI,CACzB,CACD,EAEA,OAAO,eAAeD,EAAS,UAAW,CACzC,IAAK,IAAM,KAAK,QAChB,WAAY,GACZ,aAAc,EACf,CAAC,EACDF,EAAQ,QAAQ,QAAQI,GAAUA,EAAO,KAAMF,CAAO,CAAC,CACxD,CAEA,KAAK,kBAAoBhB,EAAkBa,EAAmBE,CAAc,EAC5E,KAAK,KAAK,EACV,KAAK,kBAAkB,CACxB,CAEA,aAAaJ,EAAuBQ,EAAc,CAC5C,KAAK,MAAM,IAAIR,CAAI,GACvB,KAAK,MAAM,IAAIA,EAAM,CAAC,CAAC,EAExB,KAAK,MAAM,IAAIA,CAAI,EAAG,KAAKQ,CAAE,CAC9B,CAEQ,MAAO,CACd,IAAMC,EAAkBvB,EAGxB,GADA,KAAK,QAAU,KAAK,GAAG,cAAc,EACjC,CAAC,KAAK,QACT,MAAM,IAAI,MAAM,gCAAgC,EAEjD,IAAMwB,EAAe,KAAK,aAAa,KAAK,GAAG,cAAeD,CAAe,EACvEE,EAAiB,KAAK,aAAa,KAAK,GAAG,gBAAiB,KAAK,iBAAiB,EAQxF,GANA,KAAK,GAAG,aAAa,KAAK,QAASD,CAAY,EAC/C,KAAK,GAAG,aAAa,KAAK,QAASC,CAAc,EACjD,KAAK,GAAG,YAAY,KAAK,OAAO,EAChC,KAAK,GAAG,aAAaD,CAAY,EACjC,KAAK,GAAG,aAAaC,CAAc,EAE/B,CAAC,KAAK,GAAG,oBAAoB,KAAK,QAAS,KAAK,GAAG,WAAW,EACjE,cAAQ,MAAM,sBAAuB,KAAK,GAAG,kBAAkB,KAAK,OAAO,CAAC,EAC5E,KAAK,GAAG,cAAc,KAAK,OAAO,EAC5B,IAAI,MAAM,8BAA8B,EAG/C,IAAMC,EAAY,KAAK,GAAG,kBAAkB,KAAK,QAAS,WAAW,EACrE,KAAK,YAAYA,CAAS,EAE1B,KAAK,GAAG,WAAW,KAAK,OAAO,EAE/B,KAAK,mBAAmB,QAAQ,KAAK,OAAQ,CAAE,WAAY,GAAM,gBAAiB,CAAC,QAAS,QAAQ,CAAE,CAAC,EACvG,KAAK,eAAe,QAAQ,KAAK,MAAM,EAElC,KAAK,kBACT,KAAK,iBAAiB,EAEvB,KAAK,kBAAkB,WAAY,QAAS,KAAK,cAAc,EAC/D,KAAK,kBAAkB,UAAW,QAAS,CAAC,GAAG,KAAK,cAAe,KAAK,YAAc,EAAM,CAAG,CAAC,EAChG,KAAK,kBAAkB,SAAU,QAAS,CAAC,EAC3C,KAAK,kBAAkB,UAAW,MAAO,CAAC,EACtC,KAAK,aAAe,GACvB,KAAK,mBAAmBxB,EAAqB,KAAK,OAAQ,CAAE,QAAS,KAAK,YAAa,CAAC,EAGzF,KAAK,MAAM,IAAI,MAAM,GAAG,QAAQyB,GAAQA,EAAK,KAAK,IAAI,CAAC,CACxD,CAEQ,aAAaC,EAAcjB,EAA6B,CAC/D,IAAMP,EAAS,KAAK,GAAG,aAAawB,CAAI,EAGxC,GAFA,KAAK,GAAG,aAAaxB,EAAQO,CAAM,EACnC,KAAK,GAAG,cAAcP,CAAM,EACxB,CAAC,KAAK,GAAG,mBAAmBA,EAAQ,KAAK,GAAG,cAAc,EAC7D,cAAQ,MAAM,6BAA8BO,CAAM,EAClD,QAAQ,MAAM,KAAK,GAAG,iBAAiBP,CAAM,CAAC,EAC9C,KAAK,GAAG,aAAaA,CAAM,EACrB,IAAI,MAAM,2BAA2B,EAE5C,OAAOA,CACR,CAEQ,YAAYsB,EAAmB,CACtC,IAAMG,EAAe,IAAI,aAAa,CAAC,GAAI,GAAI,EAAG,GAAI,GAAI,EAAG,GAAI,EAAG,EAAG,GAAI,EAAG,CAAC,CAAC,EAEhF,KAAK,OAAS,KAAK,GAAG,aAAa,EACnC,KAAK,GAAG,WAAW,KAAK,GAAG,aAAc,KAAK,MAAM,EACpD,KAAK,GAAG,WAAW,KAAK,GAAG,aAAcA,EAAc,KAAK,GAAG,WAAW,EAC1E,KAAK,GAAG,SAAS,EAAG,EAAG,KAAK,GAAG,mBAAoB,KAAK,GAAG,mBAAmB,EAC9E,KAAK,GAAG,wBAAwBH,CAAS,EACzC,KAAK,GAAG,oBAAoBA,EAAW,EAAG,KAAK,GAAG,MAAO,GAAO,EAAG,CAAC,CACrE,CAEQ,uBAAwB,CAC/B,aAAa,KAAK,aAAa,EAC/B,IAAMI,EAAM,YAAY,IAAI,EACtBC,EAAsB,KAAK,eAAiB9B,EAA2B6B,EACzEC,GAAuB,GAC1B,KAAK,eAAiBD,EACtB,KAAK,aAAa,GAElB,KAAK,cAAgB,WAAW,IAAM,KAAK,sBAAsB,EAAGC,CAAmB,CAEzF,CAEQ,cAAe,CACtB,IAAMC,EAAa,OAAO,kBAAoB,EACxCC,EAAQ,KAAK,OAAO,YAAcD,EAClCE,EAAS,KAAK,OAAO,aAAeF,EACtC,KAAK,mBAAqB,KAAK,OAAO,QAAUC,GAAS,KAAK,OAAO,SAAWC,KACnF,KAAK,OAAO,MAAQD,EACpB,KAAK,OAAO,OAASC,GAEtB,KAAK,WAAWD,EAAOC,CAAM,CAC9B,CAEQ,mBAAoB,CAC3B,IAAMC,EAAe,CAACC,EAAWC,IAAc,CAC9C,GAAI,CAAC,KAAK,SAAS,IAAI,UAAU,EAAG,OACpC,IAAMC,EAAO,KAAK,OAAO,sBAAsB,EAC/C,KAAK,eAAe,CAAC,GAAKF,EAAIE,EAAK,MAAQA,EAAK,MAChD,KAAK,eAAe,CAAC,EAAI,GAAKD,EAAIC,EAAK,KAAOA,EAAK,OACnD,KAAK,eAAe,CAAE,SAAU,KAAK,cAAe,CAAC,CACtD,EAEMC,EAAc,CAACC,EAAsBJ,EAAYC,IAAe,CACrE,GAAK,KAAK,SAAS,IAAI,SAAS,EAEhC,IADA,KAAK,YAAcG,EACfA,EAAa,CAChB,IAAMF,EAAO,KAAK,OAAO,sBAAsB,EACzCG,EAAOL,EACPM,EAAOL,EACb,KAAK,cAAc,CAAC,GAAKI,EAAOH,EAAK,MAAQA,EAAK,MAClD,KAAK,cAAc,CAAC,EAAI,GAAKI,EAAOJ,EAAK,KAAOA,EAAK,MACtD,CACA,KAAK,eAAe,CAAE,QAAS,CAAC,GAAG,KAAK,cAAe,KAAK,YAAc,EAAM,CAAG,CAAE,CAAC,EACvF,EAEA,KAAK,eAAe,IAAI,YAAaK,GAAS,CAC7C,IAAMC,EAAaD,EACd,KAAK,eACTR,EAAaS,EAAW,QAASA,EAAW,OAAO,CAErD,CAAC,EAED,KAAK,eAAe,IAAI,YAAaD,GAAS,CAC7C,IAAMC,EAAaD,EACd,KAAK,eACLC,EAAW,SAAW,IACzB,KAAK,YAAc,GACnBL,EAAY,GAAMK,EAAW,QAASA,EAAW,OAAO,EAG3D,CAAC,EAED,KAAK,eAAe,IAAI,UAAWD,GAAS,CAC3C,IAAMC,EAAaD,EACd,KAAK,eACLC,EAAW,SAAW,GACzBL,EAAY,EAAK,CAGpB,CAAC,EAED,KAAK,eAAe,IAAI,YAAaI,GAAS,CAC7C,IAAME,EAAaF,EACfE,EAAW,QAAQ,OAAS,GAC/BV,EAAaU,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,CAE3E,CAAC,EAED,KAAK,eAAe,IAAI,aAAcF,GAAS,CAC9C,IAAME,EAAaF,EACnB,KAAK,cAAgB,GACjBE,EAAW,QAAQ,OAAS,IAC/BV,EAAaU,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,EACzEN,EAAY,GAAMM,EAAW,QAAQ,CAAC,EAAE,QAASA,EAAW,QAAQ,CAAC,EAAE,OAAO,EAEhF,CAAC,EAED,KAAK,eAAe,IAAI,WAAYF,GAAS,CACzBA,EACJ,QAAQ,SAAW,GACjCJ,EAAY,EAAK,CAEnB,CAAC,EAED,KAAK,eAAe,QAAQ,CAACO,EAAUH,IAAU,CAChD,KAAK,OAAO,iBAAiBA,EAAOG,CAAQ,CAC7C,CAAC,CACF,CAEQ,kBAAmB,CAC1B,IAAMC,EAA+B,CAAC,KAAK,GAAG,mBAAoB,KAAK,GAAG,mBAAmB,EAC7F,KAAK,GAAG,SAAS,EAAG,EAAG,GAAGA,CAAU,EAChC,KAAK,SAAS,IAAI,cAAc,EACnC,KAAK,eAAe,CAAE,aAAcA,CAAW,CAAC,EAEhD,KAAK,kBAAkB,eAAgB,QAASA,CAAU,EAE3D,KAAK,MAAM,IAAI,kBAAkB,GAAG,QAAQpB,GAAQA,EAAK,KAAK,IAAI,CAAC,CACpE,CAEQ,mBAAmBb,EAAuB,CACjD,IAAMkC,EAAW,KAAK,SAAS,IAAIlC,CAAI,EACvC,GAAIkC,EAAU,OAAOA,EAAS,UAC9B,GAAI,KAAK,gBAAgB,KAAK,OAAS,EAAG,OAAO,KAAK,gBAAgB,KAAK,IAAI,EAC/E,GAAI,KAAK,gBAAgB,MAAQ,KAAK,gBAAgB,IACrD,MAAM,IAAI,MAAM,uDAAuD,EAExE,OAAO,KAAK,gBAAgB,MAC7B,CAEQ,mBAAmBlC,EAAuB,CACjD,IAAMkC,EAAW,KAAK,SAAS,IAAIlC,CAAI,EACnCkC,GACH,KAAK,gBAAgB,KAAK,KAAKA,EAAS,SAAS,CAEnD,CAEQ,0BAA0BC,EAA4B,CAC7D,GAAI,CAACA,EAAY,QAAS,OAE1B,IAAMC,EAAc,IAAI,WAAWD,EAAY,MAAQA,EAAY,OAAS,CAAC,EAC7E,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWA,EAAY,SAAS,EAC9D,KAAK,GAAG,YAAY,KAAK,GAAG,iBAAkBA,EAAY,OAAO,EACjE,QAASE,EAAQ,EAAGA,EAAQF,EAAY,QAAQ,MAAO,EAAEE,EACxD,KAAK,GAAG,cACP,KAAK,GAAG,iBACR,EACA,EACA,EACAA,EACAF,EAAY,MACZA,EAAY,OACZ,EACA,KAAK,GAAG,KACR,KAAK,GAAG,cACRC,CACD,CAEF,CAEA,kBACCpC,EACAc,EACAwB,EACAnC,EACC,CACD,IAAMoC,EAAcpC,GAAS,YAC7B,GAAI,KAAK,SAAS,IAAIH,CAAI,EACzB,MAAM,IAAI,MAAM,GAAGA,CAAI,0BAA0B,EAElD,GAAIc,IAAS,SAAWA,IAAS,MAChC,MAAM,IAAI,MAAM,yBAAyBA,CAAI,8BAA8B,EAE5E,GAAIyB,GAAe,EAAE,MAAM,QAAQD,CAAK,GAAKA,EAAM,SAAWC,GAC7D,MAAM,IAAI,MAAM,GAAGvC,CAAI,gDAAgDuC,CAAW,YAAY,EAG/F,IAAIC,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAUxC,CAAI,EAI7D,GAHI,CAACwC,GAAYD,IAChBC,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAU,GAAGxC,CAAI,KAAK,GAE9D,CAACwC,EAAU,CACd,QAAQ,MAAM,GAAGxC,CAAI,yDAAyD,EAC9E,MACD,CAEA,IAAMyC,EAAaF,EAAeD,EAAgC,CAAC,EAAIA,EACjEI,EAAS,MAAM,QAAQD,CAAU,EAAKA,EAAW,OAA2B,EAClF,KAAK,SAAS,IAAIzC,EAAM,CAAE,KAAAc,EAAM,OAAA4B,EAAQ,SAAAF,EAAU,YAAAD,CAAY,CAAC,EAE/D,GAAI,CACH,KAAK,eAAe,CAAE,CAACvC,CAAI,EAAGsC,CAAM,CAAC,CACtC,OAASK,EAAO,CACf,WAAK,SAAS,OAAO3C,CAAI,EACnB2C,CACP,CACA,KAAK,MAAM,IAAI,mBAAmB,GAAG,QAAQ9B,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CACnF,CAEA,eACC+B,EACAzC,EACC,CACD,OAAO,QAAQyC,CAAO,EAAE,QAAQ,CAAC,CAAC5C,EAAMsC,CAAK,IAAM,CAClD,IAAMO,EAAU,KAAK,SAAS,IAAI7C,CAAI,EACtC,GAAI,CAAC6C,EAAS,CACb,QAAQ,MAAM,GAAG7C,CAAI,iDAAiD,EACtE,MACD,CAEA,IAAI8C,EAAiB,UAAUD,EAAQ,MAAM,GAAGA,EAAQ,KAAK,OAAO,CAAC,CAAC,GACtE,GAAIA,EAAQ,YAAa,CACxB,GAAI,CAAC,MAAM,QAAQP,CAAK,EACvB,MAAM,IAAI,MAAM,GAAGtC,CAAI,uEAAuE,EAE/F,IAAM+C,EAAUT,EAAM,OACtB,GAAI,CAACS,EAAS,OACd,GAAIA,EAAUF,EAAQ,YACrB,MAAM,IAAI,MACT,GAAG7C,CAAI,aAAa+C,CAAO,kCAAkCF,EAAQ,WAAW,GACjF,EAED,GAAIP,EAAM,KAAKU,IAAS,MAAM,QAAQA,CAAI,EAAIA,EAAK,OAAS,KAAOH,EAAQ,MAAM,EAChF,MAAM,IAAI,MACT,mBAAmB7C,CAAI,2CAA2C6C,EAAQ,MAAM,GACjF,EAED,IAAMI,EAAa,IAAKJ,EAAQ,OAAS,QAAU,aAAe,YAAYP,EAAM,KAAK,CAAC,EACtFE,EAAWK,EAAQ,SACvB,GAAI1C,GAAS,WAAY,CACxB,IAAM+C,EAAc,KAAK,GAAG,mBAAmB,KAAK,QAAU,GAAGlD,CAAI,IAAIG,EAAQ,UAAU,GAAG,EAC9F,GAAI,CAAC+C,EACJ,MAAM,IAAI,MACT,GAAGlD,CAAI,IAAIG,EAAQ,UAAU,qEAC9B,EAEDqC,EAAWU,CACZ,CACC,KAAK,GAAWJ,EAAiB,GAAG,EAAED,EAAQ,SAAUI,CAAU,CACpE,KAAO,CAEN,GADK,MAAM,QAAQX,CAAK,IAAGA,EAAQ,CAACA,CAAK,GACrCA,EAAM,SAAWO,EAAQ,OAC5B,MAAM,IAAI,MAAM,iCAAiCP,EAAM,MAAM,cAAcO,EAAQ,MAAM,GAAG,EAE5F,KAAK,GAAWC,CAAc,EAAED,EAAQ,SAAU,GAAGP,CAAK,CAC5D,CACD,CAAC,EACD,KAAK,MAAM,IAAI,gBAAgB,GAAG,QAAQzB,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CAChF,CAEQ,cACPb,EACAmC,EACAgB,EACC,CACD,GAAM,CAAE,MAAAhC,EAAO,OAAAC,CAAO,EAAIe,EACpBiB,EAAejB,EAAY,SAAS,OAAS,EAE7CkB,EAAU,KAAK,GAAG,cAAc,EACtC,GAAI,CAACA,EACJ,MAAM,IAAI,MAAM,0BAA0B,EAG3C,GAAI,OAAOF,GAAc,SACxB,GAAI,CACHA,EAAY,KAAK,mBAAmBnD,CAAI,CACzC,OAAS2C,EAAO,CACf,WAAK,GAAG,cAAcU,CAAO,EACvBV,CACP,CAGD,IAAMW,EAAaF,EAAe,EAC5BG,EAAgBD,EAAa,KAAK,GAAG,iBAAmB,KAAK,GAAG,WAEtE,YAAK,GAAG,cAAc,KAAK,GAAG,SAAWH,CAAS,EAClD,KAAK,GAAG,YAAYI,EAAeF,CAAO,EAG1C,KAAK,GAAG,YAAY,KAAK,GAAG,oBAAqB,EAAI,EACrD,KAAK,GAAG,cAAcE,EAAe,KAAK,GAAG,eAAgB,KAAK,GAAG,aAAa,EAClF,KAAK,GAAG,cAAcA,EAAe,KAAK,GAAG,eAAgB,KAAK,GAAG,aAAa,EAClF,KAAK,GAAG,cAAcA,EAAe,KAAK,GAAG,mBAAoB,KAAK,GAAG,MAAM,EAC/E,KAAK,GAAG,cAAcA,EAAe,KAAK,GAAG,mBAAoB,KAAK,GAAG,MAAM,EAC3ED,GACH,KAAK,GAAG,aAAaC,EAAe,EAAG,KAAK,GAAG,MAAOpC,EAAOC,EAAQgC,CAAY,EAE3E,CAAE,QAAAC,EAAS,UAAAF,CAAU,CAC7B,CAEQ,mBAAmBnD,EAAuBH,EAAuBM,EAAgC,CACxG,GAAI,KAAK,SAAS,IAAIH,CAAI,EACzB,MAAM,IAAI,MAAM,YAAYD,EAAWC,CAAI,CAAC,2BAA2B,EAGxE,IAAMoD,EAAejD,GAAS,SAAW,EACnC,CAAE,MAAAgB,EAAO,OAAAC,CAAO,EAAIxB,EAAoBC,CAAM,EACpD,GAAI,CAACsB,GAAS,CAACC,EACd,MAAM,IAAI,MAAM,2CAA2C,EAE5D,IAAMe,EAA6D,CAAE,MAAAhB,EAAO,OAAAC,CAAO,EAC/EgC,EAAe,IAClBjB,EAAY,QAAU,CAAE,MAAOiB,EAAc,WAAY,CAAE,GAE5D,GAAM,CAAE,QAAAC,EAAS,UAAAF,CAAU,EAAI,KAAK,cAAcnD,EAAMmC,CAAW,EAC7DqB,EAA+B,CAAE,QAAAH,EAAS,UAAAF,EAAW,GAAGhB,CAAY,EACtEiB,EAAe,IAClB,KAAK,kBAAkB,GAAGrD,EAAWC,CAAI,CAAC,cAAe,MAAO,CAAC,EACjE,KAAK,0BAA0BwD,CAAmB,GAEnD,KAAK,SAAS,IAAIxD,EAAMwD,CAAmB,EAC3C,KAAK,cAAcxD,EAAMH,CAAM,EAG/B,IAAM4D,EAAW,KAAK,GAAG,mBAAmB,KAAK,QAAU1D,EAAWC,CAAI,CAAC,EACvEyD,GACH,KAAK,GAAG,UAAUA,EAAUN,CAAS,CAEvC,CAEA,kBAAkBnD,EAAcH,EAAuBM,EAAgC,CACtF,KAAK,mBAAmBH,EAAMH,EAAQM,CAAO,EAC7C,KAAK,MAAM,IAAI,mBAAmB,GAAG,QAAQU,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,CACnF,CAEA,eAAe+B,EAAwC,CACtD,KAAK,MAAM,IAAI,gBAAgB,GAAG,QAAQ/B,GAAQA,EAAK,KAAK,KAAM,GAAG,SAAS,CAAC,EAC/E,OAAO,QAAQ+B,CAAO,EAAE,QAAQ,CAAC,CAAC5C,EAAMH,CAAM,IAAM,CACnD,KAAK,cAAcG,EAAMH,CAAM,CAChC,CAAC,CACF,CAEQ,cAAcG,EAAuBH,EAAuB,CACnE,IAAM6D,EAAO,KAAK,SAAS,IAAI1D,CAAI,EACnC,GAAI,CAAC0D,EAAM,MAAM,IAAI,MAAM,YAAY3D,EAAWC,CAAI,CAAC,uBAAuB,EAG9E,GAAM,CAAE,MAAAmB,EAAO,OAAAC,CAAO,EAAIxB,EAAoBC,CAAM,EACpD,GAAI6D,EAAK,QAAUvC,GAASuC,EAAK,SAAWtC,EAAQ,CACnD,KAAK,GAAG,cAAcsC,EAAK,OAAO,EAClCA,EAAK,MAAQvC,EACbuC,EAAK,OAAStC,EACd,GAAM,CAAE,QAAAiC,CAAQ,EAAI,KAAK,cAAcrD,EAAM0D,EAAMA,EAAK,SAAS,EACjEA,EAAK,QAAUL,EACXK,EAAK,UACRA,EAAK,QAAQ,WAAa,EAC1B,KAAK,0BAA0BA,CAAI,EAErC,CAEA,GAAIA,EAAK,QAAS,CACjB,IAAMC,EAAuB3D,IAASZ,EAEtC,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWsE,EAAK,SAAS,EACvD,KAAK,GAAG,YAAY,KAAK,GAAG,iBAAkBA,EAAK,OAAO,EACtDC,EACH,KAAK,GAAG,kBACP,KAAK,GAAG,iBACR,EACA,EACA,EACAD,EAAK,QAAQ,WACb,EACA,EACAvC,EACAC,CACD,EAEA,KAAK,GAAG,cACP,KAAK,GAAG,iBACR,EACA,EACA,EACAsC,EAAK,QAAQ,WACbvC,EACAC,EACA,EACA,KAAK,GAAG,KACR,KAAK,GAAG,cACRvB,CACD,EAED,IAAM+D,EAAyB,GAAG7D,EAAWC,CAAI,CAAC,cAClD,KAAK,eAAe,CAAE,CAAC4D,CAAsB,EAAGF,EAAK,QAAQ,UAAW,CAAC,EACzEA,EAAK,QAAQ,YAAcA,EAAK,QAAQ,WAAa,GAAKA,EAAK,QAAQ,KACxE,MACC,KAAK,GAAG,cAAc,KAAK,GAAG,SAAWA,EAAK,SAAS,EACvD,KAAK,GAAG,YAAY,KAAK,GAAG,WAAYA,EAAK,OAAO,EACpD,KAAK,GAAG,WAAW,KAAK,GAAG,WAAY,EAAG,KAAK,GAAG,KAAM,KAAK,GAAG,KAAM,KAAK,GAAG,cAAe7D,CAAM,CAErG,CAEA,MAAO,CACN,IAAMC,EAAK,KAAK,GAChBA,EAAG,MAAMA,EAAG,gBAAgB,EAC5BA,EAAG,WAAWA,EAAG,UAAW,EAAG,CAAC,CACjC,CAEA,KAAK+D,EAAc,CACd,KAAK,SAAS,IAAI,QAAQ,GAC7B,KAAK,eAAe,CAAE,OAAQA,CAAK,CAAC,EAEjC,KAAK,SAAS,IAAI,SAAS,GAC9B,KAAK,eAAe,CAAE,QAAS,KAAK,KAAM,CAAC,EAG5C,KAAK,KAAK,EAEN,KAAK,SAAS,IAAIzE,CAAmB,GACxC,KAAK,cAAcA,EAAqB,KAAK,MAAM,EAEpD,KAAK,MAAM,IAAI,MAAM,GAAG,QAAQyB,GAAQA,EAAK,KAAK,KAAMgD,EAAM,KAAK,KAAK,CAAC,EACzE,EAAE,KAAK,KACR,CAEA,KAAKC,EAAkD,CACtD,KAAK,MAAM,EACX,IAAMC,EAAQF,GAAiB,CAC9BA,GAAQA,EAAO,KAAK,WAAa,IACjC,KAAK,KAAKA,CAAI,EACd,KAAK,iBAAmB,sBAAsBE,CAAI,EAC9CD,GAAUA,EAASD,EAAM,KAAK,KAAK,CACxC,EACA,KAAK,iBAAmB,sBAAsBE,CAAI,CACnD,CAEA,OAAQ,CACH,KAAK,mBACR,qBAAqB,KAAK,gBAAgB,EAC1C,KAAK,iBAAmB,KAE1B,CAEA,OAAQ,CACP,KAAK,MAAQ,EACb,KAAK,UAAY,YAAY,IAAI,EACjC,KAAK,SAAS,QAAQV,GAAW,CAC5BA,EAAQ,UACXA,EAAQ,QAAQ,WAAa,EAC7B,KAAK,0BAA0BA,CAAO,EAExC,CAAC,EACD,KAAK,MAAM,IAAI,OAAO,GAAG,QAAQxC,GAAQA,EAAK,KAAK,IAAI,CAAC,CACzD,CAEA,SAAU,CACL,KAAK,mBACR,qBAAqB,KAAK,gBAAgB,EAC1C,KAAK,iBAAmB,MAGzB,KAAK,mBAAmB,WAAW,EACnC,KAAK,eAAe,WAAW,EAC/B,KAAK,eAAe,QAAQ,CAACmB,EAAUH,IAAU,CAChD,KAAK,OAAO,oBAAoBA,EAAOG,CAAQ,CAChD,CAAC,EAEG,KAAK,SACR,KAAK,GAAG,cAAc,KAAK,OAAO,EAGnC,KAAK,SAAS,QAAQqB,GAAW,CAChC,KAAK,GAAG,cAAcA,EAAQ,OAAO,CACtC,CAAC,EACD,KAAK,gBAAgB,KAAO,CAAC,EAC7B,KAAK,gBAAgB,KAAO,EAExB,KAAK,SACR,KAAK,GAAG,aAAa,KAAK,MAAM,EAChC,KAAK,OAAS,MAGf,KAAK,MAAM,IAAI,SAAS,GAAG,QAAQxC,GAAQA,EAAK,KAAK,IAAI,CAAC,EAEtD,KAAK,kBACR,KAAK,OAAO,OAAO,CAErB,CACD,EAEOmD,EAAQ/D","names":["DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","gl","stringFrom","name","ShaderPad","fragmentShaderSrc","options","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","aPosition","hook","type","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","existing","textureInfo","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","unitIndex","historyDepth","texture","hasHistory","textureTarget","completeTextureInfo","uSampler","info","isFramebufferHistory","frameOffsetUniformName","time","callback","loop","index_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["const DEFAULT_VERTEX_SHADER_SRC = `#version 300 es\nin vec2 aPosition;\nout vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\nconst RESIZE_THROTTLE_INTERVAL = 1000 / 30;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n\tarrayLength?: number;\n}\n\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}\n\nexport type TextureSource = HTMLImageElement | HTMLVideoElement | HTMLCanvasElement;\n\nexport interface PluginContext {\n\tgl: WebGL2RenderingContext;\n\tuniforms: Map<string, Uniform>;\n\ttextures: Map<string | symbol, Texture>;\n\tget program(): WebGLProgram | null;\n\tcanvas: HTMLCanvasElement;\n\treserveTextureUnit: (name: string | symbol) => number;\n\treleaseTextureUnit: (name: string | symbol) => void;\n\tinjectGLSL: (code: string) => void;\n}\n\ntype Plugin = (shaderPad: ShaderPad, context: PluginContext) => void;\n\ntype LifecycleMethod =\n\t| 'init'\n\t| 'step'\n\t| 'destroy'\n\t| 'updateResolution'\n\t| 'reset'\n\t| 'initializeTexture'\n\t| 'updateTextures'\n\t| 'initializeUniform'\n\t| 'updateUniforms';\n\nexport interface Options {\n\tcanvas?: HTMLCanvasElement | null;\n\tplugins?: Plugin[];\n\thistory?: number;\n}\n\ntype TextureUnitPool = {\n\tfree: number[];\n\tnext: number;\n\tmax: number;\n};\n\nconst HISTORY_TEXTURE_KEY = Symbol('u_history');\n\nfunction combineShaderCode(shader: string, injections: string[]): string {\n\tif (!injections?.length) return shader;\n\tconst lines = shader.split('\\n');\n\tconst insertAt =\n\t\tlines.findLastIndex(line => {\n\t\t\tconst trimmed = line.trimStart();\n\t\t\treturn trimmed.startsWith('precision ') || trimmed.startsWith('#version ');\n\t\t}) + 1;\n\tlines.splice(insertAt, 0, ...injections);\n\treturn lines.join('\\n');\n}\n\nfunction getSourceDimensions(source: TextureSource) {\n\tif (source instanceof HTMLVideoElement) {\n\t\treturn { width: source.videoWidth, height: source.videoHeight };\n\t} else if (source instanceof HTMLCanvasElement) {\n\t\tconst gl = source.getContext('webgl2');\n\t\treturn gl\n\t\t\t? { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight }\n\t\t\t: { width: source.width, height: source.height };\n\t}\n\t// HTMLImageElement\n\treturn { width: source.naturalWidth ?? source.width, height: source.naturalHeight ?? source.height };\n}\n\nfunction stringFrom(name: string | symbol) {\n\treturn typeof name === 'symbol' ? name.description ?? '' : name;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string | symbol, Texture> = new Map();\n\tprivate textureUnitPool: TextureUnitPool;\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resolutionObserver: MutationObserver;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: ReturnType<typeof setTimeout> = null as unknown as ReturnType<typeof setTimeout>;\n\tprivate lastResizeTime = -Infinity;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate startTime = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tpublic canvas: HTMLCanvasElement;\n\tpublic onResize?: (width: number, height: number) => void;\n\tprivate hooks: Map<LifecycleMethod, Function[]> = new Map();\n\tprivate historyDepth: number;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tthis.canvas.style.position = 'fixed';\n\t\t\tthis.canvas.style.inset = '0';\n\t\t\tthis.canvas.style.height = '100dvh';\n\t\t\tthis.canvas.style.width = '100dvw';\n\t\t\tdocument.body.appendChild(this.canvas);\n\t\t}\n\n\t\tthis.gl = this.canvas.getContext('webgl2', { antialias: false }) as WebGL2RenderingContext;\n\t\tif (!this.gl) {\n\t\t\tthrow new Error('WebGL2 not supported. Please use a browser that supports WebGL2.');\n\t\t}\n\n\t\tthis.textureUnitPool = {\n\t\t\tfree: [],\n\t\t\tnext: 0,\n\t\t\tmax: this.gl.getParameter(this.gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS),\n\t\t};\n\t\tthis.historyDepth = options.history ?? 0;\n\t\tthis.animationFrameId = null;\n\t\tthis.resolutionObserver = new MutationObserver(() => this.updateResolution());\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\n\t\tconst glslInjections: string[] = [];\n\t\tif (options.plugins) {\n\t\t\tconst context: PluginContext = {\n\t\t\t\tgl: this.gl,\n\t\t\t\tuniforms: this.uniforms,\n\t\t\t\ttextures: this.textures,\n\t\t\t\tcanvas: this.canvas,\n\t\t\t\treserveTextureUnit: this.reserveTextureUnit.bind(this),\n\t\t\t\treleaseTextureUnit: this.releaseTextureUnit.bind(this),\n\t\t\t\tinjectGLSL: (code: string) => {\n\t\t\t\t\tglslInjections.push(code);\n\t\t\t\t},\n\t\t\t} as PluginContext;\n\t\t\t// Define program as a getter so it always returns the current program.\n\t\t\tObject.defineProperty(context, 'program', {\n\t\t\t\tget: () => this.program,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t\toptions.plugins.forEach(plugin => plugin(this, context));\n\t\t}\n\n\t\tthis.fragmentShaderSrc = combineShaderCode(fragmentShaderSrc, glslInjections);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tregisterHook(name: LifecycleMethod, fn: Function) {\n\t\tif (!this.hooks.has(name)) {\n\t\t\tthis.hooks.set(name, []);\n\t\t}\n\t\tthis.hooks.get(name)!.push(fn);\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = DEFAULT_VERTEX_SHADER_SRC;\n\n\t\tthis.program = this.gl.createProgram();\n\t\tif (!this.program) {\n\t\t\tthrow new Error('Failed to create WebGL program');\n\t\t}\n\t\tconst vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexShaderSrc);\n\t\tconst fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, this.fragmentShaderSrc);\n\n\t\tthis.gl.attachShader(this.program, vertexShader);\n\t\tthis.gl.attachShader(this.program, fragmentShader);\n\t\tthis.gl.linkProgram(this.program);\n\t\tthis.gl.deleteShader(vertexShader);\n\t\tthis.gl.deleteShader(fragmentShader);\n\n\t\tif (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n\t\t\tconsole.error('Program link error:', this.gl.getProgramInfoLog(this.program));\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t\tthrow new Error('Failed to link WebGL program');\n\t\t}\n\n\t\tconst aPosition = this.gl.getAttribLocation(this.program, 'aPosition');\n\t\tthis.setupBuffer(aPosition);\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.resolutionObserver.observe(this.canvas, { attributes: true, attributeFilter: ['width', 'height'] });\n\t\tthis.resizeObserver.observe(this.canvas);\n\n\t\tif (!this.isInternalCanvas) {\n\t\t\tthis.updateResolution();\n\t\t}\n\t\tthis.initializeUniform('u_cursor', 'float', this.cursorPosition);\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]);\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\t\tif (this.historyDepth > 0) {\n\t\t\tthis._initializeTexture(HISTORY_TEXTURE_KEY, this.canvas, { history: this.historyDepth });\n\t\t}\n\n\t\tthis.hooks.get('init')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate setupBuffer(aPosition: number) {\n\t\tconst quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);\n\n\t\tthis.buffer = this.gl.createBuffer();\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\t\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\tprivate throttledHandleResize() {\n\t\tclearTimeout(this.resizeTimeout);\n\t\tconst now = performance.now();\n\t\tconst timeUntilNextResize = this.lastResizeTime + RESIZE_THROTTLE_INTERVAL - now;\n\t\tif (timeUntilNextResize <= 0) {\n\t\t\tthis.lastResizeTime = now;\n\t\t\tthis.handleResize();\n\t\t} else {\n\t\t\tthis.resizeTimeout = setTimeout(() => this.throttledHandleResize(), timeUntilNextResize);\n\t\t}\n\t}\n\n\tprivate handleResize() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\t\tif (this.isInternalCanvas && (this.canvas.width !== width || this.canvas.height !== height)) {\n\t\t\tthis.canvas.width = width;\n\t\t\tthis.canvas.height = height;\n\t\t}\n\t\tthis.onResize?.(width, height);\n\t}\n\n\tprivate addEventListeners() {\n\t\tconst updateCursor = (x: number, y: number) => {\n\t\t\tif (!this.uniforms.has('u_cursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tthis.cursorPosition[0] = (x - rect.left) / rect.width;\n\t\t\tthis.cursorPosition[1] = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ u_cursor: this.cursorPosition });\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\n\t\t\tif (!this.uniforms.has('u_click')) return;\n\t\t\tthis.isMouseDown = isMouseDown;\n\t\t\tif (isMouseDown) {\n\t\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\t\tconst xVal = x as number;\n\t\t\t\tconst yVal = y as number;\n\t\t\t\tthis.clickPosition[0] = (xVal - rect.left) / rect.width;\n\t\t\t\tthis.clickPosition[1] = 1 - (yVal - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\t}\n\t\t\tthis.updateUniforms({ u_click: [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0] });\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchmove', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchstart', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tthis.isTouchDevice = true;\n\t\t\tif (touchEvent.touches.length > 0) {\n\t\t\t\tupdateCursor(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('touchend', event => {\n\t\t\tconst touchEvent = event as TouchEvent;\n\t\t\tif (touchEvent.touches.length === 0) {\n\t\t\t\tupdateClick(false);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.addEventListener(event, listener);\n\t\t});\n\t}\n\n\tprivate updateResolution() {\n\t\tconst resolution: [number, number] = [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];\n\t\tthis.gl.viewport(0, 0, ...resolution);\n\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\tthis.updateUniforms({ u_resolution: resolution });\n\t\t} else {\n\t\t\tthis.initializeUniform('u_resolution', 'float', resolution);\n\t\t}\n\t\tthis.hooks.get('updateResolution')?.forEach(hook => hook.call(this));\n\t}\n\n\tprivate reserveTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) return existing.unitIndex;\n\t\tif (this.textureUnitPool.free.length > 0) return this.textureUnitPool.free.pop()!;\n\t\tif (this.textureUnitPool.next >= this.textureUnitPool.max) {\n\t\t\tthrow new Error('Exceeded the available texture units for this device.');\n\t\t}\n\t\treturn this.textureUnitPool.next++;\n\t}\n\n\tprivate releaseTextureUnit(name: string | symbol) {\n\t\tconst existing = this.textures.get(name);\n\t\tif (existing) {\n\t\t\tthis.textureUnitPool.free.push(existing.unitIndex);\n\t\t}\n\t}\n\n\tprivate clearHistoryTextureLayers(textureInfo: Texture): void {\n\t\tif (!textureInfo.history) return;\n\n\t\tconst transparent = new Uint8Array(textureInfo.width * textureInfo.height * 4);\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureInfo.unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, textureInfo.texture);\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n\t\tfor (let layer = 0; layer < textureInfo.history.depth; ++layer) {\n\t\t\tthis.gl.texSubImage3D(\n\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tlayer,\n\t\t\t\ttextureInfo.width,\n\t\t\t\ttextureInfo.height,\n\t\t\t\t1,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\ttransparent\n\t\t\t);\n\t\t}\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t}\n\n\tinitializeUniform(\n\t\tname: string,\n\t\ttype: 'float' | 'int',\n\t\tvalue: number | number[] | (number | number[])[],\n\t\toptions?: { arrayLength?: number }\n\t) {\n\t\tconst arrayLength = options?.arrayLength;\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`${name} is already initialized.`);\n\t\t}\n\t\tif (type !== 'float' && type !== 'int') {\n\t\t\tthrow new Error(`Invalid uniform type: ${type}. Expected 'float' or 'int'.`);\n\t\t}\n\t\tif (arrayLength && !(Array.isArray(value) && value.length === arrayLength)) {\n\t\t\tthrow new Error(`${name} array length mismatch: must initialize with ${arrayLength} elements.`);\n\t\t}\n\n\t\tlet location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location && arrayLength) {\n\t\t\tlocation = this.gl.getUniformLocation(this.program!, `${name}[0]`);\n\t\t}\n\t\tif (!location) {\n\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst probeValue = arrayLength ? (value as number[] | number[][])[0] : value;\n\t\tconst length = Array.isArray(probeValue) ? (probeValue.length as 1 | 2 | 3 | 4) : 1;\n\t\tthis.uniforms.set(name, { type, length, location, arrayLength });\n\n\t\ttry {\n\t\t\tthis.updateUniforms({ [name]: value });\n\t\t} catch (error) {\n\t\t\tthis.uniforms.delete(name);\n\t\t\tthrow error;\n\t\t}\n\t\tthis.hooks.get('initializeUniform')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateUniforms(\n\t\tupdates: Record<string, number | number[] | (number | number[])[]>,\n\t\toptions?: { startIndex?: number }\n\t) {\n\t\tObject.entries(updates).forEach(([name, value]) => {\n\t\t\tconst uniform = this.uniforms.get(name);\n\t\t\tif (!uniform) {\n\t\t\t\tconsole.debug(`${name} not found in fragment shader. Skipping update.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet glFunctionName = `uniform${uniform.length}${uniform.type.charAt(0)}`; // e.g. uniform1f, uniform3i…\n\t\t\tif (uniform.arrayLength) {\n\t\t\t\tif (!Array.isArray(value)) {\n\t\t\t\t\tthrow new Error(`${name} is an array, but the value passed to updateUniforms is not an array.`);\n\t\t\t\t}\n\t\t\t\tconst nValues = value.length;\n\t\t\t\tif (!nValues) return;\n\t\t\t\tif (nValues > uniform.arrayLength) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${name} received ${nValues} values, but maximum length is ${uniform.arrayLength}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (value.some(item => (Array.isArray(item) ? item.length : 1) !== uniform.length)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Tried to update ${name} with some elements that are not length ${uniform.length}.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst typedArray = new (uniform.type === 'float' ? Float32Array : Int32Array)(value.flat());\n\t\t\t\tlet location = uniform.location;\n\t\t\t\tif (options?.startIndex) {\n\t\t\t\t\tconst newLocation = this.gl.getUniformLocation(this.program!, `${name}[${options.startIndex}]`);\n\t\t\t\t\tif (!newLocation) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`${name}[${options.startIndex}] not found in fragment shader. Did you pass an invalid startIndex?`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tlocation = newLocation;\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName + 'v'](uniform.location, typedArray);\n\t\t\t} else {\n\t\t\t\tif (!Array.isArray(value)) value = [value];\n\t\t\t\tif (value.length !== uniform.length) {\n\t\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t\t}\n\t\t\t\t(this.gl as any)[glFunctionName](uniform.location, ...value);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('updateUniforms')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tprivate createTexture(\n\t\tname: string | symbol,\n\t\ttextureInfo: Pick<Texture, 'width' | 'height' | 'history'>,\n\t\tunitIndex?: 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\tif (typeof unitIndex !== 'number') {\n\t\t\ttry {\n\t\t\t\tunitIndex = this.reserveTextureUnit(name);\n\t\t\t} catch (error) {\n\t\t\t\tthis.gl.deleteTexture(texture);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst hasHistory = historyDepth > 0;\n\t\tconst textureTarget = hasHistory ? this.gl.TEXTURE_2D_ARRAY : this.gl.TEXTURE_2D;\n\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(textureTarget, texture);\n\t\t// Flip the texture vertically during upload to match WebGL’s coordinate system.\n\t\t// WebGL uses bottom-left origin, while images/videos use top-left origin.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(textureTarget, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\t\tif (hasHistory) {\n\t\t\tthis.gl.texStorage3D(textureTarget, 1, this.gl.RGBA8, width, height, historyDepth);\n\t\t}\n\t\treturn { texture, unitIndex };\n\t}\n\n\tprivate _initializeTexture(name: string | symbol, source: TextureSource, options?: { history?: number }) {\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 historyDepth = options?.history ?? 0;\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (!width || !height) {\n\t\t\tthrow new Error(`Texture source must have valid dimensions`);\n\t\t}\n\t\tconst textureInfo: Pick<Texture, 'width' | 'height' | 'history'> = { width, height };\n\t\tif (historyDepth > 0) {\n\t\t\ttextureInfo.history = { depth: historyDepth, writeIndex: 0 };\n\t\t}\n\t\tconst { texture, unitIndex } = this.createTexture(name, textureInfo);\n\t\tconst completeTextureInfo: Texture = { texture, unitIndex, ...textureInfo };\n\t\tif (historyDepth > 0) {\n\t\t\tthis.initializeUniform(`${stringFrom(name)}FrameOffset`, 'int', 0);\n\t\t\tthis.clearHistoryTextureLayers(completeTextureInfo);\n\t\t}\n\t\tthis.textures.set(name, completeTextureInfo);\n\t\tthis.updateTexture(name, source);\n\n\t\t// Set a uniform to access the texture in the fragment shader.\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, stringFrom(name));\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tinitializeTexture(name: string, source: TextureSource, options?: { history?: number }) {\n\t\tthis._initializeTexture(name, source, options);\n\t\tthis.hooks.get('initializeTexture')?.forEach(hook => hook.call(this, ...arguments));\n\t}\n\n\tupdateTextures(updates: Record<string, TextureSource>) {\n\t\tthis.hooks.get('updateTextures')?.forEach(hook => hook.call(this, ...arguments));\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tthis.updateTexture(name, source);\n\t\t});\n\t}\n\n\tprivate updateTexture(name: string | symbol, source: TextureSource) {\n\t\tconst info = this.textures.get(name);\n\t\tif (!info) throw new Error(`Texture '${stringFrom(name)}' is not initialized.`);\n\n\t\t// If dimensions changed, recreate the texture with new dimensions.\n\t\tconst { width, height } = getSourceDimensions(source);\n\t\tif (info.width !== width || info.height !== height) {\n\t\t\tthis.gl.deleteTexture(info.texture);\n\t\t\tinfo.width = width;\n\t\t\tinfo.height = height;\n\t\t\tconst { texture } = this.createTexture(name, info, info.unitIndex);\n\t\t\tinfo.texture = texture;\n\t\t\tif (info.history) {\n\t\t\t\tinfo.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(info);\n\t\t\t}\n\t\t}\n\n\t\tif (info.history) {\n\t\t\tconst isFramebufferHistory = name === HISTORY_TEXTURE_KEY;\n\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D_ARRAY, info.texture);\n\t\t\tif (isFramebufferHistory) {\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n\t\t\t\tthis.gl.copyTexSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\twidth,\n\t\t\t\t\theight\n\t\t\t\t);\n\t\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\t\t} else {\n\t\t\t\tthis.gl.texSubImage3D(\n\t\t\t\t\tthis.gl.TEXTURE_2D_ARRAY,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t\tinfo.history.writeIndex,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\t1,\n\t\t\t\t\tthis.gl.RGBA,\n\t\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\t\tsource\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst frameOffsetUniformName = `${stringFrom(name)}FrameOffset`;\n\t\t\tthis.updateUniforms({ [frameOffsetUniformName]: info.history.writeIndex });\n\t\t\tinfo.history.writeIndex = (info.history.writeIndex + 1) % info.history.depth;\n\t\t} else {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + info.unitIndex);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, info.texture);\n\t\t\tthis.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, source);\n\t\t}\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t}\n\n\tstep(time: number) {\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\tthis.draw();\n\n\t\tif (this.textures.get(HISTORY_TEXTURE_KEY)) {\n\t\t\tthis.updateTexture(HISTORY_TEXTURE_KEY, this.canvas);\n\t\t}\n\t\tthis.hooks.get('step')?.forEach(hook => hook.call(this, time, this.frame));\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tthis.pause(); // Prevent double play.\n\t\tconst loop = (time: number) => {\n\t\t\ttime = (time - this.startTime) / 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t};\n\t\tthis.animationFrameId = requestAnimationFrame(loop);\n\t}\n\n\tpause() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\t}\n\n\treset() {\n\t\tthis.frame = 0;\n\t\tthis.startTime = performance.now();\n\t\tthis.textures.forEach(texture => {\n\t\t\tif (texture.history) {\n\t\t\t\ttexture.history.writeIndex = 0;\n\t\t\t\tthis.clearHistoryTextureLayers(texture);\n\t\t\t}\n\t\t});\n\t\tthis.hooks.get('reset')?.forEach(hook => hook.call(this));\n\t}\n\n\tdestroy() {\n\t\tif (this.animationFrameId) {\n\t\t\tcancelAnimationFrame(this.animationFrameId);\n\t\t\tthis.animationFrameId = null;\n\t\t}\n\n\t\tthis.resolutionObserver.disconnect();\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.eventListeners.forEach((listener, event) => {\n\t\t\tthis.canvas.removeEventListener(event, listener);\n\t\t});\n\n\t\tif (this.program) {\n\t\t\tthis.gl.deleteProgram(this.program);\n\t\t}\n\n\t\tthis.textures.forEach(texture => {\n\t\t\tthis.gl.deleteTexture(texture.texture);\n\t\t});\n\t\tthis.textureUnitPool.free = [];\n\t\tthis.textureUnitPool.next = 0;\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tthis.hooks.get('destroy')?.forEach(hook => hook.call(this));\n\n\t\tif (this.isInternalCanvas) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["DEFAULT_VERTEX_SHADER_SRC","RESIZE_THROTTLE_INTERVAL","HISTORY_TEXTURE_KEY","combineShaderCode","shader","injections","lines","insertAt","line","trimmed","getSourceDimensions","source","gl","stringFrom","name","ShaderPad","fragmentShaderSrc","options","glslInjections","context","code","plugin","fn","vertexShaderSrc","vertexShader","fragmentShader","aPosition","hook","type","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","touchEvent","listener","resolution","existing","textureInfo","transparent","layer","value","arrayLength","location","probeValue","length","error","updates","uniform","glFunctionName","nValues","item","typedArray","newLocation","unitIndex","historyDepth","texture","hasHistory","textureTarget","completeTextureInfo","uSampler","info","isFramebufferHistory","frameOffsetUniformName","time","callback","loop","index_default"]}
|