shaderpad 1.0.0-alpha.6 → 1.0.0-alpha.7

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 CHANGED
@@ -14,11 +14,11 @@ npm install shaderpad
14
14
  import ShaderPad from 'shaderpad';
15
15
 
16
16
  // Your custom GLSL fragment shader code.
17
- const fragmentShaderSrc = `
17
+ const fragmentShaderSrc = `#version 300 es
18
18
  precision highp float;
19
19
 
20
20
  // Built-in variables.
21
- varying vec2 v_uv;
21
+ in vec2 v_uv;
22
22
  uniform float u_time;
23
23
  uniform vec2 u_resolution;
24
24
  uniform vec4 u_cursor; // [cursorX, cursorY, scrollX, scrollY]
@@ -26,6 +26,8 @@ uniform vec4 u_cursor; // [cursorX, cursorY, scrollX, scrollY]
26
26
  // Custom variables.
27
27
  uniform vec3 u_cursorColor;
28
28
 
29
+ out vec4 outColor;
30
+
29
31
  void main() {
30
32
  vec2 uv = v_uv * u_resolution;
31
33
  vec2 dotGrid = mod(uv, 50.) - 25.;
@@ -38,12 +40,12 @@ void main() {
38
40
  vec3 color = mix(vec3(0., 0., 1.), vec3(1.), dot);
39
41
  color = mix(color, u_cursorColor, cursor);
40
42
 
41
- gl_FragColor = vec4(color, 1.);
43
+ outColor = vec4(color, 1.);
42
44
  }
43
45
  `;
44
46
 
45
47
  // Initialize the shader.
46
- const shader = new ShaderPad(fragmentShaderSrc /* , canvasElement */);
48
+ const shader = new ShaderPad(fragmentShaderSrc /* , options */);
47
49
 
48
50
  // Add your own custom uniforms.
49
51
  const getColor = (time: number) =>
@@ -61,15 +63,41 @@ shader.play(time => {
61
63
 
62
64
  See the [`examples/` directory](./examples/) for more.
63
65
 
66
+ ## Options
67
+
68
+ ShaderPad’s constructor accepts an optional `options` object.
69
+
70
+ ### canvas
71
+
72
+ The `canvas` option allows you to pass in an existing canvas element. If not provided, ShaderPad will create a new canvas element and append it to the document body.
73
+
74
+ ```typescript
75
+ const canvas = document.createElement('canvas');
76
+ const shader = new ShaderPad(fragmentShaderSrc, { canvas });
77
+ ```
78
+
79
+ ### history
80
+
81
+ ShaderPad supports frame history buffers for effects like motion blur, feedback, and trails:
82
+
83
+ ```typescript
84
+ // 2-frame history (eg. for cellular automata).
85
+ const shader = new ShaderPad(fragmentShaderSrc, { history: 2 });
86
+
87
+ // 10-frame history (eg. for motion blur).
88
+ const shader = new ShaderPad(fragmentShaderSrc, { history: 10 });
89
+ ```
90
+
64
91
  ## Included uniforms
65
92
 
66
- | Uniform | Type | Description |
67
- | -------------- | -------- | -------------------------------------------------- |
68
- | `u_time` | float | The current time in seconds. |
69
- | `u_frame` | int | The current frame number. |
70
- | `u_resolution` | float[2] | The canvas element's dimensions. |
71
- | `u_cursor` | float[4] | Cursor position (x, y) and scroll position (z, w). |
72
- | `u_click` | float[3] | Click position (x, y) and left click state (z). |
93
+ | Uniform | Type | Description |
94
+ | -------------- | -------------- | -------------------------------------------------- |
95
+ | `u_time` | float | The current time in seconds. |
96
+ | `u_frame` | int | The current frame number. |
97
+ | `u_resolution` | float[2] | The canvas element's dimensions. |
98
+ | `u_cursor` | float[4] | Cursor position (x, y) and scroll position (z, w). |
99
+ | `u_click` | float[3] | Click position (x, y) and left click state (z). |
100
+ | `u_history` | sampler2DArray | Buffer texture of prior frames. |
73
101
 
74
102
  ## Included varyings
75
103
 
package/dist/index.d.mts CHANGED
@@ -1,3 +1,7 @@
1
+ interface Options {
2
+ history?: number;
3
+ canvas?: HTMLCanvasElement | null;
4
+ }
1
5
  declare class ShaderPad {
2
6
  private isInternalCanvas;
3
7
  private isTouchDevice;
@@ -11,6 +15,8 @@ declare class ShaderPad {
11
15
  private program;
12
16
  private animationFrameId;
13
17
  private resizeObserver;
18
+ private resizeTimeout;
19
+ private lastResizeTime;
14
20
  private eventListeners;
15
21
  private frame;
16
22
  private cursorPosition;
@@ -18,11 +24,15 @@ declare class ShaderPad {
18
24
  private scrollY;
19
25
  private clickPosition;
20
26
  private isMouseDown;
21
- constructor(fragmentShaderSrc: string, canvas?: HTMLCanvasElement | null);
27
+ private historyLength;
28
+ private historyTexture;
29
+ constructor(fragmentShaderSrc: string, options?: Options);
22
30
  private init;
31
+ private initializeHistoryBuffer;
23
32
  private createShader;
24
33
  private setupBuffer;
25
- private resizeCanvas;
34
+ private throttledHandleResize;
35
+ private handleResize;
26
36
  private addEventListeners;
27
37
  initializeUniform(name: string, type: 'float' | 'int', value: number | number[]): void;
28
38
  updateUniforms(updates: Record<string, number | number[]>): void;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ interface Options {
2
+ history?: number;
3
+ canvas?: HTMLCanvasElement | null;
4
+ }
1
5
  declare class ShaderPad {
2
6
  private isInternalCanvas;
3
7
  private isTouchDevice;
@@ -11,6 +15,8 @@ declare class ShaderPad {
11
15
  private program;
12
16
  private animationFrameId;
13
17
  private resizeObserver;
18
+ private resizeTimeout;
19
+ private lastResizeTime;
14
20
  private eventListeners;
15
21
  private frame;
16
22
  private cursorPosition;
@@ -18,11 +24,15 @@ declare class ShaderPad {
18
24
  private scrollY;
19
25
  private clickPosition;
20
26
  private isMouseDown;
21
- constructor(fragmentShaderSrc: string, canvas?: HTMLCanvasElement | null);
27
+ private historyLength;
28
+ private historyTexture;
29
+ constructor(fragmentShaderSrc: string, options?: Options);
22
30
  private init;
31
+ private initializeHistoryBuffer;
23
32
  private createShader;
24
33
  private setupBuffer;
25
- private resizeCanvas;
34
+ private throttledHandleResize;
35
+ private handleResize;
26
36
  private addEventListeners;
27
37
  initializeUniform(name: string, type: 'float' | 'int', value: number | number[]): void;
28
38
  updateUniforms(updates: Record<string, number | number[]>): void;
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- "use strict";var h=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var d=(n,e)=>{for(var s in e)h(n,s,{get:e[s],enumerable:!0})},f=(n,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of u(e))!m.call(n,i)&&i!==s&&h(n,i,{get:()=>e[i],enumerable:!(t=g(e,i))||t.enumerable});return n};var v=n=>f(h({},"__esModule",{value:!0}),n);var T={};d(T,{default:()=>p});module.exports=v(T);var E=`
2
- attribute vec2 aPosition;
3
- varying vec2 v_uv;
1
+ "use strict";var a=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var d=(n,t)=>{for(var e in t)a(n,e,{get:t[e],enumerable:!0})},f=(n,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of g(t))!m.call(n,s)&&s!==e&&a(n,s,{get:()=>t[s],enumerable:!(i=u(t,s))||i.enumerable});return n};var E=n=>f(a({},"__esModule",{value:!0}),n);var R={};d(R,{default:()=>p});module.exports=E(R);var T=`#version 300 es
2
+ in vec2 aPosition;
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
- `,o=class{constructor(e,s=null){this.isInternalCanvas=!1;this.isTouchDevice=!1;this.uniforms=new Map;this.textures=new Map;this.buffer=null;this.program=null;this.eventListeners=new Map;this.frame=0;this.cursorPosition=[.5,.5];this.scrollX=0;this.scrollY=0;this.clickPosition=[.5,.5];this.isMouseDown=!1;this.canvas=s||document.createElement("canvas"),s||(this.isInternalCanvas=!0,document.body.appendChild(this.canvas),this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw"),this.gl=this.canvas.getContext("webgl"),this.downloadLink=document.createElement("a"),this.fragmentShaderSrc=e,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.resizeCanvas()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let e=E;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let s=this.createShader(this.gl.VERTEX_SHADER,e),t=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,s),this.gl.attachShader(this.program,t),this.gl.linkProgram(this.program),this.gl.deleteShader(s),this.gl.deleteShader(t),!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 i=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(i),this.resizeCanvas(),this.gl.useProgram(this.program),this.initializeUniform("u_resolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("u_cursor","float",[...this.cursorPosition,this.scrollX,this.scrollY]),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0)}createShader(e,s){let t=this.gl.createShader(e);if(this.gl.shaderSource(t,s),this.gl.compileShader(t),!this.gl.getShaderParameter(t,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",s),console.error(this.gl.getShaderInfoLog(t)),this.gl.deleteShader(t),new Error("Shader compilation failed");return t}setupBuffer(e){let s=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,s,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.gl.enableVertexAttribArray(e),this.gl.vertexAttribPointer(e,2,this.gl.FLOAT,!1,0,0)}resizeCanvas(){let e=window.devicePixelRatio||1,s=this.canvas.clientWidth*e,t=this.canvas.clientHeight*e,i=getComputedStyle(this.canvas),r=i.width!==`${this.canvas.width}px`&&i.width!=="auto",a=i.height!==`${this.canvas.height}px`&&i.height!=="auto";(!r||!a)&&(this.canvas.style.width=`${this.canvas.clientWidth}px`,this.canvas.style.height=`${this.canvas.clientHeight}px`),(this.canvas.width!==s||this.canvas.height!==t)&&(this.canvas.width=s,this.canvas.height=t,this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.uniforms.has("u_resolution")&&this.updateUniforms({u_resolution:[this.canvas.width,this.canvas.height]}))}addEventListeners(){let e=(t,i)=>{if(!this.uniforms.has("u_cursor"))return;let r=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(t-r.left)/r.width,this.cursorPosition[1]=1-(i-r.top)/r.height,this.updateUniforms({u_cursor:[this.cursorPosition[0],this.cursorPosition[1],this.scrollX,this.scrollY]})},s=(t,i,r)=>{if(this.isMouseDown=t,t){let a=this.canvas.getBoundingClientRect(),l=i,c=r;this.clickPosition[0]=(l-a.left)/a.width,this.clickPosition[1]=1-(c-a.top)/a.height}this.updateUniforms({u_click:[this.clickPosition[0],this.clickPosition[1],this.isMouseDown?1:0]})};this.eventListeners.set("mousemove",t=>{let i=t;this.isTouchDevice||e(i.clientX,i.clientY)}),this.eventListeners.set("mousedown",t=>{let i=t;this.isTouchDevice||i.button===0&&(this.isMouseDown=!0,s(!0,i.clientX,i.clientY))}),this.eventListeners.set("mouseup",t=>{let i=t;this.isTouchDevice||i.button===0&&s(!1)}),this.eventListeners.set("wheel",t=>{let i=t;this.scrollX+=i.deltaX*.01,this.scrollY+=i.deltaY*.01,e(i.clientX,i.clientY)}),this.eventListeners.set("touchmove",t=>{let i=t;i.touches.length>0&&e(i.touches[0].clientX,i.touches[0].clientY)}),this.eventListeners.set("touchstart",t=>{let i=t;this.isTouchDevice=!0,i.touches.length>0&&(s(!0,i.touches[0].clientX,i.touches[0].clientY),e(i.touches[0].clientX,i.touches[0].clientY))}),this.eventListeners.set("touchend",t=>{t.touches.length===0&&s(!1)}),this.eventListeners.forEach((t,i)=>{this.canvas.addEventListener(i,t)})}initializeUniform(e,s,t){if(this.uniforms.has(e))throw new Error(`Uniform '${e}' is already initialized.`);if(s!=="float"&&s!=="int")throw new Error(`Invalid uniform type: ${s}. Expected 'float' or 'int'.`);let i=this.gl.getUniformLocation(this.program,e);if(!i){console.debug(`Uniform ${e} not found in fragment shader. Skipping initialization.`);return}if(Array.isArray(t)||(t=[t]),t.length<1||t.length>4)throw new Error(`Invalid uniform value length: ${t.length}. Expected a length between 1 and 4.`);let r=t.length;this.uniforms.set(e,{type:s,length:r,location:i}),this.updateUniforms({[e]:t})}updateUniforms(e){Object.entries(e).forEach(([s,t])=>{if(!this.uniforms.has(s))throw new Error(`Uniform '${s}' is not initialized.`);let i=this.uniforms.get(s);if(Array.isArray(t)||(t=[t]),t.length!==i.length)throw new Error(`Invalid uniform value length: ${t.length}. Expected ${i.length}.`);this.gl[`uniform${i.length}${i.type.charAt(0)}`](i.location,...t)})}step(e){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.uniforms.has("u_time")&&this.updateUniforms({u_time:e}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),++this.frame,this.gl.drawArrays(this.gl.TRIANGLES,0,6)}play(e){let s=t=>{t/=1e3,this.step(t),e&&e(t,this.frame),this.animationFrameId=requestAnimationFrame(s)};this.animationFrameId=requestAnimationFrame(s)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}save(e){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.drawArrays(this.gl.TRIANGLES,0,6);let s=this.canvas.toDataURL();e&&!`${e}`.toLowerCase().endsWith(".png")&&(e=`${e}.png`),this.downloadLink.download=e||"export.png",this.downloadLink.href=s,this.downloadLink.click()}initializeTexture(e,s){if(this.textures.has(e))throw new Error(`Texture '${e}' is already initialized.`);let t=this.gl.createTexture();if(!t)throw new Error("Failed to create texture");let i=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+i),this.gl.bindTexture(this.gl.TEXTURE_2D,t),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.textures.set(e,{texture:t,unitIndex:i}),this.updateTextures({[e]:s});let r=this.gl.getUniformLocation(this.program,e);r&&this.gl.uniform1i(r,i)}updateTextures(e){Object.entries(e).forEach(([s,t])=>{let i=this.textures.get(s);if(!i)throw new Error(`Texture '${s}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,i.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,t)})}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resizeObserver.unobserve(this.canvas),this.eventListeners.forEach((e,s)=>{this.canvas.removeEventListener(s,e)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(e=>{this.gl.deleteTexture(e.texture)}),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},p=o;
8
+ `,v=33.333333333333336,o=class{constructor(t,e={}){this.isInternalCanvas=!1;this.isTouchDevice=!1;this.uniforms=new Map;this.textures=new Map;this.buffer=null;this.program=null;this.resizeTimeout=null;this.lastResizeTime=0;this.eventListeners=new Map;this.frame=0;this.cursorPosition=[.5,.5];this.scrollX=0;this.scrollY=0;this.clickPosition=[.5,.5];this.isMouseDown=!1;this.historyTexture=null;if(this.canvas=e.canvas||document.createElement("canvas"),this.historyLength=e.history||0,e.canvas||(this.isInternalCanvas=!0,document.body.appendChild(this.canvas),this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw"),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.downloadLink=document.createElement("a"),this.fragmentShaderSrc=t,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let t=T;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let e=this.createShader(this.gl.VERTEX_SHADER,t),i=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,e),this.gl.attachShader(this.program,i),this.gl.linkProgram(this.program),this.gl.deleteShader(e),this.gl.deleteShader(i),!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 s=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(s),this.handleResize(),this.gl.useProgram(this.program),this.initializeUniform("u_resolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("u_cursor","float",[...this.cursorPosition,this.scrollX,this.scrollY]),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyLength>0&&this.initializeHistoryBuffer()}initializeHistoryBuffer(){let{gl:t}=this;if(this.historyTexture=t.createTexture(),!this.historyTexture)throw new Error("Failed to create history texture");t.bindTexture(t.TEXTURE_2D_ARRAY,this.historyTexture),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texStorage3D(t.TEXTURE_2D_ARRAY,1,t.RGBA8,this.canvas.width,this.canvas.height,this.historyLength),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D_ARRAY,this.historyTexture),this.uniforms.has("u_history")||this.initializeUniform("u_history","int",0)}createShader(t,e){let i=this.gl.createShader(t);if(this.gl.shaderSource(i,e),this.gl.compileShader(i),!this.gl.getShaderParameter(i,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",e),console.error(this.gl.getShaderInfoLog(i)),this.gl.deleteShader(i),new Error("Shader compilation failed");return i}setupBuffer(t){let e=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,e,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,0,0)}throttledHandleResize(){clearTimeout(this.resizeTimeout);let t=performance.now(),e=this.lastResizeTime+v-t;e<=0?(this.lastResizeTime=t,this.handleResize()):this.resizeTimeout=setTimeout(()=>this.throttledHandleResize(),e)}handleResize(){let t=window.devicePixelRatio||1,e=this.canvas.clientWidth*t,i=this.canvas.clientHeight*t,s=getComputedStyle(this.canvas),r=s.width!==`${this.canvas.width}px`&&s.width!=="auto",h=s.height!==`${this.canvas.height}px`&&s.height!=="auto";(!r||!h)&&(this.canvas.style.width=`${this.canvas.clientWidth}px`,this.canvas.style.height=`${this.canvas.clientHeight}px`),(this.canvas.width!==e||this.canvas.height!==i)&&(this.canvas.width=e,this.canvas.height=i,this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.uniforms.has("u_resolution")&&this.updateUniforms({u_resolution:[this.canvas.width,this.canvas.height]}),this.historyLength>0&&this.historyTexture&&(this.gl.deleteTexture(this.historyTexture),this.initializeHistoryBuffer()))}addEventListeners(){let t=(i,s)=>{if(!this.uniforms.has("u_cursor"))return;let r=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(i-r.left)/r.width,this.cursorPosition[1]=1-(s-r.top)/r.height,this.updateUniforms({u_cursor:[this.cursorPosition[0],this.cursorPosition[1],this.scrollX,this.scrollY]})},e=(i,s,r)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=i,i){let h=this.canvas.getBoundingClientRect(),l=s,c=r;this.clickPosition[0]=(l-h.left)/h.width,this.clickPosition[1]=1-(c-h.top)/h.height}this.updateUniforms({u_click:[this.clickPosition[0],this.clickPosition[1],this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",i=>{let s=i;this.isTouchDevice||t(s.clientX,s.clientY)}),this.eventListeners.set("mousedown",i=>{let s=i;this.isTouchDevice||s.button===0&&(this.isMouseDown=!0,e(!0,s.clientX,s.clientY))}),this.eventListeners.set("mouseup",i=>{let s=i;this.isTouchDevice||s.button===0&&e(!1)}),this.eventListeners.set("wheel",i=>{let s=i;this.scrollX+=s.deltaX*.01,this.scrollY+=s.deltaY*.01,t(s.clientX,s.clientY)}),this.eventListeners.set("touchmove",i=>{let s=i;s.touches.length>0&&t(s.touches[0].clientX,s.touches[0].clientY)}),this.eventListeners.set("touchstart",i=>{let s=i;this.isTouchDevice=!0,s.touches.length>0&&(e(!0,s.touches[0].clientX,s.touches[0].clientY),t(s.touches[0].clientX,s.touches[0].clientY))}),this.eventListeners.set("touchend",i=>{i.touches.length===0&&e(!1)}),this.eventListeners.forEach((i,s)=>{this.canvas.addEventListener(s,i)})}initializeUniform(t,e,i){if(this.uniforms.has(t))throw new Error(`Uniform '${t}' is already initialized.`);if(e!=="float"&&e!=="int")throw new Error(`Invalid uniform type: ${e}. Expected 'float' or 'int'.`);let s=this.gl.getUniformLocation(this.program,t);if(!s){console.debug(`Uniform ${t} not found in fragment shader. Skipping initialization.`);return}if(Array.isArray(i)||(i=[i]),i.length<1||i.length>4)throw new Error(`Invalid uniform value length: ${i.length}. Expected a length between 1 and 4.`);let r=i.length;this.uniforms.set(t,{type:e,length:r,location:s}),this.updateUniforms({[t]:i})}updateUniforms(t){Object.entries(t).forEach(([e,i])=>{if(!this.uniforms.has(e))throw new Error(`Uniform '${e}' is not initialized.`);let s=this.uniforms.get(e);if(Array.isArray(i)||(i=[i]),i.length!==s.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${s.length}.`);this.gl[`uniform${s.length}${s.type.charAt(0)}`](s.location,...i)})}step(t){let e=this.gl;if(this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.historyLength>0){let i=this.frame%this.historyLength;e.bindFramebuffer(e.FRAMEBUFFER,null),e.viewport(0,0,this.canvas.width,this.canvas.height),e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLES,0,6),e.bindTexture(e.TEXTURE_2D_ARRAY,this.historyTexture),e.copyTexSubImage3D(e.TEXTURE_2D_ARRAY,0,0,0,i,0,0,this.canvas.width,this.canvas.height)}else e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLES,0,6);++this.frame}play(t){let e=i=>{i/=1e3,this.step(i),t&&t(i,this.frame),this.animationFrameId=requestAnimationFrame(e)};this.animationFrameId=requestAnimationFrame(e)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}save(t){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.drawArrays(this.gl.TRIANGLES,0,6);let e=this.canvas.toDataURL();t&&!`${t}`.toLowerCase().endsWith(".png")&&(t=`${t}.png`),this.downloadLink.download=t||"export.png",this.downloadLink.href=e,this.downloadLink.click()}initializeTexture(t,e){if(this.textures.has(t))throw new Error(`Texture '${t}' is already initialized.`);let i=this.gl.createTexture();if(!i)throw new Error("Failed to create texture");let s=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+s),this.gl.bindTexture(this.gl.TEXTURE_2D,i),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.textures.set(t,{texture:i,unitIndex:s}),this.updateTextures({[t]:e});let r=this.gl.getUniformLocation(this.program,t);r&&this.gl.uniform1i(r,s)}updateTextures(t){Object.entries(t).forEach(([e,i])=>{let s=this.textures.get(e);if(!s)throw new Error(`Texture '${e}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+s.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,s.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,i)})}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resizeObserver.unobserve(this.canvas),this.eventListeners.forEach((t,e)=>{this.canvas.removeEventListener(e,t)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(t=>{this.gl.deleteTexture(t.texture)}),this.historyTexture&&(this.gl.deleteTexture(this.historyTexture),this.historyTexture=null),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},p=o;
9
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const defaultVertexShaderSrc = `\nattribute vec2 aPosition;\nvarying vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate canvas: HTMLCanvasElement;\n\tprivate gl: WebGLRenderingContext;\n\tprivate downloadLink: HTMLAnchorElement;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string, Texture> = new Map();\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate scrollX = 0;\n\tprivate scrollY = 0;\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\n\tconstructor(fragmentShaderSrc: string, canvas: HTMLCanvasElement | null = null) {\n\t\tthis.canvas = canvas || document.createElement('canvas');\n\t\tif (!canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tdocument.body.appendChild(this.canvas);\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}\n\t\tthis.gl = this.canvas.getContext('webgl')!;\n\t\tthis.downloadLink = document.createElement('a');\n\t\tthis.fragmentShaderSrc = fragmentShaderSrc;\n\t\tthis.animationFrameId = null;\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resizeCanvas());\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = defaultVertexShaderSrc;\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\t\tthis.resizeCanvas();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.initializeUniform('u_resolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('u_cursor', 'float', [...this.cursorPosition, this.scrollX, this.scrollY]); // [cursorX, cursorY, scrollX, scrollY]\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]); // [clickX, clickY, leftClick]\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\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.canvas.width, this.canvas.height);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\t// TODO: This breaks for `position: fixed; inset: 0` canvases.\n\tprivate resizeCanvas() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\n\t\tconst computedStyle = getComputedStyle(this.canvas);\n\t\tconst hasExplicitWidth = computedStyle.width !== `${this.canvas.width}px` && computedStyle.width !== 'auto';\n\t\tconst hasExplicitHeight = computedStyle.height !== `${this.canvas.height}px` && computedStyle.height !== 'auto';\n\t\tif (!hasExplicitWidth || !hasExplicitHeight) {\n\t\t\tthis.canvas.style.width = `${this.canvas.clientWidth}px`;\n\t\t\tthis.canvas.style.height = `${this.canvas.clientHeight}px`;\n\t\t}\n\n\t\tif (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\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\t\tthis.updateUniforms({ u_resolution: [this.canvas.width, this.canvas.height] });\n\t\t\t}\n\t\t}\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({\n\t\t\t\tu_cursor: [this.cursorPosition[0], this.cursorPosition[1], this.scrollX, this.scrollY],\n\t\t\t});\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\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({\n\t\t\t\tu_click: [this.clickPosition[0], this.clickPosition[1], this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('wheel', event => {\n\t\t\tconst wheelEvent = event as WheelEvent;\n\t\t\tthis.scrollX += wheelEvent.deltaX * 0.01;\n\t\t\tthis.scrollY += wheelEvent.deltaY * 0.01;\n\t\t\tupdateCursor(wheelEvent.clientX, wheelEvent.clientY);\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\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\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('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\tinitializeUniform(name: string, type: 'float' | 'int', value: number | number[]) {\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`Uniform '${name}' is already initialized.`);\n\t\t}\n\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\n\t\tconst location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location) {\n\t\t\tconsole.debug(`Uniform ${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!Array.isArray(value)) {\n\t\t\tvalue = [value];\n\t\t}\n\t\tif (value.length < 1 || value.length > 4) {\n\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected a length between 1 and 4.`);\n\t\t}\n\n\t\tconst length = value.length as 1 | 2 | 3 | 4;\n\t\tthis.uniforms.set(name, { type, length, location });\n\t\tthis.updateUniforms({ [name]: value });\n\t}\n\n\tupdateUniforms(updates: Record<string, number | number[]>) {\n\t\tObject.entries(updates).forEach(([name, value]: [string, number | number[]]) => {\n\t\t\tif (!this.uniforms.has(name)) {\n\t\t\t\tthrow new Error(`Uniform '${name}' is not initialized.`);\n\t\t\t}\n\n\t\t\tconst uniform = this.uniforms.get(name)!;\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tvalue = [value];\n\t\t\t}\n\t\t\tif (value.length !== uniform.length) {\n\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t}\n\t\t\t(this.gl as any)[`uniform${uniform.length}${uniform.type.charAt(0)}`](uniform.location, ...value);\n\t\t});\n\t}\n\n\tstep(time: number) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\t++this.frame;\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tconst loop = (time: number) => {\n\t\t\ttime /= 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\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\tsave(filename: string) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\n\t\tconst image = this.canvas.toDataURL();\n\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\tfilename = `${filename}.png`;\n\t\t}\n\t\tthis.downloadLink.download = filename || 'export.png';\n\t\tthis.downloadLink.href = image;\n\t\tthis.downloadLink.click();\n\t}\n\n\tinitializeTexture(name: string, source: HTMLImageElement | HTMLVideoElement) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${name}' is already initialized.`);\n\t\t}\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\t\tconst unitIndex = this.textures.size;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\n\t\t// Flip the texture vertically since v_uv is flipped, and set up filters and wrapping.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n\t\tthis.textures.set(name, { texture, unitIndex });\n\t\tthis.updateTextures({ [name]: source });\n\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, name);\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tupdateTextures(updates: Record<string, HTMLImageElement | HTMLVideoElement>) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tconst info = this.textures.get(name);\n\t\t\tif (!info) {\n\t\t\t\tthrow new Error(`Texture '${name}' is not initialized.`);\n\t\t\t}\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\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.resizeObserver.unobserve(this.canvas);\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\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tif (this.isInternalCanvas) {\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","defaultVertexShaderSrc","ShaderPad","fragmentShaderSrc","canvas","vertexShaderSrc","vertexShader","fragmentShader","aPosition","type","source","shader","quadVertices","pixelRatio","width","height","computedStyle","hasExplicitWidth","hasExplicitHeight","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","wheelEvent","touchEvent","listener","name","value","location","length","updates","uniform","time","callback","loop","filename","image","texture","unitIndex","uSampler","info"]}
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}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n}\n\ninterface Options {\n\thistory?: number;\n\tcanvas?: HTMLCanvasElement | null;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate canvas: HTMLCanvasElement;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate downloadLink: HTMLAnchorElement;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string, Texture> = new Map();\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: NodeJS.Timeout = null as unknown as NodeJS.Timeout;\n\tprivate lastResizeTime = 0;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate scrollX = 0;\n\tprivate scrollY = 0;\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tprivate historyLength: number;\n\tprivate historyTexture: WebGLTexture | null = null;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tthis.historyLength = options.history || 0;\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tdocument.body.appendChild(this.canvas);\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}\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.downloadLink = document.createElement('a');\n\t\tthis.fragmentShaderSrc = fragmentShaderSrc;\n\t\tthis.animationFrameId = null;\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.init();\n\t\tthis.addEventListeners();\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\t\tthis.handleResize();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.initializeUniform('u_resolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('u_cursor', 'float', [...this.cursorPosition, this.scrollX, this.scrollY]); // [cursorX, cursorY, scrollX, scrollY]\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]); // [clickX, clickY, leftClick]\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\n\t\tif (this.historyLength > 0) {\n\t\t\tthis.initializeHistoryBuffer();\n\t\t}\n\t}\n\n\tprivate initializeHistoryBuffer() {\n\t\tconst { gl } = this;\n\n\t\tthis.historyTexture = gl.createTexture();\n\t\tif (!this.historyTexture) {\n\t\t\tthrow new Error('Failed to create history texture');\n\t\t}\n\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, this.canvas.width, this.canvas.height, this.historyLength);\n\n\t\tgl.activeTexture(gl.TEXTURE0);\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\n\t\tif (!this.uniforms.has('u_history')) {\n\t\t\tthis.initializeUniform('u_history', 'int', 0);\n\t\t}\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate 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.canvas.width, this.canvas.height);\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\t// TODO: This breaks for `position: fixed; inset: 0` canvases.\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\n\t\tconst computedStyle = getComputedStyle(this.canvas);\n\t\tconst hasExplicitWidth = computedStyle.width !== `${this.canvas.width}px` && computedStyle.width !== 'auto';\n\t\tconst hasExplicitHeight = computedStyle.height !== `${this.canvas.height}px` && computedStyle.height !== 'auto';\n\t\tif (!hasExplicitWidth || !hasExplicitHeight) {\n\t\t\tthis.canvas.style.width = `${this.canvas.clientWidth}px`;\n\t\t\tthis.canvas.style.height = `${this.canvas.clientHeight}px`;\n\t\t}\n\n\t\tif (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\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\t\tthis.updateUniforms({ u_resolution: [this.canvas.width, this.canvas.height] });\n\t\t\t}\n\n\t\t\t// Delete and recreate history buffer, since the canvas size won’t be correct anymore.\n\t\t\tif (this.historyLength > 0 && this.historyTexture) {\n\t\t\t\tthis.gl.deleteTexture(this.historyTexture);\n\t\t\t\tthis.initializeHistoryBuffer();\n\t\t\t}\n\t\t}\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({\n\t\t\t\tu_cursor: [this.cursorPosition[0], this.cursorPosition[1], this.scrollX, this.scrollY],\n\t\t\t});\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({\n\t\t\t\tu_click: [this.clickPosition[0], this.clickPosition[1], this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('wheel', event => {\n\t\t\tconst wheelEvent = event as WheelEvent;\n\t\t\tthis.scrollX += wheelEvent.deltaX * 0.01;\n\t\t\tthis.scrollY += wheelEvent.deltaY * 0.01;\n\t\t\tupdateCursor(wheelEvent.clientX, wheelEvent.clientY);\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\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\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('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\tinitializeUniform(name: string, type: 'float' | 'int', value: number | number[]) {\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`Uniform '${name}' is already initialized.`);\n\t\t}\n\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\n\t\tconst location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location) {\n\t\t\tconsole.debug(`Uniform ${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!Array.isArray(value)) {\n\t\t\tvalue = [value];\n\t\t}\n\t\tif (value.length < 1 || value.length > 4) {\n\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected a length between 1 and 4.`);\n\t\t}\n\n\t\tconst length = value.length as 1 | 2 | 3 | 4;\n\t\tthis.uniforms.set(name, { type, length, location });\n\t\tthis.updateUniforms({ [name]: value });\n\t}\n\n\tupdateUniforms(updates: Record<string, number | number[]>) {\n\t\tObject.entries(updates).forEach(([name, value]: [string, number | number[]]) => {\n\t\t\tif (!this.uniforms.has(name)) {\n\t\t\t\tthrow new Error(`Uniform '${name}' is not initialized.`);\n\t\t\t}\n\n\t\t\tconst uniform = this.uniforms.get(name)!;\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tvalue = [value];\n\t\t\t}\n\t\t\tif (value.length !== uniform.length) {\n\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t}\n\t\t\t(this.gl as any)[`uniform${uniform.length}${uniform.type.charAt(0)}`](uniform.location, ...value);\n\t\t});\n\t}\n\n\tstep(time: number) {\n\t\tconst gl = this.gl;\n\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\tif (this.historyLength > 0) {\n\t\t\tconst writeIdx = this.frame % this.historyLength;\n\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\t\t\tgl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, writeIdx, 0, 0, this.canvas.width, this.canvas.height);\n\t\t} else {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t\t}\n\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tconst loop = (time: number) => {\n\t\t\ttime /= 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\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\tsave(filename: string) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\n\t\tconst image = this.canvas.toDataURL();\n\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\tfilename = `${filename}.png`;\n\t\t}\n\t\tthis.downloadLink.download = filename || 'export.png';\n\t\tthis.downloadLink.href = image;\n\t\tthis.downloadLink.click();\n\t}\n\n\tinitializeTexture(name: string, source: HTMLImageElement | HTMLVideoElement) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${name}' is already initialized.`);\n\t\t}\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\t\tconst unitIndex = this.textures.size;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\n\t\t// Flip the texture vertically since v_uv is flipped, and set up filters and wrapping.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n\t\tthis.textures.set(name, { texture, unitIndex });\n\t\tthis.updateTextures({ [name]: source });\n\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, name);\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tupdateTextures(updates: Record<string, HTMLImageElement | HTMLVideoElement>) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tconst info = this.textures.get(name);\n\t\t\tif (!info) {\n\t\t\t\tthrow new Error(`Texture '${name}' is not initialized.`);\n\t\t\t}\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\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.resizeObserver.unobserve(this.canvas);\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\n\t\tif (this.historyTexture) {\n\t\t\tthis.gl.deleteTexture(this.historyTexture);\n\t\t\tthis.historyTexture = null;\n\t\t}\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\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","ShaderPad","fragmentShaderSrc","options","vertexShaderSrc","vertexShader","fragmentShader","aPosition","gl","type","source","shader","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","computedStyle","hasExplicitWidth","hasExplicitHeight","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","wheelEvent","touchEvent","listener","name","value","location","length","updates","uniform","time","writeIdx","callback","loop","filename","image","texture","unitIndex","uSampler","info"]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- var l=`
2
- attribute vec2 aPosition;
3
- varying vec2 v_uv;
1
+ var l=`#version 300 es
2
+ in vec2 aPosition;
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
- `,a=class{constructor(e,s=null){this.isInternalCanvas=!1;this.isTouchDevice=!1;this.uniforms=new Map;this.textures=new Map;this.buffer=null;this.program=null;this.eventListeners=new Map;this.frame=0;this.cursorPosition=[.5,.5];this.scrollX=0;this.scrollY=0;this.clickPosition=[.5,.5];this.isMouseDown=!1;this.canvas=s||document.createElement("canvas"),s||(this.isInternalCanvas=!0,document.body.appendChild(this.canvas),this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw"),this.gl=this.canvas.getContext("webgl"),this.downloadLink=document.createElement("a"),this.fragmentShaderSrc=e,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.resizeCanvas()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let e=l;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let s=this.createShader(this.gl.VERTEX_SHADER,e),t=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,s),this.gl.attachShader(this.program,t),this.gl.linkProgram(this.program),this.gl.deleteShader(s),this.gl.deleteShader(t),!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 i=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(i),this.resizeCanvas(),this.gl.useProgram(this.program),this.initializeUniform("u_resolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("u_cursor","float",[...this.cursorPosition,this.scrollX,this.scrollY]),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0)}createShader(e,s){let t=this.gl.createShader(e);if(this.gl.shaderSource(t,s),this.gl.compileShader(t),!this.gl.getShaderParameter(t,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",s),console.error(this.gl.getShaderInfoLog(t)),this.gl.deleteShader(t),new Error("Shader compilation failed");return t}setupBuffer(e){let s=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,s,this.gl.STATIC_DRAW),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.gl.enableVertexAttribArray(e),this.gl.vertexAttribPointer(e,2,this.gl.FLOAT,!1,0,0)}resizeCanvas(){let e=window.devicePixelRatio||1,s=this.canvas.clientWidth*e,t=this.canvas.clientHeight*e,i=getComputedStyle(this.canvas),r=i.width!==`${this.canvas.width}px`&&i.width!=="auto",n=i.height!==`${this.canvas.height}px`&&i.height!=="auto";(!r||!n)&&(this.canvas.style.width=`${this.canvas.clientWidth}px`,this.canvas.style.height=`${this.canvas.clientHeight}px`),(this.canvas.width!==s||this.canvas.height!==t)&&(this.canvas.width=s,this.canvas.height=t,this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.uniforms.has("u_resolution")&&this.updateUniforms({u_resolution:[this.canvas.width,this.canvas.height]}))}addEventListeners(){let e=(t,i)=>{if(!this.uniforms.has("u_cursor"))return;let r=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(t-r.left)/r.width,this.cursorPosition[1]=1-(i-r.top)/r.height,this.updateUniforms({u_cursor:[this.cursorPosition[0],this.cursorPosition[1],this.scrollX,this.scrollY]})},s=(t,i,r)=>{if(this.isMouseDown=t,t){let n=this.canvas.getBoundingClientRect(),h=i,o=r;this.clickPosition[0]=(h-n.left)/n.width,this.clickPosition[1]=1-(o-n.top)/n.height}this.updateUniforms({u_click:[this.clickPosition[0],this.clickPosition[1],this.isMouseDown?1:0]})};this.eventListeners.set("mousemove",t=>{let i=t;this.isTouchDevice||e(i.clientX,i.clientY)}),this.eventListeners.set("mousedown",t=>{let i=t;this.isTouchDevice||i.button===0&&(this.isMouseDown=!0,s(!0,i.clientX,i.clientY))}),this.eventListeners.set("mouseup",t=>{let i=t;this.isTouchDevice||i.button===0&&s(!1)}),this.eventListeners.set("wheel",t=>{let i=t;this.scrollX+=i.deltaX*.01,this.scrollY+=i.deltaY*.01,e(i.clientX,i.clientY)}),this.eventListeners.set("touchmove",t=>{let i=t;i.touches.length>0&&e(i.touches[0].clientX,i.touches[0].clientY)}),this.eventListeners.set("touchstart",t=>{let i=t;this.isTouchDevice=!0,i.touches.length>0&&(s(!0,i.touches[0].clientX,i.touches[0].clientY),e(i.touches[0].clientX,i.touches[0].clientY))}),this.eventListeners.set("touchend",t=>{t.touches.length===0&&s(!1)}),this.eventListeners.forEach((t,i)=>{this.canvas.addEventListener(i,t)})}initializeUniform(e,s,t){if(this.uniforms.has(e))throw new Error(`Uniform '${e}' is already initialized.`);if(s!=="float"&&s!=="int")throw new Error(`Invalid uniform type: ${s}. Expected 'float' or 'int'.`);let i=this.gl.getUniformLocation(this.program,e);if(!i){console.debug(`Uniform ${e} not found in fragment shader. Skipping initialization.`);return}if(Array.isArray(t)||(t=[t]),t.length<1||t.length>4)throw new Error(`Invalid uniform value length: ${t.length}. Expected a length between 1 and 4.`);let r=t.length;this.uniforms.set(e,{type:s,length:r,location:i}),this.updateUniforms({[e]:t})}updateUniforms(e){Object.entries(e).forEach(([s,t])=>{if(!this.uniforms.has(s))throw new Error(`Uniform '${s}' is not initialized.`);let i=this.uniforms.get(s);if(Array.isArray(t)||(t=[t]),t.length!==i.length)throw new Error(`Invalid uniform value length: ${t.length}. Expected ${i.length}.`);this.gl[`uniform${i.length}${i.type.charAt(0)}`](i.location,...t)})}step(e){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.uniforms.has("u_time")&&this.updateUniforms({u_time:e}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),++this.frame,this.gl.drawArrays(this.gl.TRIANGLES,0,6)}play(e){let s=t=>{t/=1e3,this.step(t),e&&e(t,this.frame),this.animationFrameId=requestAnimationFrame(s)};this.animationFrameId=requestAnimationFrame(s)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}save(e){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.drawArrays(this.gl.TRIANGLES,0,6);let s=this.canvas.toDataURL();e&&!`${e}`.toLowerCase().endsWith(".png")&&(e=`${e}.png`),this.downloadLink.download=e||"export.png",this.downloadLink.href=s,this.downloadLink.click()}initializeTexture(e,s){if(this.textures.has(e))throw new Error(`Texture '${e}' is already initialized.`);let t=this.gl.createTexture();if(!t)throw new Error("Failed to create texture");let i=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+i),this.gl.bindTexture(this.gl.TEXTURE_2D,t),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.textures.set(e,{texture:t,unitIndex:i}),this.updateTextures({[e]:s});let r=this.gl.getUniformLocation(this.program,e);r&&this.gl.uniform1i(r,i)}updateTextures(e){Object.entries(e).forEach(([s,t])=>{let i=this.textures.get(s);if(!i)throw new Error(`Texture '${s}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+i.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,i.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,t)})}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resizeObserver.unobserve(this.canvas),this.eventListeners.forEach((e,s)=>{this.canvas.removeEventListener(s,e)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(e=>{this.gl.deleteTexture(e.texture)}),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},g=a;export{g as default};
8
+ `,c=33.333333333333336,h=class{constructor(t,i={}){this.isInternalCanvas=!1;this.isTouchDevice=!1;this.uniforms=new Map;this.textures=new Map;this.buffer=null;this.program=null;this.resizeTimeout=null;this.lastResizeTime=0;this.eventListeners=new Map;this.frame=0;this.cursorPosition=[.5,.5];this.scrollX=0;this.scrollY=0;this.clickPosition=[.5,.5];this.isMouseDown=!1;this.historyTexture=null;if(this.canvas=i.canvas||document.createElement("canvas"),this.historyLength=i.history||0,i.canvas||(this.isInternalCanvas=!0,document.body.appendChild(this.canvas),this.canvas.style.position="fixed",this.canvas.style.inset="0",this.canvas.style.height="100dvh",this.canvas.style.width="100dvw"),this.gl=this.canvas.getContext("webgl2",{antialias:!1}),!this.gl)throw new Error("WebGL2 not supported. Please use a browser that supports WebGL2.");this.downloadLink=document.createElement("a"),this.fragmentShaderSrc=t,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.throttledHandleResize()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let t=l;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 s=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(s),this.handleResize(),this.gl.useProgram(this.program),this.initializeUniform("u_resolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("u_cursor","float",[...this.cursorPosition,this.scrollX,this.scrollY]),this.initializeUniform("u_click","float",[...this.clickPosition,this.isMouseDown?1:0]),this.initializeUniform("u_time","float",0),this.initializeUniform("u_frame","int",0),this.historyLength>0&&this.initializeHistoryBuffer()}initializeHistoryBuffer(){let{gl:t}=this;if(this.historyTexture=t.createTexture(),!this.historyTexture)throw new Error("Failed to create history texture");t.bindTexture(t.TEXTURE_2D_ARRAY,this.historyTexture),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D_ARRAY,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texStorage3D(t.TEXTURE_2D_ARRAY,1,t.RGBA8,this.canvas.width,this.canvas.height,this.historyLength),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D_ARRAY,this.historyTexture),this.uniforms.has("u_history")||this.initializeUniform("u_history","int",0)}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.canvas.width,this.canvas.height),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+c-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,s=getComputedStyle(this.canvas),r=s.width!==`${this.canvas.width}px`&&s.width!=="auto",n=s.height!==`${this.canvas.height}px`&&s.height!=="auto";(!r||!n)&&(this.canvas.style.width=`${this.canvas.clientWidth}px`,this.canvas.style.height=`${this.canvas.clientHeight}px`),(this.canvas.width!==i||this.canvas.height!==e)&&(this.canvas.width=i,this.canvas.height=e,this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.uniforms.has("u_resolution")&&this.updateUniforms({u_resolution:[this.canvas.width,this.canvas.height]}),this.historyLength>0&&this.historyTexture&&(this.gl.deleteTexture(this.historyTexture),this.initializeHistoryBuffer()))}addEventListeners(){let t=(e,s)=>{if(!this.uniforms.has("u_cursor"))return;let r=this.canvas.getBoundingClientRect();this.cursorPosition[0]=(e-r.left)/r.width,this.cursorPosition[1]=1-(s-r.top)/r.height,this.updateUniforms({u_cursor:[this.cursorPosition[0],this.cursorPosition[1],this.scrollX,this.scrollY]})},i=(e,s,r)=>{if(this.uniforms.has("u_click")){if(this.isMouseDown=e,e){let n=this.canvas.getBoundingClientRect(),a=s,o=r;this.clickPosition[0]=(a-n.left)/n.width,this.clickPosition[1]=1-(o-n.top)/n.height}this.updateUniforms({u_click:[this.clickPosition[0],this.clickPosition[1],this.isMouseDown?1:0]})}};this.eventListeners.set("mousemove",e=>{let s=e;this.isTouchDevice||t(s.clientX,s.clientY)}),this.eventListeners.set("mousedown",e=>{let s=e;this.isTouchDevice||s.button===0&&(this.isMouseDown=!0,i(!0,s.clientX,s.clientY))}),this.eventListeners.set("mouseup",e=>{let s=e;this.isTouchDevice||s.button===0&&i(!1)}),this.eventListeners.set("wheel",e=>{let s=e;this.scrollX+=s.deltaX*.01,this.scrollY+=s.deltaY*.01,t(s.clientX,s.clientY)}),this.eventListeners.set("touchmove",e=>{let s=e;s.touches.length>0&&t(s.touches[0].clientX,s.touches[0].clientY)}),this.eventListeners.set("touchstart",e=>{let s=e;this.isTouchDevice=!0,s.touches.length>0&&(i(!0,s.touches[0].clientX,s.touches[0].clientY),t(s.touches[0].clientX,s.touches[0].clientY))}),this.eventListeners.set("touchend",e=>{e.touches.length===0&&i(!1)}),this.eventListeners.forEach((e,s)=>{this.canvas.addEventListener(s,e)})}initializeUniform(t,i,e){if(this.uniforms.has(t))throw new Error(`Uniform '${t}' is already initialized.`);if(i!=="float"&&i!=="int")throw new Error(`Invalid uniform type: ${i}. Expected 'float' or 'int'.`);let s=this.gl.getUniformLocation(this.program,t);if(!s){console.debug(`Uniform ${t} not found in fragment shader. Skipping initialization.`);return}if(Array.isArray(e)||(e=[e]),e.length<1||e.length>4)throw new Error(`Invalid uniform value length: ${e.length}. Expected a length between 1 and 4.`);let r=e.length;this.uniforms.set(t,{type:i,length:r,location:s}),this.updateUniforms({[t]:e})}updateUniforms(t){Object.entries(t).forEach(([i,e])=>{if(!this.uniforms.has(i))throw new Error(`Uniform '${i}' is not initialized.`);let s=this.uniforms.get(i);if(Array.isArray(e)||(e=[e]),e.length!==s.length)throw new Error(`Invalid uniform value length: ${e.length}. Expected ${s.length}.`);this.gl[`uniform${s.length}${s.type.charAt(0)}`](s.location,...e)})}step(t){let i=this.gl;if(this.uniforms.has("u_time")&&this.updateUniforms({u_time:t}),this.uniforms.has("u_frame")&&this.updateUniforms({u_frame:this.frame}),this.historyLength>0){let e=this.frame%this.historyLength;i.bindFramebuffer(i.FRAMEBUFFER,null),i.viewport(0,0,this.canvas.width,this.canvas.height),i.clear(i.COLOR_BUFFER_BIT),i.drawArrays(i.TRIANGLES,0,6),i.bindTexture(i.TEXTURE_2D_ARRAY,this.historyTexture),i.copyTexSubImage3D(i.TEXTURE_2D_ARRAY,0,0,0,e,0,0,this.canvas.width,this.canvas.height)}else i.clear(i.COLOR_BUFFER_BIT),i.drawArrays(i.TRIANGLES,0,6);++this.frame}play(t){let i=e=>{e/=1e3,this.step(e),t&&t(e,this.frame),this.animationFrameId=requestAnimationFrame(i)};this.animationFrameId=requestAnimationFrame(i)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}save(t){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.drawArrays(this.gl.TRIANGLES,0,6);let i=this.canvas.toDataURL();t&&!`${t}`.toLowerCase().endsWith(".png")&&(t=`${t}.png`),this.downloadLink.download=t||"export.png",this.downloadLink.href=i,this.downloadLink.click()}initializeTexture(t,i){if(this.textures.has(t))throw new Error(`Texture '${t}' is already initialized.`);let e=this.gl.createTexture();if(!e)throw new Error("Failed to create texture");let s=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+s),this.gl.bindTexture(this.gl.TEXTURE_2D,e),this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!0),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.textures.set(t,{texture:e,unitIndex:s}),this.updateTextures({[t]:i});let r=this.gl.getUniformLocation(this.program,t);r&&this.gl.uniform1i(r,s)}updateTextures(t){Object.entries(t).forEach(([i,e])=>{let s=this.textures.get(i);if(!s)throw new Error(`Texture '${i}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+s.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,s.texture),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,this.gl.RGBA,this.gl.UNSIGNED_BYTE,e)})}destroy(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null),this.resizeObserver.unobserve(this.canvas),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.historyTexture&&(this.gl.deleteTexture(this.historyTexture),this.historyTexture=null),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},g=h;export{g as default};
9
9
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const defaultVertexShaderSrc = `\nattribute vec2 aPosition;\nvarying vec2 v_uv;\nvoid main() {\n v_uv = aPosition * 0.5 + 0.5;\n gl_Position = vec4(aPosition, 0.0, 1.0);\n}\n`;\n\ninterface Uniform {\n\ttype: 'float' | 'int';\n\tlength: 1 | 2 | 3 | 4;\n\tlocation: WebGLUniformLocation;\n}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate canvas: HTMLCanvasElement;\n\tprivate gl: WebGLRenderingContext;\n\tprivate downloadLink: HTMLAnchorElement;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string, Texture> = new Map();\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate scrollX = 0;\n\tprivate scrollY = 0;\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\n\tconstructor(fragmentShaderSrc: string, canvas: HTMLCanvasElement | null = null) {\n\t\tthis.canvas = canvas || document.createElement('canvas');\n\t\tif (!canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tdocument.body.appendChild(this.canvas);\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}\n\t\tthis.gl = this.canvas.getContext('webgl')!;\n\t\tthis.downloadLink = document.createElement('a');\n\t\tthis.fragmentShaderSrc = fragmentShaderSrc;\n\t\tthis.animationFrameId = null;\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resizeCanvas());\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.init();\n\t\tthis.addEventListeners();\n\t}\n\n\tprivate init() {\n\t\tconst vertexShaderSrc = defaultVertexShaderSrc;\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\t\tthis.resizeCanvas();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.initializeUniform('u_resolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('u_cursor', 'float', [...this.cursorPosition, this.scrollX, this.scrollY]); // [cursorX, cursorY, scrollX, scrollY]\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]); // [clickX, clickY, leftClick]\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\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.canvas.width, this.canvas.height);\n\t\tthis.gl.enableVertexAttribArray(aPosition);\n\t\tthis.gl.vertexAttribPointer(aPosition, 2, this.gl.FLOAT, false, 0, 0);\n\t}\n\n\t// TODO: This breaks for `position: fixed; inset: 0` canvases.\n\tprivate resizeCanvas() {\n\t\tconst pixelRatio = window.devicePixelRatio || 1;\n\t\tconst width = this.canvas.clientWidth * pixelRatio;\n\t\tconst height = this.canvas.clientHeight * pixelRatio;\n\n\t\tconst computedStyle = getComputedStyle(this.canvas);\n\t\tconst hasExplicitWidth = computedStyle.width !== `${this.canvas.width}px` && computedStyle.width !== 'auto';\n\t\tconst hasExplicitHeight = computedStyle.height !== `${this.canvas.height}px` && computedStyle.height !== 'auto';\n\t\tif (!hasExplicitWidth || !hasExplicitHeight) {\n\t\t\tthis.canvas.style.width = `${this.canvas.clientWidth}px`;\n\t\t\tthis.canvas.style.height = `${this.canvas.clientHeight}px`;\n\t\t}\n\n\t\tif (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\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\t\tthis.updateUniforms({ u_resolution: [this.canvas.width, this.canvas.height] });\n\t\t\t}\n\t\t}\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({\n\t\t\t\tu_cursor: [this.cursorPosition[0], this.cursorPosition[1], this.scrollX, this.scrollY],\n\t\t\t});\n\t\t};\n\n\t\tconst updateClick = (isMouseDown: boolean, x?: number, y?: number) => {\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({\n\t\t\t\tu_click: [this.clickPosition[0], this.clickPosition[1], this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('wheel', event => {\n\t\t\tconst wheelEvent = event as WheelEvent;\n\t\t\tthis.scrollX += wheelEvent.deltaX * 0.01;\n\t\t\tthis.scrollY += wheelEvent.deltaY * 0.01;\n\t\t\tupdateCursor(wheelEvent.clientX, wheelEvent.clientY);\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\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\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('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\tinitializeUniform(name: string, type: 'float' | 'int', value: number | number[]) {\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`Uniform '${name}' is already initialized.`);\n\t\t}\n\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\n\t\tconst location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location) {\n\t\t\tconsole.debug(`Uniform ${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!Array.isArray(value)) {\n\t\t\tvalue = [value];\n\t\t}\n\t\tif (value.length < 1 || value.length > 4) {\n\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected a length between 1 and 4.`);\n\t\t}\n\n\t\tconst length = value.length as 1 | 2 | 3 | 4;\n\t\tthis.uniforms.set(name, { type, length, location });\n\t\tthis.updateUniforms({ [name]: value });\n\t}\n\n\tupdateUniforms(updates: Record<string, number | number[]>) {\n\t\tObject.entries(updates).forEach(([name, value]: [string, number | number[]]) => {\n\t\t\tif (!this.uniforms.has(name)) {\n\t\t\t\tthrow new Error(`Uniform '${name}' is not initialized.`);\n\t\t\t}\n\n\t\t\tconst uniform = this.uniforms.get(name)!;\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tvalue = [value];\n\t\t\t}\n\t\t\tif (value.length !== uniform.length) {\n\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t}\n\t\t\t(this.gl as any)[`uniform${uniform.length}${uniform.type.charAt(0)}`](uniform.location, ...value);\n\t\t});\n\t}\n\n\tstep(time: number) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tif (this.uniforms.has('u_time')) {\n\t\t\tthis.updateUniforms({ u_time: time });\n\t\t}\n\n\t\tif (this.uniforms.has('u_frame')) {\n\t\t\tthis.updateUniforms({ u_frame: this.frame });\n\t\t}\n\n\t\t++this.frame;\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tconst loop = (time: number) => {\n\t\t\ttime /= 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\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\tsave(filename: string) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\n\t\tconst image = this.canvas.toDataURL();\n\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\tfilename = `${filename}.png`;\n\t\t}\n\t\tthis.downloadLink.download = filename || 'export.png';\n\t\tthis.downloadLink.href = image;\n\t\tthis.downloadLink.click();\n\t}\n\n\tinitializeTexture(name: string, source: HTMLImageElement | HTMLVideoElement) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${name}' is already initialized.`);\n\t\t}\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\t\tconst unitIndex = this.textures.size;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\n\t\t// Flip the texture vertically since v_uv is flipped, and set up filters and wrapping.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n\t\tthis.textures.set(name, { texture, unitIndex });\n\t\tthis.updateTextures({ [name]: source });\n\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, name);\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tupdateTextures(updates: Record<string, HTMLImageElement | HTMLVideoElement>) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tconst info = this.textures.get(name);\n\t\t\tif (!info) {\n\t\t\t\tthrow new Error(`Texture '${name}' is not initialized.`);\n\t\t\t}\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\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.resizeObserver.unobserve(this.canvas);\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\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\tif (this.isInternalCanvas) {\n\t\t\tthis.canvas.remove();\n\t\t}\n\t}\n}\n\nexport default ShaderPad;\n"],"mappings":"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","names":["defaultVertexShaderSrc","ShaderPad","fragmentShaderSrc","canvas","vertexShaderSrc","vertexShader","fragmentShader","aPosition","type","source","shader","quadVertices","pixelRatio","width","height","computedStyle","hasExplicitWidth","hasExplicitHeight","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","wheelEvent","touchEvent","listener","name","value","location","length","updates","uniform","time","callback","loop","filename","image","texture","unitIndex","uSampler","info","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}\n\ninterface Texture {\n\ttexture: WebGLTexture;\n\tunitIndex: number;\n}\n\ninterface Options {\n\thistory?: number;\n\tcanvas?: HTMLCanvasElement | null;\n}\n\nclass ShaderPad {\n\tprivate isInternalCanvas = false;\n\tprivate isTouchDevice = false;\n\tprivate canvas: HTMLCanvasElement;\n\tprivate gl: WebGL2RenderingContext;\n\tprivate downloadLink: HTMLAnchorElement;\n\tprivate fragmentShaderSrc: string;\n\tprivate uniforms: Map<string, Uniform> = new Map();\n\tprivate textures: Map<string, Texture> = new Map();\n\tprivate buffer: WebGLBuffer | null = null;\n\tprivate program: WebGLProgram | null = null;\n\tprivate animationFrameId: number | null;\n\tprivate resizeObserver: ResizeObserver;\n\tprivate resizeTimeout: NodeJS.Timeout = null as unknown as NodeJS.Timeout;\n\tprivate lastResizeTime = 0;\n\tprivate eventListeners: Map<string, EventListener> = new Map();\n\tprivate frame = 0;\n\tprivate cursorPosition = [0.5, 0.5];\n\tprivate scrollX = 0;\n\tprivate scrollY = 0;\n\tprivate clickPosition = [0.5, 0.5];\n\tprivate isMouseDown = false;\n\tprivate historyLength: number;\n\tprivate historyTexture: WebGLTexture | null = null;\n\n\tconstructor(fragmentShaderSrc: string, options: Options = {}) {\n\t\tthis.canvas = options.canvas || document.createElement('canvas');\n\t\tthis.historyLength = options.history || 0;\n\t\tif (!options.canvas) {\n\t\t\tthis.isInternalCanvas = true;\n\t\t\tdocument.body.appendChild(this.canvas);\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}\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.downloadLink = document.createElement('a');\n\t\tthis.fragmentShaderSrc = fragmentShaderSrc;\n\t\tthis.animationFrameId = null;\n\t\tthis.resizeObserver = new ResizeObserver(() => this.throttledHandleResize());\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.init();\n\t\tthis.addEventListeners();\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\t\tthis.handleResize();\n\n\t\tthis.gl.useProgram(this.program);\n\n\t\tthis.initializeUniform('u_resolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('u_cursor', 'float', [...this.cursorPosition, this.scrollX, this.scrollY]); // [cursorX, cursorY, scrollX, scrollY]\n\t\tthis.initializeUniform('u_click', 'float', [...this.clickPosition, this.isMouseDown ? 1.0 : 0.0]); // [clickX, clickY, leftClick]\n\t\tthis.initializeUniform('u_time', 'float', 0);\n\t\tthis.initializeUniform('u_frame', 'int', 0);\n\n\t\tif (this.historyLength > 0) {\n\t\t\tthis.initializeHistoryBuffer();\n\t\t}\n\t}\n\n\tprivate initializeHistoryBuffer() {\n\t\tconst { gl } = this;\n\n\t\tthis.historyTexture = gl.createTexture();\n\t\tif (!this.historyTexture) {\n\t\t\tthrow new Error('Failed to create history texture');\n\t\t}\n\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, this.canvas.width, this.canvas.height, this.historyLength);\n\n\t\tgl.activeTexture(gl.TEXTURE0);\n\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\n\t\tif (!this.uniforms.has('u_history')) {\n\t\t\tthis.initializeUniform('u_history', 'int', 0);\n\t\t}\n\t}\n\n\tprivate createShader(type: number, source: string): WebGLShader {\n\t\tconst shader = this.gl.createShader(type)!;\n\t\tthis.gl.shaderSource(shader, source);\n\t\tthis.gl.compileShader(shader);\n\t\tif (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n\t\t\tconsole.error('Shader compilation failed:', source);\n\t\t\tconsole.error(this.gl.getShaderInfoLog(shader));\n\t\t\tthis.gl.deleteShader(shader);\n\t\t\tthrow new Error('Shader compilation failed');\n\t\t}\n\t\treturn shader;\n\t}\n\n\tprivate 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.canvas.width, this.canvas.height);\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\t// TODO: This breaks for `position: fixed; inset: 0` canvases.\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\n\t\tconst computedStyle = getComputedStyle(this.canvas);\n\t\tconst hasExplicitWidth = computedStyle.width !== `${this.canvas.width}px` && computedStyle.width !== 'auto';\n\t\tconst hasExplicitHeight = computedStyle.height !== `${this.canvas.height}px` && computedStyle.height !== 'auto';\n\t\tif (!hasExplicitWidth || !hasExplicitHeight) {\n\t\t\tthis.canvas.style.width = `${this.canvas.clientWidth}px`;\n\t\t\tthis.canvas.style.height = `${this.canvas.clientHeight}px`;\n\t\t}\n\n\t\tif (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\tthis.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);\n\t\t\tif (this.uniforms.has('u_resolution')) {\n\t\t\t\tthis.updateUniforms({ u_resolution: [this.canvas.width, this.canvas.height] });\n\t\t\t}\n\n\t\t\t// Delete and recreate history buffer, since the canvas size won’t be correct anymore.\n\t\t\tif (this.historyLength > 0 && this.historyTexture) {\n\t\t\t\tthis.gl.deleteTexture(this.historyTexture);\n\t\t\t\tthis.initializeHistoryBuffer();\n\t\t\t}\n\t\t}\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({\n\t\t\t\tu_cursor: [this.cursorPosition[0], this.cursorPosition[1], this.scrollX, this.scrollY],\n\t\t\t});\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({\n\t\t\t\tu_click: [this.clickPosition[0], this.clickPosition[1], this.isMouseDown ? 1.0 : 0.0],\n\t\t\t});\n\t\t};\n\n\t\tthis.eventListeners.set('mousemove', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tupdateCursor(mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mousedown', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tthis.isMouseDown = true;\n\t\t\t\t\tupdateClick(true, mouseEvent.clientX, mouseEvent.clientY);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('mouseup', event => {\n\t\t\tconst mouseEvent = event as MouseEvent;\n\t\t\tif (!this.isTouchDevice) {\n\t\t\t\tif (mouseEvent.button === 0) {\n\t\t\t\t\tupdateClick(false);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tthis.eventListeners.set('wheel', event => {\n\t\t\tconst wheelEvent = event as WheelEvent;\n\t\t\tthis.scrollX += wheelEvent.deltaX * 0.01;\n\t\t\tthis.scrollY += wheelEvent.deltaY * 0.01;\n\t\t\tupdateCursor(wheelEvent.clientX, wheelEvent.clientY);\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\tupdateClick(true, touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);\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('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\tinitializeUniform(name: string, type: 'float' | 'int', value: number | number[]) {\n\t\tif (this.uniforms.has(name)) {\n\t\t\tthrow new Error(`Uniform '${name}' is already initialized.`);\n\t\t}\n\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\n\t\tconst location = this.gl.getUniformLocation(this.program!, name);\n\t\tif (!location) {\n\t\t\tconsole.debug(`Uniform ${name} not found in fragment shader. Skipping initialization.`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!Array.isArray(value)) {\n\t\t\tvalue = [value];\n\t\t}\n\t\tif (value.length < 1 || value.length > 4) {\n\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected a length between 1 and 4.`);\n\t\t}\n\n\t\tconst length = value.length as 1 | 2 | 3 | 4;\n\t\tthis.uniforms.set(name, { type, length, location });\n\t\tthis.updateUniforms({ [name]: value });\n\t}\n\n\tupdateUniforms(updates: Record<string, number | number[]>) {\n\t\tObject.entries(updates).forEach(([name, value]: [string, number | number[]]) => {\n\t\t\tif (!this.uniforms.has(name)) {\n\t\t\t\tthrow new Error(`Uniform '${name}' is not initialized.`);\n\t\t\t}\n\n\t\t\tconst uniform = this.uniforms.get(name)!;\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tvalue = [value];\n\t\t\t}\n\t\t\tif (value.length !== uniform.length) {\n\t\t\t\tthrow new Error(`Invalid uniform value length: ${value.length}. Expected ${uniform.length}.`);\n\t\t\t}\n\t\t\t(this.gl as any)[`uniform${uniform.length}${uniform.type.charAt(0)}`](uniform.location, ...value);\n\t\t});\n\t}\n\n\tstep(time: number) {\n\t\tconst gl = this.gl;\n\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\tif (this.historyLength > 0) {\n\t\t\tconst writeIdx = this.frame % this.historyLength;\n\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\n\t\t\tgl.bindTexture(gl.TEXTURE_2D_ARRAY, this.historyTexture);\n\t\t\tgl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, writeIdx, 0, 0, this.canvas.width, this.canvas.height);\n\t\t} else {\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t\t}\n\n\t\t++this.frame;\n\t}\n\n\tplay(callback?: (time: number, frame: number) => void) {\n\t\tconst loop = (time: number) => {\n\t\t\ttime /= 1000; // Convert from milliseconds to seconds.\n\t\t\tthis.step(time);\n\t\t\tif (callback) callback(time, this.frame);\n\t\t\tthis.animationFrameId = requestAnimationFrame(loop);\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\tsave(filename: string) {\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\t\tthis.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\n\t\tconst image = this.canvas.toDataURL();\n\t\tif (filename && !`${filename}`.toLowerCase().endsWith('.png')) {\n\t\t\tfilename = `${filename}.png`;\n\t\t}\n\t\tthis.downloadLink.download = filename || 'export.png';\n\t\tthis.downloadLink.href = image;\n\t\tthis.downloadLink.click();\n\t}\n\n\tinitializeTexture(name: string, source: HTMLImageElement | HTMLVideoElement) {\n\t\tif (this.textures.has(name)) {\n\t\t\tthrow new Error(`Texture '${name}' is already initialized.`);\n\t\t}\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\t\tconst unitIndex = this.textures.size;\n\t\tthis.gl.activeTexture(this.gl.TEXTURE0 + unitIndex);\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\n\t\t// Flip the texture vertically since v_uv is flipped, and set up filters and wrapping.\n\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n\t\tthis.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n\t\tthis.textures.set(name, { texture, unitIndex });\n\t\tthis.updateTextures({ [name]: source });\n\n\t\tconst uSampler = this.gl.getUniformLocation(this.program!, name);\n\t\tif (uSampler) {\n\t\t\tthis.gl.uniform1i(uSampler, unitIndex);\n\t\t}\n\t}\n\n\tupdateTextures(updates: Record<string, HTMLImageElement | HTMLVideoElement>) {\n\t\tObject.entries(updates).forEach(([name, source]) => {\n\t\t\tconst info = this.textures.get(name);\n\t\t\tif (!info) {\n\t\t\t\tthrow new Error(`Texture '${name}' is not initialized.`);\n\t\t\t}\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\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.resizeObserver.unobserve(this.canvas);\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\n\t\tif (this.historyTexture) {\n\t\t\tthis.gl.deleteTexture(this.historyTexture);\n\t\t\tthis.historyTexture = null;\n\t\t}\n\n\t\tif (this.buffer) {\n\t\t\tthis.gl.deleteBuffer(this.buffer);\n\t\t\tthis.buffer = null;\n\t\t}\n\n\t\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","ShaderPad","fragmentShaderSrc","options","vertexShaderSrc","vertexShader","fragmentShader","aPosition","gl","type","source","shader","quadVertices","now","timeUntilNextResize","pixelRatio","width","height","computedStyle","hasExplicitWidth","hasExplicitHeight","updateCursor","x","y","rect","updateClick","isMouseDown","xVal","yVal","event","mouseEvent","wheelEvent","touchEvent","listener","name","value","location","length","updates","uniform","time","writeIdx","callback","loop","filename","image","texture","unitIndex","uSampler","info","index_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shaderpad",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.7",
4
4
  "description": "A lightweight, dependency-free library to reduce boilerplate when writing fragment shaders.",
5
5
  "keywords": [
6
6
  "shaders",