shaderpad 1.0.0-alpha.4 → 1.0.0-alpha.6

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
@@ -18,25 +18,25 @@ const fragmentShaderSrc = `
18
18
  precision highp float;
19
19
 
20
20
  // Built-in variables.
21
- varying vec2 vUv;
22
- uniform float uTime;
23
- uniform vec2 uResolution;
24
- uniform vec2 uCursor;
21
+ varying vec2 v_uv;
22
+ uniform float u_time;
23
+ uniform vec2 u_resolution;
24
+ uniform vec4 u_cursor; // [cursorX, cursorY, scrollX, scrollY]
25
25
 
26
26
  // Custom variables.
27
- uniform vec3 uCursorColor;
27
+ uniform vec3 u_cursorColor;
28
28
 
29
29
  void main() {
30
- vec2 uv = vUv * uResolution;
30
+ vec2 uv = v_uv * u_resolution;
31
31
  vec2 dotGrid = mod(uv, 50.) - 25.;
32
32
  float dotDist = length(dotGrid);
33
33
  float dot = step(dotDist, 5.);
34
34
 
35
- float cursorDist = distance(uv, uCursor * uResolution);
36
- float cursor = step(cursorDist, 25. + sin(uTime * 5.) * 5.);
35
+ float cursorDist = distance(uv, u_cursor.xy * u_resolution);
36
+ float cursor = step(cursorDist, 25. + sin(u_time * 5.) * 5.);
37
37
 
38
38
  vec3 color = mix(vec3(0., 0., 1.), vec3(1.), dot);
39
- color = mix(color, uCursorColor, cursor);
39
+ color = mix(color, u_cursorColor, cursor);
40
40
 
41
41
  gl_FragColor = vec4(color, 1.);
42
42
  }
@@ -48,11 +48,11 @@ const shader = new ShaderPad(fragmentShaderSrc /* , canvasElement */);
48
48
  // Add your own custom uniforms.
49
49
  const getColor = (time: number) =>
50
50
  [time, time + (Math.PI * 2) / 3, time + (Math.PI * 4) / 3].map(x => 1 + Math.sin(x) / 2);
51
- shader.initializeUniform('uCursorColor', 'float', getColor(0));
51
+ shader.initializeUniform('u_cursorColor', 'float', getColor(0));
52
52
 
53
53
  // Start the render loop.
54
54
  shader.play(time => {
55
- shader.updateUniforms({ uCursorColor: getColor(time) });
55
+ shader.updateUniforms({ u_cursorColor: getColor(time) });
56
56
  });
57
57
 
58
58
  // Optionally pause the render loop.
@@ -63,13 +63,45 @@ See the [`examples/` directory](./examples/) for more.
63
63
 
64
64
  ## Included uniforms
65
65
 
66
- | Uniform | Type | Description |
67
- | ------------- | -------- | ----------------------------------- |
68
- | `uUv` | float[2] | The UV coordinates of the fragment. |
69
- | `uTime` | float | The current time in seconds. |
70
- | `uFrame` | int | The current frame number. |
71
- | `uResolution` | float[2] | The canvas element’s dimensions. |
72
- | `uCursor` | float[2] | The current mouse/cursor position. |
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). |
73
+
74
+ ## Included varyings
75
+
76
+ | Varying | Type | Description |
77
+ | ------- | -------- | ----------------------------------- |
78
+ | `v_uv` | float[2] | The UV coordinates of the fragment. |
79
+
80
+ ## Contributing
81
+
82
+ ### Running an example
83
+
84
+ ```bash
85
+ # Clone the repository.
86
+ git clone https://github.com/your-username/shaderpad.git
87
+ cd shaderpad
88
+
89
+ # Install dependencies and start the development server.
90
+ cd examples
91
+ npm install
92
+ npm run dev
93
+ ```
94
+
95
+ This will launch a local server (powered by Vite). Open the provided URL (usually `http://localhost:5173`) in your browser to view and interact with the examples.
96
+
97
+ `examples/index.html` hardcodes the `main.ts` example. To view a different example, change `<script type="module" src="/src/main.ts"></script>` to point to your new example.
98
+
99
+ ### Adding an example
100
+
101
+ - Add a new `.ts` file in `examples/src/`.
102
+ - Follow the structure of an existing example as a template.
103
+ - Change `<script type="module" src="/src/main.ts"></script>` in `examples/index.html` to point to your new example.
104
+ - If your example needs images or other assets, place them in `examples/public/` and reference them with a relative path.
73
105
 
74
106
  ## License
75
107
 
package/dist/index.d.mts CHANGED
@@ -13,6 +13,11 @@ declare class ShaderPad {
13
13
  private resizeObserver;
14
14
  private eventListeners;
15
15
  private frame;
16
+ private cursorPosition;
17
+ private scrollX;
18
+ private scrollY;
19
+ private clickPosition;
20
+ private isMouseDown;
16
21
  constructor(fragmentShaderSrc: string, canvas?: HTMLCanvasElement | null);
17
22
  private init;
18
23
  private createShader;
package/dist/index.d.ts CHANGED
@@ -13,6 +13,11 @@ declare class ShaderPad {
13
13
  private resizeObserver;
14
14
  private eventListeners;
15
15
  private frame;
16
+ private cursorPosition;
17
+ private scrollX;
18
+ private scrollY;
19
+ private clickPosition;
20
+ private isMouseDown;
16
21
  constructor(fragmentShaderSrc: string, canvas?: HTMLCanvasElement | null);
17
22
  private init;
18
23
  private createShader;
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- "use strict";var h=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var u=(s,t)=>{for(var e in t)h(s,e,{get:t[e],enumerable:!0})},d=(s,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of g(t))!c.call(s,r)&&r!==e&&h(s,r,{get:()=>t[r],enumerable:!(i=l(t,r))||i.enumerable});return s};var m=s=>d(h({},"__esModule",{value:!0}),s);var p={};u(p,{default:()=>v});module.exports=m(p);var f=`
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
2
  attribute vec2 aPosition;
3
- varying vec2 vUv;
3
+ varying vec2 v_uv;
4
4
  void main() {
5
- vUv = aPosition * 0.5 + 0.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(t,e=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.canvas=e||document.createElement("canvas"),e||(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=t,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.resizeCanvas()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let t=f;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 r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.resizeCanvas(),this.gl.useProgram(this.program),this.initializeUniform("uResolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("uCursor","float",[.5,.5]),this.initializeUniform("uTime","float",0),this.initializeUniform("uFrame","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)}resizeCanvas(){let t=window.devicePixelRatio||1,e=this.canvas.clientWidth*t,i=this.canvas.clientHeight*t,r=getComputedStyle(this.canvas),n=r.width!==`${this.canvas.width}px`&&r.width!=="auto",a=r.height!==`${this.canvas.height}px`&&r.height!=="auto";(!n||!a)&&(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("uResolution")&&this.updateUniforms({uResolution:[this.canvas.width,this.canvas.height]}))}addEventListeners(){let t=(e,i)=>{if(!this.uniforms.has("uCursor"))return;let r=this.canvas.getBoundingClientRect(),n=(e-r.left)/r.width,a=1-(i-r.top)/r.height;this.updateUniforms({uCursor:[n,a]})};this.eventListeners.set("mousemove",e=>{let i=e;this.isTouchDevice||t(i.clientX,i.clientY)}),this.eventListeners.set("touchmove",e=>{let i=e;i.touches.length>0&&t(i.touches[0].clientX,i.touches[0].clientY)}),this.eventListeners.set("touchstart",()=>{this.isTouchDevice=!0}),this.eventListeners.forEach((e,i)=>{this.canvas.addEventListener(i,e)})}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 r=this.gl.getUniformLocation(this.program,t);if(!r){console.log(`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 n=i.length;this.uniforms.set(t,{type:e,length:n,location:r}),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 r=this.uniforms.get(e);if(Array.isArray(i)||(i=[i]),i.length!==r.length)throw new Error(`Invalid uniform value length: ${i.length}. Expected ${r.length}.`);this.gl[`uniform${r.length}${r.type.charAt(0)}`](r.location,...i)})}step(t){t/=1e3,this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.uniforms.has("uTime")&&this.updateUniforms({uTime:t}),this.uniforms.has("uFrame")&&this.updateUniforms({uFrame:this.frame}),++this.frame,this.gl.drawArrays(this.gl.TRIANGLES,0,6)}play(t){let e=i=>{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 r=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+r),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:r}),this.updateTextures({[t]:e});let n=this.gl.getUniformLocation(this.program,t);n&&this.gl.uniform1i(n,r)}updateTextures(t){Object.entries(t).forEach(([e,i])=>{let r=this.textures.get(e);if(!r)throw new Error(`Texture '${e}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+r.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,r.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.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},v=o;
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;
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 vUv;\nvoid main() {\n vUv = 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\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('uResolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('uCursor', 'float', [0.5, 0.5]);\n\t\tthis.initializeUniform('uTime', 'float', 0);\n\t\tthis.initializeUniform('uFrame', '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('uResolution')) {\n\t\t\t\tthis.updateUniforms({ uResolution: [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('uCursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst cursorX = (x - rect.left) / rect.width;\n\t\t\tconst cursorY = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ uCursor: [cursorX, cursorY] });\n\t\t};\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\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\t\tthis.eventListeners.set('touchstart', () => {\n\t\t\tthis.isTouchDevice = true;\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.log(`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\ttime /= 1000; // Convert from milliseconds to seconds.\n\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tif (this.uniforms.has('uTime')) {\n\t\t\tthis.updateUniforms({ uTime: time });\n\t\t}\n\n\t\tif (this.uniforms.has('uFrame')) {\n\t\t\tthis.updateUniforms({ uFrame: 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\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 vUv 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","cursorX","cursorY","event","mouseEvent","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 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"]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- var h=`
1
+ var l=`
2
2
  attribute vec2 aPosition;
3
- varying vec2 vUv;
3
+ varying vec2 v_uv;
4
4
  void main() {
5
- vUv = aPosition * 0.5 + 0.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(i,e=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.canvas=e||document.createElement("canvas"),e||(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=i,this.animationFrameId=null,this.resizeObserver=new ResizeObserver(()=>this.resizeCanvas()),this.resizeObserver.observe(this.canvas),this.init(),this.addEventListeners()}init(){let i=h;if(this.program=this.gl.createProgram(),!this.program)throw new Error("Failed to create WebGL program");let e=this.createShader(this.gl.VERTEX_SHADER,i),t=this.createShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSrc);if(this.gl.attachShader(this.program,e),this.gl.attachShader(this.program,t),this.gl.linkProgram(this.program),this.gl.deleteShader(e),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 r=this.gl.getAttribLocation(this.program,"aPosition");this.setupBuffer(r),this.resizeCanvas(),this.gl.useProgram(this.program),this.initializeUniform("uResolution","float",[this.canvas.width,this.canvas.height]),this.initializeUniform("uCursor","float",[.5,.5]),this.initializeUniform("uTime","float",0),this.initializeUniform("uFrame","int",0)}createShader(i,e){let t=this.gl.createShader(i);if(this.gl.shaderSource(t,e),this.gl.compileShader(t),!this.gl.getShaderParameter(t,this.gl.COMPILE_STATUS))throw console.error("Shader compilation failed:",e),console.error(this.gl.getShaderInfoLog(t)),this.gl.deleteShader(t),new Error("Shader compilation failed");return t}setupBuffer(i){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(i),this.gl.vertexAttribPointer(i,2,this.gl.FLOAT,!1,0,0)}resizeCanvas(){let i=window.devicePixelRatio||1,e=this.canvas.clientWidth*i,t=this.canvas.clientHeight*i,r=getComputedStyle(this.canvas),s=r.width!==`${this.canvas.width}px`&&r.width!=="auto",n=r.height!==`${this.canvas.height}px`&&r.height!=="auto";(!s||!n)&&(this.canvas.style.width=`${this.canvas.clientWidth}px`,this.canvas.style.height=`${this.canvas.clientHeight}px`),(this.canvas.width!==e||this.canvas.height!==t)&&(this.canvas.width=e,this.canvas.height=t,this.gl.viewport(0,0,this.gl.drawingBufferWidth,this.gl.drawingBufferHeight),this.uniforms.has("uResolution")&&this.updateUniforms({uResolution:[this.canvas.width,this.canvas.height]}))}addEventListeners(){let i=(e,t)=>{if(!this.uniforms.has("uCursor"))return;let r=this.canvas.getBoundingClientRect(),s=(e-r.left)/r.width,n=1-(t-r.top)/r.height;this.updateUniforms({uCursor:[s,n]})};this.eventListeners.set("mousemove",e=>{let t=e;this.isTouchDevice||i(t.clientX,t.clientY)}),this.eventListeners.set("touchmove",e=>{let t=e;t.touches.length>0&&i(t.touches[0].clientX,t.touches[0].clientY)}),this.eventListeners.set("touchstart",()=>{this.isTouchDevice=!0}),this.eventListeners.forEach((e,t)=>{this.canvas.addEventListener(t,e)})}initializeUniform(i,e,t){if(this.uniforms.has(i))throw new Error(`Uniform '${i}' is already initialized.`);if(e!=="float"&&e!=="int")throw new Error(`Invalid uniform type: ${e}. Expected 'float' or 'int'.`);let r=this.gl.getUniformLocation(this.program,i);if(!r){console.log(`Uniform ${i} 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 s=t.length;this.uniforms.set(i,{type:e,length:s,location:r}),this.updateUniforms({[i]:t})}updateUniforms(i){Object.entries(i).forEach(([e,t])=>{if(!this.uniforms.has(e))throw new Error(`Uniform '${e}' is not initialized.`);let r=this.uniforms.get(e);if(Array.isArray(t)||(t=[t]),t.length!==r.length)throw new Error(`Invalid uniform value length: ${t.length}. Expected ${r.length}.`);this.gl[`uniform${r.length}${r.type.charAt(0)}`](r.location,...t)})}step(i){i/=1e3,this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.uniforms.has("uTime")&&this.updateUniforms({uTime:i}),this.uniforms.has("uFrame")&&this.updateUniforms({uFrame:this.frame}),++this.frame,this.gl.drawArrays(this.gl.TRIANGLES,0,6)}play(i){let e=t=>{this.step(t),i&&i(t,this.frame),this.animationFrameId=requestAnimationFrame(e)};this.animationFrameId=requestAnimationFrame(e)}pause(){this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}save(i){this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.drawArrays(this.gl.TRIANGLES,0,6);let e=this.canvas.toDataURL();i&&!`${i}`.toLowerCase().endsWith(".png")&&(i=`${i}.png`),this.downloadLink.download=i||"export.png",this.downloadLink.href=e,this.downloadLink.click()}initializeTexture(i,e){if(this.textures.has(i))throw new Error(`Texture '${i}' is already initialized.`);let t=this.gl.createTexture();if(!t)throw new Error("Failed to create texture");let r=this.textures.size;this.gl.activeTexture(this.gl.TEXTURE0+r),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(i,{texture:t,unitIndex:r}),this.updateTextures({[i]:e});let s=this.gl.getUniformLocation(this.program,i);s&&this.gl.uniform1i(s,r)}updateTextures(i){Object.entries(i).forEach(([e,t])=>{let r=this.textures.get(e);if(!r)throw new Error(`Texture '${e}' is not initialized.`);this.gl.activeTexture(this.gl.TEXTURE0+r.unitIndex),this.gl.bindTexture(this.gl.TEXTURE_2D,r.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((i,e)=>{this.canvas.removeEventListener(e,i)}),this.program&&this.gl.deleteProgram(this.program),this.textures.forEach(i=>{this.gl.deleteTexture(i.texture)}),this.buffer&&(this.gl.deleteBuffer(this.buffer),this.buffer=null),this.isInternalCanvas&&this.canvas.remove()}},l=a;export{l as default};
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};
9
9
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["const defaultVertexShaderSrc = `\nattribute vec2 aPosition;\nvarying vec2 vUv;\nvoid main() {\n vUv = 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\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('uResolution', 'float', [this.canvas.width, this.canvas.height]);\n\t\tthis.initializeUniform('uCursor', 'float', [0.5, 0.5]);\n\t\tthis.initializeUniform('uTime', 'float', 0);\n\t\tthis.initializeUniform('uFrame', '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('uResolution')) {\n\t\t\t\tthis.updateUniforms({ uResolution: [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('uCursor')) return;\n\t\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\t\tconst cursorX = (x - rect.left) / rect.width;\n\t\t\tconst cursorY = 1 - (y - rect.top) / rect.height; // Flip Y for WebGL\n\t\t\tthis.updateUniforms({ uCursor: [cursorX, cursorY] });\n\t\t};\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\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\t\tthis.eventListeners.set('touchstart', () => {\n\t\t\tthis.isTouchDevice = true;\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.log(`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\ttime /= 1000; // Convert from milliseconds to seconds.\n\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tif (this.uniforms.has('uTime')) {\n\t\t\tthis.updateUniforms({ uTime: time });\n\t\t}\n\n\t\tif (this.uniforms.has('uFrame')) {\n\t\t\tthis.updateUniforms({ uFrame: 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\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 vUv 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","cursorX","cursorY","event","mouseEvent","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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shaderpad",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.6",
4
4
  "description": "A lightweight, dependency-free library to reduce boilerplate when writing fragment shaders.",
5
5
  "keywords": [
6
6
  "shaders",