@paper-design/shaders 0.0.0-canary.55a3ef1 → 0.0.0-canary.5bfd3e7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/html-in-canvas.d.ts +35 -0
- package/dist/html-in-canvas.js +79 -0
- package/dist/html-in-canvas.js.map +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +2 -2
- package/dist/shader-mount.d.ts +12 -1
- package/dist/shader-mount.js +119 -25
- package/dist/shader-mount.js.map +2 -2
- package/dist/shaders/fluted-glass.d.ts +7 -4
- package/dist/shaders/fluted-glass.js +23 -23
- package/dist/shaders/fluted-glass.js.map +2 -2
- package/dist/shaders/halftone-cmyk.d.ts +7 -4
- package/dist/shaders/halftone-cmyk.js +35 -11
- package/dist/shaders/halftone-cmyk.js.map +2 -2
- package/dist/shaders/halftone-dots.d.ts +7 -4
- package/dist/shaders/halftone-dots.js +32 -8
- package/dist/shaders/halftone-dots.js.map +2 -2
- package/dist/shaders/image-dithering.d.ts +6 -4
- package/dist/shaders/image-dithering.js +37 -27
- package/dist/shaders/image-dithering.js.map +2 -2
- package/dist/shaders/lens-distortion.d.ts +5 -2
- package/dist/shaders/lens-distortion.js +26 -12
- package/dist/shaders/lens-distortion.js.map +2 -2
- package/dist/shaders/paper-texture.d.ts +49 -45
- package/dist/shaders/paper-texture.js +64 -41
- package/dist/shaders/paper-texture.js.map +2 -2
- package/dist/shaders/water.d.ts +8 -4
- package/dist/shaders/water.js +19 -6
- package/dist/shaders/water.js.map +2 -2
- package/dist/vertex-shader.d.ts +1 -1
- package/dist/vertex-shader.js +21 -18
- package/dist/vertex-shader.js.map +2 -2
- package/package.json +1 -1
- package/dist/shaders/paper-texture---.d.ts +0 -11
- package/dist/shaders/paper-texture---.js +0 -509
- package/dist/shaders/paper-texture---.js.map +0 -7
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Experimental HTML-in-canvas support (https://github.com/WICG/html-in-canvas),
|
|
3
|
+
* available in Chromium behind `chrome://flags/#canvas-draw-element`. Older Chromium versions opt the canvas in with
|
|
4
|
+
* `layoutsubtree` instead of `content="drawable"`, so the canvas gets both.
|
|
5
|
+
*
|
|
6
|
+
* An HTML element passed as a texture uniform is moved into the shader canvas and drawn 1:1 where it's laid out:
|
|
7
|
+
*
|
|
8
|
+
* <div data-paper-shader>
|
|
9
|
+
* <canvas content="drawable" layoutsubtree>
|
|
10
|
+
* <div drawable>…</div>
|
|
11
|
+
* </canvas>
|
|
12
|
+
* </div>
|
|
13
|
+
*
|
|
14
|
+
* React renders this markup itself, since it can't let its nodes be moved, and the shader adopts that canvas.
|
|
15
|
+
*
|
|
16
|
+
* The HTML texture always matches the canvas size, so shaders sample it like any canvas-sized texture: a resize
|
|
17
|
+
* captures the HTML again right away instead of waiting for the next paint.
|
|
18
|
+
*/
|
|
19
|
+
export interface DrawableCanvasElement extends HTMLCanvasElement {
|
|
20
|
+
requestPaint(): void;
|
|
21
|
+
updateElementGeometry(element: Element, options?: {
|
|
22
|
+
canvasTransform?: DOMMatrixInit;
|
|
23
|
+
}): void;
|
|
24
|
+
}
|
|
25
|
+
export declare function isHtmlInCanvasSupported(): boolean;
|
|
26
|
+
/** `<img>` stays a static image uniform. nodeType instead of `instanceof` works across iframes */
|
|
27
|
+
export declare function isHtmlUniform(value: unknown): value is HTMLElement;
|
|
28
|
+
export declare function findReactCanvas(values: unknown[], parentElement: Element): DrawableCanvasElement | null;
|
|
29
|
+
/** Moves the element into the canvas, returns a function that puts it back */
|
|
30
|
+
export declare function attachHtml(canvas: DrawableCanvasElement, element: HTMLElement): () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Captures the element into the bound texture, sized to the canvas drawing buffer. The texture is only reallocated
|
|
33
|
+
* (and so cleared) when its size or the drawn area changes; returns that layout to pass back in next time
|
|
34
|
+
*/
|
|
35
|
+
export declare function drawHtml(gl: WebGL2RenderingContext, canvas: DrawableCanvasElement, element: HTMLElement, lastLayout?: string): string;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
2
|
+
* Paper Shaders *
|
|
3
|
+
* https://github.com/paper-design/shaders *
|
|
4
|
+
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
|
+
|
|
6
|
+
function isHtmlInCanvasSupported() {
|
|
7
|
+
return typeof HTMLCanvasElement !== "undefined" && "requestPaint" in HTMLCanvasElement.prototype && typeof WebGL2RenderingContext !== "undefined" && "texElementSubImage2D" in WebGL2RenderingContext.prototype;
|
|
8
|
+
}
|
|
9
|
+
function isHtmlUniform(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && value.nodeType === 1 && value.tagName !== "IMG";
|
|
11
|
+
}
|
|
12
|
+
function findReactCanvas(values, parentElement) {
|
|
13
|
+
for (const value of values) {
|
|
14
|
+
const canvas = isHtmlUniform(value) ? value.parentElement : null;
|
|
15
|
+
if (canvas?.tagName === "CANVAS" && canvas.parentElement === parentElement) {
|
|
16
|
+
return canvas;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
function attachHtml(canvas, element) {
|
|
22
|
+
if (element.parentElement === canvas) {
|
|
23
|
+
return () => {
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const parent = element.parentNode;
|
|
27
|
+
const nextSibling = element.nextSibling;
|
|
28
|
+
canvas.setAttribute("content", "drawable");
|
|
29
|
+
canvas.setAttribute("layoutsubtree", "");
|
|
30
|
+
element.setAttribute("drawable", "");
|
|
31
|
+
canvas.append(element);
|
|
32
|
+
return () => {
|
|
33
|
+
element.removeAttribute("drawable");
|
|
34
|
+
if (parent) {
|
|
35
|
+
parent.insertBefore(element, nextSibling?.parentNode === parent ? nextSibling : null);
|
|
36
|
+
} else {
|
|
37
|
+
element.remove();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function drawHtml(gl, canvas, element, lastLayout) {
|
|
42
|
+
const width = Math.max(1, canvas.width);
|
|
43
|
+
const height = Math.max(1, canvas.height);
|
|
44
|
+
const scaleX = width / Math.max(1, canvas.clientWidth);
|
|
45
|
+
const scaleY = height / Math.max(1, canvas.clientHeight);
|
|
46
|
+
const left = element.offsetLeft;
|
|
47
|
+
const top = element.offsetTop;
|
|
48
|
+
const visibleLeft = Math.max(0, left);
|
|
49
|
+
const visibleTop = Math.max(0, top);
|
|
50
|
+
const visibleRight = Math.min(canvas.clientWidth, left + element.offsetWidth);
|
|
51
|
+
const visibleBottom = Math.min(canvas.clientHeight, top + element.offsetHeight);
|
|
52
|
+
const x0 = Math.round(visibleLeft * scaleX);
|
|
53
|
+
const y0 = Math.round(visibleTop * scaleY);
|
|
54
|
+
const x1 = Math.min(width, Math.round(visibleRight * scaleX));
|
|
55
|
+
const y1 = Math.min(height, Math.round(visibleBottom * scaleY));
|
|
56
|
+
const layout = `${width}x${height} ${x0},${y0},${x1},${y1}`;
|
|
57
|
+
if (layout !== lastLayout) {
|
|
58
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
59
|
+
}
|
|
60
|
+
if (x1 > x0 && y1 > y0) {
|
|
61
|
+
gl.texElementSubImage2D(gl.TEXTURE_2D, 0, x0, y0, element, {
|
|
62
|
+
sx: visibleLeft - left,
|
|
63
|
+
sy: visibleTop - top,
|
|
64
|
+
swidth: visibleRight - visibleLeft,
|
|
65
|
+
sheight: visibleBottom - visibleTop,
|
|
66
|
+
width: x1 - x0,
|
|
67
|
+
height: y1 - y0
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return layout;
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
attachHtml,
|
|
74
|
+
drawHtml,
|
|
75
|
+
findReactCanvas,
|
|
76
|
+
isHtmlInCanvasSupported,
|
|
77
|
+
isHtmlUniform
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=html-in-canvas.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/html-in-canvas.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Experimental HTML-in-canvas support (https://github.com/WICG/html-in-canvas),\n * available in Chromium behind `chrome://flags/#canvas-draw-element`. Older Chromium versions opt the canvas in with\n * `layoutsubtree` instead of `content=\"drawable\"`, so the canvas gets both.\n *\n * An HTML element passed as a texture uniform is moved into the shader canvas and drawn 1:1 where it's laid out:\n *\n * <div data-paper-shader>\n * <canvas content=\"drawable\" layoutsubtree>\n * <div drawable>\u2026</div>\n * </canvas>\n * </div>\n *\n * React renders this markup itself, since it can't let its nodes be moved, and the shader adopts that canvas.\n *\n * The HTML texture always matches the canvas size, so shaders sample it like any canvas-sized texture: a resize\n * captures the HTML again right away instead of waiting for the next paint.\n */\n\nexport interface DrawableCanvasElement extends HTMLCanvasElement {\n requestPaint(): void;\n updateElementGeometry(element: Element, options?: { canvasTransform?: DOMMatrixInit }): void;\n}\n\ninterface DrawableCanvasWebGL2Context extends WebGL2RenderingContext {\n texElementSubImage2D(\n target: GLenum,\n level: GLint,\n xoffset: GLint,\n yoffset: GLint,\n element: Element,\n config?: { width?: number; height?: number; sx?: number; sy?: number; swidth?: number; sheight?: number }\n ): void;\n}\n\nexport function isHtmlInCanvasSupported(): boolean {\n return (\n typeof HTMLCanvasElement !== 'undefined' &&\n 'requestPaint' in HTMLCanvasElement.prototype &&\n typeof WebGL2RenderingContext !== 'undefined' &&\n 'texElementSubImage2D' in WebGL2RenderingContext.prototype\n );\n}\n\n/** `<img>` stays a static image uniform. nodeType instead of `instanceof` works across iframes */\nexport function isHtmlUniform(value: unknown): value is HTMLElement {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as Node).nodeType === 1 &&\n (value as Element).tagName !== 'IMG'\n );\n}\n\nexport function findReactCanvas(values: unknown[], parentElement: Element): DrawableCanvasElement | null {\n for (const value of values) {\n const canvas = isHtmlUniform(value) ? value.parentElement : null;\n if (canvas?.tagName === 'CANVAS' && canvas.parentElement === parentElement) {\n return canvas as DrawableCanvasElement;\n }\n }\n return null;\n}\n\n/** Moves the element into the canvas, returns a function that puts it back */\nexport function attachHtml(canvas: DrawableCanvasElement, element: HTMLElement): () => void {\n if (element.parentElement === canvas) {\n return () => {};\n }\n\n const parent = element.parentNode;\n const nextSibling = element.nextSibling;\n canvas.setAttribute('content', 'drawable');\n canvas.setAttribute('layoutsubtree', '');\n element.setAttribute('drawable', '');\n canvas.append(element);\n\n return () => {\n element.removeAttribute('drawable');\n if (parent) {\n parent.insertBefore(element, nextSibling?.parentNode === parent ? nextSibling : null);\n } else {\n element.remove();\n }\n };\n}\n\n/**\n * Captures the element into the bound texture, sized to the canvas drawing buffer. The texture is only reallocated\n * (and so cleared) when its size or the drawn area changes; returns that layout to pass back in next time\n */\nexport function drawHtml(\n gl: WebGL2RenderingContext,\n canvas: DrawableCanvasElement,\n element: HTMLElement,\n lastLayout?: string\n): string {\n const width = Math.max(1, canvas.width);\n const height = Math.max(1, canvas.height);\n const scaleX = width / Math.max(1, canvas.clientWidth);\n const scaleY = height / Math.max(1, canvas.clientHeight);\n\n const left = element.offsetLeft;\n const top = element.offsetTop;\n const visibleLeft = Math.max(0, left);\n const visibleTop = Math.max(0, top);\n const visibleRight = Math.min(canvas.clientWidth, left + element.offsetWidth);\n const visibleBottom = Math.min(canvas.clientHeight, top + element.offsetHeight);\n const x0 = Math.round(visibleLeft * scaleX);\n const y0 = Math.round(visibleTop * scaleY);\n const x1 = Math.min(width, Math.round(visibleRight * scaleX));\n const y1 = Math.min(height, Math.round(visibleBottom * scaleY));\n\n const layout = `${width}x${height} ${x0},${y0},${x1},${y1}`;\n if (layout !== lastLayout) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n }\n\n if (x1 > x0 && y1 > y0) {\n (gl as DrawableCanvasWebGL2Context).texElementSubImage2D(gl.TEXTURE_2D, 0, x0, y0, element, {\n sx: visibleLeft - left,\n sy: visibleTop - top,\n swidth: visibleRight - visibleLeft,\n sheight: visibleBottom - visibleTop,\n width: x1 - x0,\n height: y1 - y0,\n });\n }\n\n return layout;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;AAmCO,SAAS,0BAAmC;AACjD,SACE,OAAO,sBAAsB,eAC7B,kBAAkB,kBAAkB,aACpC,OAAO,2BAA2B,eAClC,0BAA0B,uBAAuB;AAErD;AAGO,SAAS,cAAc,OAAsC;AAClE,SACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAe,aAAa,KAC5B,MAAkB,YAAY;AAEnC;AAEO,SAAS,gBAAgB,QAAmB,eAAsD;AACvG,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAAS,cAAc,KAAK,IAAI,MAAM,gBAAgB;AAC5D,QAAI,QAAQ,YAAY,YAAY,OAAO,kBAAkB,eAAe;AAC1E,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,WAAW,QAA+B,SAAkC;AAC1F,MAAI,QAAQ,kBAAkB,QAAQ;AACpC,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,QAAM,SAAS,QAAQ;AACvB,QAAM,cAAc,QAAQ;AAC5B,SAAO,aAAa,WAAW,UAAU;AACzC,SAAO,aAAa,iBAAiB,EAAE;AACvC,UAAQ,aAAa,YAAY,EAAE;AACnC,SAAO,OAAO,OAAO;AAErB,SAAO,MAAM;AACX,YAAQ,gBAAgB,UAAU;AAClC,QAAI,QAAQ;AACV,aAAO,aAAa,SAAS,aAAa,eAAe,SAAS,cAAc,IAAI;AAAA,IACtF,OAAO;AACL,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;AAMO,SAAS,SACd,IACA,QACA,SACA,YACQ;AACR,QAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,KAAK;AACtC,QAAM,SAAS,KAAK,IAAI,GAAG,OAAO,MAAM;AACxC,QAAM,SAAS,QAAQ,KAAK,IAAI,GAAG,OAAO,WAAW;AACrD,QAAM,SAAS,SAAS,KAAK,IAAI,GAAG,OAAO,YAAY;AAEvD,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAM,QAAQ;AACpB,QAAM,cAAc,KAAK,IAAI,GAAG,IAAI;AACpC,QAAM,aAAa,KAAK,IAAI,GAAG,GAAG;AAClC,QAAM,eAAe,KAAK,IAAI,OAAO,aAAa,OAAO,QAAQ,WAAW;AAC5E,QAAM,gBAAgB,KAAK,IAAI,OAAO,cAAc,MAAM,QAAQ,YAAY;AAC9E,QAAM,KAAK,KAAK,MAAM,cAAc,MAAM;AAC1C,QAAM,KAAK,KAAK,MAAM,aAAa,MAAM;AACzC,QAAM,KAAK,KAAK,IAAI,OAAO,KAAK,MAAM,eAAe,MAAM,CAAC;AAC5D,QAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,gBAAgB,MAAM,CAAC;AAE9D,QAAM,SAAS,GAAG,KAAK,IAAI,MAAM,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;AACzD,MAAI,WAAW,YAAY;AACzB,OAAG,WAAW,GAAG,YAAY,GAAG,GAAG,OAAO,OAAO,QAAQ,GAAG,GAAG,MAAM,GAAG,eAAe,IAAI;AAAA,EAC7F;AAEA,MAAI,KAAK,MAAM,KAAK,IAAI;AACtB,IAAC,GAAmC,qBAAqB,GAAG,YAAY,GAAG,IAAI,IAAI,SAAS;AAAA,MAC1F,IAAI,cAAc;AAAA,MAClB,IAAI,aAAa;AAAA,MACjB,QAAQ,eAAe;AAAA,MACvB,SAAS,gBAAgB;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** The core Shader Mount class. Pass it a parent element and a fragment shader to get started. */
|
|
2
2
|
export { ShaderMount, isPaperShaderElement } from './shader-mount.js';
|
|
3
|
+
export { isHtmlInCanvasSupported } from './html-in-canvas.js';
|
|
3
4
|
export type { PaperShaderElement, ShaderMotionParams, ShaderMountUniforms, ShaderPreset, ImageShaderPreset, } from './shader-mount.js';
|
|
4
5
|
/** Shader sizing options and uniforms */
|
|
5
6
|
export { defaultObjectSizing, defaultPatternSizing, ShaderFitOptions, type ShaderFit, type ShaderSizingParams, type ShaderSizingUniforms, } from './shader-sizing.js';
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
6
|
import { ShaderMount, isPaperShaderElement } from "./shader-mount.js";
|
|
7
|
+
import { isHtmlInCanvasSupported } from "./html-in-canvas.js";
|
|
7
8
|
import {
|
|
8
9
|
defaultObjectSizing,
|
|
9
10
|
defaultPatternSizing,
|
|
@@ -156,6 +157,7 @@ export {
|
|
|
156
157
|
heatmapFragmentShader,
|
|
157
158
|
heatmapMeta,
|
|
158
159
|
imageDitheringFragmentShader,
|
|
160
|
+
isHtmlInCanvasSupported,
|
|
159
161
|
isPaperShaderElement,
|
|
160
162
|
lensDistortionFragmentShader,
|
|
161
163
|
lensDistortionMeta,
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["/** The core Shader Mount class. Pass it a parent element and a fragment shader to get started. */\nexport { ShaderMount, isPaperShaderElement } from './shader-mount.js';\nexport type {\n PaperShaderElement,\n ShaderMotionParams,\n ShaderMountUniforms,\n ShaderPreset,\n ImageShaderPreset,\n} from './shader-mount.js';\n\n/** Shader sizing options and uniforms */\nexport {\n defaultObjectSizing,\n defaultPatternSizing,\n ShaderFitOptions,\n type ShaderFit,\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n} from './shader-sizing.js';\n\n/** A flowing interplay of color spots, moving along distinct trajectories and transformed by organic distortion */\nexport {\n meshGradientFragmentShader,\n meshGradientMeta,\n type MeshGradientParams,\n type MeshGradientUniforms,\n} from './shaders/mesh-gradient.js';\n\n/** Radial multi-colored gradient shaped with layered noise for a natural, smoky aesthetic */\nexport {\n smokeRingMeta,\n smokeRingFragmentShader,\n type SmokeRingParams,\n type SmokeRingUniforms,\n} from './shaders/smoke-ring.js';\n\n/** A glowing, web-like structure of fluid lines and soft intersections. Great for creating atmospheric, organic-yet-futuristic visuals */\nexport { neuroNoiseFragmentShader, type NeuroNoiseParams, type NeuroNoiseUniforms } from './shaders/neuro-noise.js';\n\n/** Animated multi-color dots pattern with each dot orbiting around its cell center. Supports up to 40 colors and various shape and motion controls. Great for playful, dynamic backgrounds and UI textures */\nexport {\n dotOrbitMeta,\n dotOrbitFragmentShader,\n type DotOrbitParams,\n type DotOrbitUniforms,\n} from './shaders/dot-orbit.js';\n\n/** Static grid pattern made of circles, diamonds, squares or triangles */\nexport {\n dotGridFragmentShader,\n DotGridShapes,\n type DotGridShape,\n type DotGridParams,\n type DotGridUniforms,\n} from './shaders/dot-grid.js';\n\n/** A multi-color gradient mapped into smooth, animated curves, delivering a sleek, futuristic visual */\nexport {\n simplexNoiseMeta,\n simplexNoiseFragmentShader,\n type SimplexNoiseParams,\n type SimplexNoiseUniforms,\n} from './shaders/simplex-noise.js';\n\n/** Up to 20 gooey blobs moving around the center and merging into smooth organic shapes */\nexport {\n metaballsMeta,\n metaballsFragmentShader,\n type MetaballsParams,\n type MetaballsUniforms,\n} from './shaders/metaballs.js';\n\n/** Animated 3D Perlin noise with exposed controls */\nexport { perlinNoiseFragmentShader, type PerlinNoiseParams, type PerlinNoiseUniforms } from './shaders/perlin-noise.js';\n\n/** Anti-aliased animated Voronoi pattern with smooth and customizable edges */\nexport { voronoiMeta, voronoiFragmentShader, type VoronoiParams, type VoronoiUniforms } from './shaders/voronoi.js';\n\n/** Static line pattern configurable into textures ranging from sharp zigzags to smooth flowing waves */\nexport { wavesFragmentShader, type WavesParams, type WavesUniforms } from './shaders/waves.js';\n\n/** Animated color fields warped by noise and swirls, applied over base patterns (checks, stripes, or split edge). Blends up to 10 colors with adjustable distribution, softness, distortion, and swirl. Great for fluid, smoky, or marbled effects */\nexport {\n warpMeta,\n warpFragmentShader,\n WarpPatterns,\n type WarpParams,\n type WarpUniforms,\n type WarpPattern,\n} from './shaders/warp.js';\n\n/** Animated rays of light radiating from the center, blended with up to 5 colors. The rays are adjustable by size, density, brightness and center glow. Great for dramatic backgrounds, logo reveals, and VFX like energy bursts or sun shafts */\nexport { godRaysMeta, godRaysFragmentShader, type GodRaysParams, type GodRaysUniforms } from './shaders/god-rays.js';\n\n/** A single-colored animated spiral that morphs across a wide range of shapes - from crisp, thin-lined geometry to flowing whirlpool forms and wavy, abstract rings */\nexport { spiralFragmentShader, type SpiralParams, type SpiralUniforms } from './shaders/spiral.js';\n\n/** Animated bands of color twisting and bending, producing spirals, arcs, and flowing circular patterns */\nexport { swirlMeta, swirlFragmentShader, type SwirlParams, type SwirlUniforms } from './shaders/swirl.js';\n\n/** Animated 2-color dithering over with multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere) */\nexport {\n ditheringFragmentShader,\n DitheringShapes,\n DitheringTypes,\n type DitheringParams,\n type DitheringUniforms,\n type DitheringShape,\n type DitheringType,\n} from './shaders/dithering.js';\n\n/** Multi-color gradients with grainy, noise-textured distortion available in 7 animated abstract forms */\nexport {\n grainGradientFragmentShader,\n grainGradientMeta,\n GrainGradientShapes,\n type GrainGradientParams,\n type GrainGradientUniforms,\n type GrainGradientShape,\n} from './shaders/grain-gradient.js';\n\n/** Luminous trails of color merging into a glowing gradient frame */\nexport {\n pulsingBorderMeta,\n pulsingBorderFragmentShader,\n PulsingBorderAspectRatios,\n type PulsingBorderParams,\n type PulsingBorderUniforms,\n type PulsingBorderAspectRatio,\n} from './shaders/pulsing-border.js';\n\n/** Glowing translucent 3D panels rotating around a central axis */\nexport {\n colorPanelsFragmentShader,\n colorPanelsMeta,\n type ColorPanelsParams,\n type ColorPanelsUniforms,\n} from './shaders/color-panels.js';\n\n/** Multi-point mesh gradients with up to 10 color spots, enhanced by two-direction warping, adjustable blend sharpness, and grain controls. Perfect for elegant wallpapers and atmospheric backdrops */\nexport {\n staticMeshGradientFragmentShader,\n staticMeshGradientMeta,\n type StaticMeshGradientParams,\n type StaticMeshGradientUniforms,\n} from './shaders/static-mesh-gradient.js';\n\n/** Radial gradient with up to 10 blended colors, featuring advanced focal point control, shape distortion, and grain effects */\nexport {\n staticRadialGradientFragmentShader,\n staticRadialGradientMeta,\n type StaticRadialGradientParams,\n type StaticRadialGradientUniforms,\n} from './shaders/static-radial-gradient.js';\n\n/** A static texture built from multiple noise layers, usable for a realistic paper and cardboard surfaces or generating abstract patterns. Can be used as a image filter or as a texture */\nexport {\n paperTextureFragmentShader,\n paperTextureMeta,\n type PaperTextureParams,\n type PaperTextureUniforms,\n} from './shaders/paper-texture.js';\n\n/** Water-like surface distortion with natural caustic realism. Works as an image filter or animated texture without image */\nexport { waterFragmentShader, type WaterParams, type WaterUniforms } from './shaders/water.js';\n\n/** Fluted glass image filter transforms an image into streaked, ribbed distortions, giving a mix of clarity and obscurity */\nexport {\n flutedGlassFragmentShader,\n GlassDistortionShapes,\n GlassGridShapes,\n type GlassDistortionShape,\n type GlassGridShape,\n type FlutedGlassParams,\n type FlutedGlassUniforms,\n} from './shaders/fluted-glass.js';\n\n/** A dithering image filter with support for 4 dithering modes and multiple color palettes (2-color, 3-color, and multicolor options, using either predefined colors or ones sampled directly from the original image) */\nexport {\n imageDitheringFragmentShader,\n type ImageDitheringParams,\n type ImageDitheringUniforms,\n} from './shaders/image-dithering.js';\n\n/** Lens Distortion image filter that separates an image into shifting color layers, recreating the chromatic aberration of a lens, and warps the image geometry with barrel or pincushion curvature */\nexport {\n lensDistortionFragmentShader,\n lensDistortionMeta,\n type LensDistortionParams,\n type LensDistortionUniforms,\n} from './shaders/lens-distortion.js';\n\n/** A glowing gradient of colors flowing through an input image. The effect creates a smoothly animated wave of intensity across the image */\nexport {\n heatmapMeta,\n heatmapFragmentShader,\n toProcessedHeatmap,\n type HeatmapParams,\n type HeatmapUniforms,\n} from './shaders/heatmap.js';\n\n/** Futuristic liquid metal material applied to uploaded logo or one of pre-defined abstract shape */\nexport {\n liquidMetalFragmentShader,\n LiquidMetalShapes,\n toProcessedLiquidMetal,\n type LiquidMetalShape,\n type LiquidMetalParams,\n type LiquidMetalUniforms,\n} from './shaders/liquid-metal.js';\n\n/** A halftone-dot image filter featuring customizable grids, color palettes, and dot styles */\nexport {\n HalftoneDotsTypes,\n HalftoneDotsGrids,\n halftoneDotsFragmentShader,\n type HalftoneDotsParams,\n type HalftoneDotsUniforms,\n type HalftoneDotsType,\n type HalftoneDotsGrid,\n} from './shaders/halftone-dots.js';\n\n/** A halftone CMYK classic algo */\nexport {\n HalftoneCmykTypes,\n halftoneCmykFragmentShader,\n type HalftoneCmykParams,\n type HalftoneCmykUniforms,\n type HalftoneCmykType,\n} from './shaders/halftone-cmyk.js';\n\n/** Animated color fields running around a glassy logo shape */\nexport {\n gemSmokeMeta,\n gemSmokeFragmentShader,\n toProcessedGemSmoke,\n GemSmokeShapes,\n type GemSmokeShape,\n type GemSmokeParams,\n type GemSmokeUniforms,\n} from './shaders/gem-smoke.js';\n\n// ----- Utils ----- //\nexport { getShaderColorFromString } from './get-shader-color-from-string.js';\nexport { getShaderNoiseTexture } from './get-shader-noise-texture.js';\nexport { emptyPixel } from './empty-pixel.js';\n"],
|
|
5
|
-
"mappings": ";;;;;AACA,SAAS,aAAa,4BAA4B;
|
|
4
|
+
"sourcesContent": ["/** The core Shader Mount class. Pass it a parent element and a fragment shader to get started. */\nexport { ShaderMount, isPaperShaderElement } from './shader-mount.js';\nexport { isHtmlInCanvasSupported } from './html-in-canvas.js';\nexport type {\n PaperShaderElement,\n ShaderMotionParams,\n ShaderMountUniforms,\n ShaderPreset,\n ImageShaderPreset,\n} from './shader-mount.js';\n\n/** Shader sizing options and uniforms */\nexport {\n defaultObjectSizing,\n defaultPatternSizing,\n ShaderFitOptions,\n type ShaderFit,\n type ShaderSizingParams,\n type ShaderSizingUniforms,\n} from './shader-sizing.js';\n\n/** A flowing interplay of color spots, moving along distinct trajectories and transformed by organic distortion */\nexport {\n meshGradientFragmentShader,\n meshGradientMeta,\n type MeshGradientParams,\n type MeshGradientUniforms,\n} from './shaders/mesh-gradient.js';\n\n/** Radial multi-colored gradient shaped with layered noise for a natural, smoky aesthetic */\nexport {\n smokeRingMeta,\n smokeRingFragmentShader,\n type SmokeRingParams,\n type SmokeRingUniforms,\n} from './shaders/smoke-ring.js';\n\n/** A glowing, web-like structure of fluid lines and soft intersections. Great for creating atmospheric, organic-yet-futuristic visuals */\nexport { neuroNoiseFragmentShader, type NeuroNoiseParams, type NeuroNoiseUniforms } from './shaders/neuro-noise.js';\n\n/** Animated multi-color dots pattern with each dot orbiting around its cell center. Supports up to 40 colors and various shape and motion controls. Great for playful, dynamic backgrounds and UI textures */\nexport {\n dotOrbitMeta,\n dotOrbitFragmentShader,\n type DotOrbitParams,\n type DotOrbitUniforms,\n} from './shaders/dot-orbit.js';\n\n/** Static grid pattern made of circles, diamonds, squares or triangles */\nexport {\n dotGridFragmentShader,\n DotGridShapes,\n type DotGridShape,\n type DotGridParams,\n type DotGridUniforms,\n} from './shaders/dot-grid.js';\n\n/** A multi-color gradient mapped into smooth, animated curves, delivering a sleek, futuristic visual */\nexport {\n simplexNoiseMeta,\n simplexNoiseFragmentShader,\n type SimplexNoiseParams,\n type SimplexNoiseUniforms,\n} from './shaders/simplex-noise.js';\n\n/** Up to 20 gooey blobs moving around the center and merging into smooth organic shapes */\nexport {\n metaballsMeta,\n metaballsFragmentShader,\n type MetaballsParams,\n type MetaballsUniforms,\n} from './shaders/metaballs.js';\n\n/** Animated 3D Perlin noise with exposed controls */\nexport { perlinNoiseFragmentShader, type PerlinNoiseParams, type PerlinNoiseUniforms } from './shaders/perlin-noise.js';\n\n/** Anti-aliased animated Voronoi pattern with smooth and customizable edges */\nexport { voronoiMeta, voronoiFragmentShader, type VoronoiParams, type VoronoiUniforms } from './shaders/voronoi.js';\n\n/** Static line pattern configurable into textures ranging from sharp zigzags to smooth flowing waves */\nexport { wavesFragmentShader, type WavesParams, type WavesUniforms } from './shaders/waves.js';\n\n/** Animated color fields warped by noise and swirls, applied over base patterns (checks, stripes, or split edge). Blends up to 10 colors with adjustable distribution, softness, distortion, and swirl. Great for fluid, smoky, or marbled effects */\nexport {\n warpMeta,\n warpFragmentShader,\n WarpPatterns,\n type WarpParams,\n type WarpUniforms,\n type WarpPattern,\n} from './shaders/warp.js';\n\n/** Animated rays of light radiating from the center, blended with up to 5 colors. The rays are adjustable by size, density, brightness and center glow. Great for dramatic backgrounds, logo reveals, and VFX like energy bursts or sun shafts */\nexport { godRaysMeta, godRaysFragmentShader, type GodRaysParams, type GodRaysUniforms } from './shaders/god-rays.js';\n\n/** A single-colored animated spiral that morphs across a wide range of shapes - from crisp, thin-lined geometry to flowing whirlpool forms and wavy, abstract rings */\nexport { spiralFragmentShader, type SpiralParams, type SpiralUniforms } from './shaders/spiral.js';\n\n/** Animated bands of color twisting and bending, producing spirals, arcs, and flowing circular patterns */\nexport { swirlMeta, swirlFragmentShader, type SwirlParams, type SwirlUniforms } from './shaders/swirl.js';\n\n/** Animated 2-color dithering over with multiple pattern sources (noise, warp, dots, waves, ripple, swirl, sphere) */\nexport {\n ditheringFragmentShader,\n DitheringShapes,\n DitheringTypes,\n type DitheringParams,\n type DitheringUniforms,\n type DitheringShape,\n type DitheringType,\n} from './shaders/dithering.js';\n\n/** Multi-color gradients with grainy, noise-textured distortion available in 7 animated abstract forms */\nexport {\n grainGradientFragmentShader,\n grainGradientMeta,\n GrainGradientShapes,\n type GrainGradientParams,\n type GrainGradientUniforms,\n type GrainGradientShape,\n} from './shaders/grain-gradient.js';\n\n/** Luminous trails of color merging into a glowing gradient frame */\nexport {\n pulsingBorderMeta,\n pulsingBorderFragmentShader,\n PulsingBorderAspectRatios,\n type PulsingBorderParams,\n type PulsingBorderUniforms,\n type PulsingBorderAspectRatio,\n} from './shaders/pulsing-border.js';\n\n/** Glowing translucent 3D panels rotating around a central axis */\nexport {\n colorPanelsFragmentShader,\n colorPanelsMeta,\n type ColorPanelsParams,\n type ColorPanelsUniforms,\n} from './shaders/color-panels.js';\n\n/** Multi-point mesh gradients with up to 10 color spots, enhanced by two-direction warping, adjustable blend sharpness, and grain controls. Perfect for elegant wallpapers and atmospheric backdrops */\nexport {\n staticMeshGradientFragmentShader,\n staticMeshGradientMeta,\n type StaticMeshGradientParams,\n type StaticMeshGradientUniforms,\n} from './shaders/static-mesh-gradient.js';\n\n/** Radial gradient with up to 10 blended colors, featuring advanced focal point control, shape distortion, and grain effects */\nexport {\n staticRadialGradientFragmentShader,\n staticRadialGradientMeta,\n type StaticRadialGradientParams,\n type StaticRadialGradientUniforms,\n} from './shaders/static-radial-gradient.js';\n\n/** A static texture built from multiple noise layers, usable for a realistic paper and cardboard surfaces or generating abstract patterns. Can be used as a image filter or as a texture */\nexport {\n paperTextureFragmentShader,\n paperTextureMeta,\n type PaperTextureParams,\n type PaperTextureUniforms,\n} from './shaders/paper-texture.js';\n\n/** Water-like surface distortion with natural caustic realism. Works as an image filter or animated texture without image */\nexport { waterFragmentShader, type WaterParams, type WaterUniforms } from './shaders/water.js';\n\n/** Fluted glass image filter transforms an image into streaked, ribbed distortions, giving a mix of clarity and obscurity */\nexport {\n flutedGlassFragmentShader,\n GlassDistortionShapes,\n GlassGridShapes,\n type GlassDistortionShape,\n type GlassGridShape,\n type FlutedGlassParams,\n type FlutedGlassUniforms,\n} from './shaders/fluted-glass.js';\n\n/** A dithering image filter with support for 4 dithering modes and multiple color palettes (2-color, 3-color, and multicolor options, using either predefined colors or ones sampled directly from the original image) */\nexport {\n imageDitheringFragmentShader,\n type ImageDitheringParams,\n type ImageDitheringUniforms,\n} from './shaders/image-dithering.js';\n\n/** Lens Distortion image filter that separates an image into shifting color layers, recreating the chromatic aberration of a lens, and warps the image geometry with barrel or pincushion curvature */\nexport {\n lensDistortionFragmentShader,\n lensDistortionMeta,\n type LensDistortionParams,\n type LensDistortionUniforms,\n} from './shaders/lens-distortion.js';\n\n/** A glowing gradient of colors flowing through an input image. The effect creates a smoothly animated wave of intensity across the image */\nexport {\n heatmapMeta,\n heatmapFragmentShader,\n toProcessedHeatmap,\n type HeatmapParams,\n type HeatmapUniforms,\n} from './shaders/heatmap.js';\n\n/** Futuristic liquid metal material applied to uploaded logo or one of pre-defined abstract shape */\nexport {\n liquidMetalFragmentShader,\n LiquidMetalShapes,\n toProcessedLiquidMetal,\n type LiquidMetalShape,\n type LiquidMetalParams,\n type LiquidMetalUniforms,\n} from './shaders/liquid-metal.js';\n\n/** A halftone-dot image filter featuring customizable grids, color palettes, and dot styles */\nexport {\n HalftoneDotsTypes,\n HalftoneDotsGrids,\n halftoneDotsFragmentShader,\n type HalftoneDotsParams,\n type HalftoneDotsUniforms,\n type HalftoneDotsType,\n type HalftoneDotsGrid,\n} from './shaders/halftone-dots.js';\n\n/** A halftone CMYK classic algo */\nexport {\n HalftoneCmykTypes,\n halftoneCmykFragmentShader,\n type HalftoneCmykParams,\n type HalftoneCmykUniforms,\n type HalftoneCmykType,\n} from './shaders/halftone-cmyk.js';\n\n/** Animated color fields running around a glassy logo shape */\nexport {\n gemSmokeMeta,\n gemSmokeFragmentShader,\n toProcessedGemSmoke,\n GemSmokeShapes,\n type GemSmokeShape,\n type GemSmokeParams,\n type GemSmokeUniforms,\n} from './shaders/gem-smoke.js';\n\n// ----- Utils ----- //\nexport { getShaderColorFromString } from './get-shader-color-from-string.js';\nexport { getShaderNoiseTexture } from './get-shader-noise-texture.js';\nexport { emptyPixel } from './empty-pixel.js';\n"],
|
|
5
|
+
"mappings": ";;;;;AACA,SAAS,aAAa,4BAA4B;AAClD,SAAS,+BAA+B;AAUxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP,SAAS,gCAAgF;AAGzF;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP,SAAS,iCAAmF;AAG5F,SAAS,aAAa,6BAAuE;AAG7F,SAAS,2BAAiE;AAG1E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,SAAS,aAAa,6BAAuE;AAG7F,SAAS,4BAAoE;AAG7E,SAAS,WAAW,2BAAiE;AAGrF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP,SAAS,2BAAiE;AAG1E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAGP;AAAA,EACE;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,SAAS,gCAAgC;AACzC,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/shader-mount.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export declare class ShaderMount {
|
|
|
32
32
|
private uniformCache;
|
|
33
33
|
private textureUnitMap;
|
|
34
34
|
private ownerDocument;
|
|
35
|
+
private htmlUniforms;
|
|
36
|
+
private isReactCanvas;
|
|
35
37
|
constructor(
|
|
36
38
|
/** The div you'd like to mount the shader to. The shader will match its size. */
|
|
37
39
|
parentElement: HTMLElement, fragmentShader: string, uniforms: ShaderMountUniforms, webGlContextAttributes?: WebGLContextAttributes,
|
|
@@ -81,6 +83,13 @@ export declare class ShaderMount {
|
|
|
81
83
|
private requestRender;
|
|
82
84
|
/** Creates a texture from an image and sets it into a uniform value */
|
|
83
85
|
private setTextureUniform;
|
|
86
|
+
private createTexture;
|
|
87
|
+
/** Moves the element into the shader canvas and redraws it into the texture on every canvas paint */
|
|
88
|
+
private setHtmlUniform;
|
|
89
|
+
/** Captures each HTML uniform into its texture. On resize only HTML that has a snapshot already, so it can't throw */
|
|
90
|
+
private captureHtml;
|
|
91
|
+
private unsetHtmlUniform;
|
|
92
|
+
private handleCanvasPaint;
|
|
84
93
|
/** Utility: recursive equality test for all the uniforms */
|
|
85
94
|
private areUniformValuesEqual;
|
|
86
95
|
/** Sets the provided uniform values into the WebGL program, can be a partial list of uniforms that have changed */
|
|
@@ -100,6 +109,8 @@ export declare class ShaderMount {
|
|
|
100
109
|
setMinPixelRatio: (newMinPixelRatio?: number) => void;
|
|
101
110
|
/** Update the uniforms that are provided by the outside shader, can be a partial set with only the uniforms that have changed */
|
|
102
111
|
setUniforms: (newUniforms: ShaderMountUniforms) => void;
|
|
112
|
+
/** Render right away only when the rAF loop isn't running */
|
|
113
|
+
private renderUnlessAnimating;
|
|
103
114
|
private handleDocumentVisibilityChange;
|
|
104
115
|
/** Dispose of the shader mount, cleaning up all of the WebGL resources */
|
|
105
116
|
dispose: () => void;
|
|
@@ -117,7 +128,7 @@ export declare function isPaperShaderElement(element: HTMLElement): element is P
|
|
|
117
128
|
* We just skip setting the uniform if it's undefined. This allows the shader mount to still take up space during server rendering
|
|
118
129
|
*/
|
|
119
130
|
export interface ShaderMountUniforms {
|
|
120
|
-
[key: string]: boolean | number | number[] | number[][] | HTMLImageElement | undefined;
|
|
131
|
+
[key: string]: boolean | number | number[] | number[][] | HTMLImageElement | HTMLElement | undefined;
|
|
121
132
|
}
|
|
122
133
|
export interface ShaderMotionParams {
|
|
123
134
|
speed?: number;
|
package/dist/shader-mount.js
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
5
5
|
|
|
6
6
|
import { vertexShaderSource } from "./vertex-shader.js";
|
|
7
|
+
import {
|
|
8
|
+
attachHtml,
|
|
9
|
+
drawHtml,
|
|
10
|
+
findReactCanvas,
|
|
11
|
+
isHtmlInCanvasSupported,
|
|
12
|
+
isHtmlUniform
|
|
13
|
+
} from "./html-in-canvas.js";
|
|
7
14
|
const DEFAULT_MAX_PIXEL_COUNT = 1920 * 1080 * 4;
|
|
8
15
|
class ShaderMount {
|
|
9
16
|
parentElement;
|
|
@@ -39,6 +46,8 @@ class ShaderMount {
|
|
|
39
46
|
uniformCache = {};
|
|
40
47
|
textureUnitMap = /* @__PURE__ */ new Map();
|
|
41
48
|
ownerDocument;
|
|
49
|
+
htmlUniforms = /* @__PURE__ */ new Map();
|
|
50
|
+
isReactCanvas = false;
|
|
42
51
|
constructor(parentElement, fragmentShader, uniforms, webGlContextAttributes, speed = 0, frame = 0, minPixelRatio = 2, maxPixelCount = DEFAULT_MAX_PIXEL_COUNT, mipmaps = []) {
|
|
43
52
|
if (parentElement?.nodeType === 1) {
|
|
44
53
|
this.parentElement = parentElement;
|
|
@@ -52,20 +61,31 @@ class ShaderMount {
|
|
|
52
61
|
styleElement.setAttribute("data-paper-shader", "");
|
|
53
62
|
this.ownerDocument.head.prepend(styleElement);
|
|
54
63
|
}
|
|
55
|
-
const
|
|
64
|
+
const reactCanvas = findReactCanvas(Object.values(uniforms), this.parentElement);
|
|
65
|
+
const canvasElement = reactCanvas ?? this.ownerDocument.createElement("canvas");
|
|
56
66
|
this.canvasElement = canvasElement;
|
|
57
|
-
this.
|
|
67
|
+
this.isReactCanvas = reactCanvas !== null;
|
|
68
|
+
if (!reactCanvas) {
|
|
69
|
+
this.parentElement.prepend(canvasElement);
|
|
70
|
+
}
|
|
71
|
+
canvasElement.addEventListener("paint", this.handleCanvasPaint);
|
|
58
72
|
this.fragmentShader = fragmentShader;
|
|
59
73
|
this.providedUniforms = uniforms;
|
|
60
74
|
this.mipmaps = mipmaps;
|
|
61
75
|
this.currentFrame = frame;
|
|
62
76
|
this.minPixelRatio = minPixelRatio;
|
|
63
77
|
this.maxPixelCount = maxPixelCount;
|
|
64
|
-
const gl = canvasElement.getContext("webgl2",
|
|
78
|
+
const gl = canvasElement.getContext("webgl2", {
|
|
79
|
+
antialias: false,
|
|
80
|
+
depth: false,
|
|
81
|
+
stencil: false,
|
|
82
|
+
...webGlContextAttributes
|
|
83
|
+
});
|
|
65
84
|
if (!gl) {
|
|
66
85
|
throw new Error("Paper Shaders: WebGL is not supported in this browser");
|
|
67
86
|
}
|
|
68
87
|
this.gl = gl;
|
|
88
|
+
this.gl.pixelStorei(this.gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
69
89
|
this.initProgram();
|
|
70
90
|
this.setupPositionAttribute();
|
|
71
91
|
this.setupUniforms();
|
|
@@ -82,6 +102,7 @@ class ShaderMount {
|
|
|
82
102
|
const program = createProgram(this.gl, vertexShaderSource, this.fragmentShader);
|
|
83
103
|
if (!program) return;
|
|
84
104
|
this.program = program;
|
|
105
|
+
this.gl.useProgram(program);
|
|
85
106
|
};
|
|
86
107
|
setupPositionAttribute = () => {
|
|
87
108
|
const positionAttributeLocation = this.gl.getAttribLocation(this.program, "a_position");
|
|
@@ -100,9 +121,10 @@ class ShaderMount {
|
|
|
100
121
|
};
|
|
101
122
|
Object.entries(this.providedUniforms).forEach(([key, value]) => {
|
|
102
123
|
uniformLocations[key] = this.gl.getUniformLocation(this.program, key);
|
|
103
|
-
if (value instanceof HTMLImageElement) {
|
|
124
|
+
if (value instanceof HTMLImageElement || isHtmlUniform(value)) {
|
|
104
125
|
const aspectRatioUniformName = `${key}AspectRatio`;
|
|
105
126
|
uniformLocations[aspectRatioUniformName] = this.gl.getUniformLocation(this.program, aspectRatioUniformName);
|
|
127
|
+
uniformLocations[`${key}IsHtml`] = this.gl.getUniformLocation(this.program, `${key}IsHtml`);
|
|
106
128
|
}
|
|
107
129
|
});
|
|
108
130
|
this.uniformLocations = uniformLocations;
|
|
@@ -187,6 +209,10 @@ class ShaderMount {
|
|
|
187
209
|
this.canvasElement.height = newHeight;
|
|
188
210
|
this.resolutionChanged = true;
|
|
189
211
|
this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
|
|
212
|
+
this.captureHtml(true);
|
|
213
|
+
if (this.htmlUniforms.size > 0) {
|
|
214
|
+
this.canvasElement.requestPaint();
|
|
215
|
+
}
|
|
190
216
|
this.render(performance.now());
|
|
191
217
|
}
|
|
192
218
|
};
|
|
@@ -202,7 +228,6 @@ class ShaderMount {
|
|
|
202
228
|
this.currentFrame += dt * this.currentSpeed;
|
|
203
229
|
}
|
|
204
230
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
205
|
-
this.gl.useProgram(this.program);
|
|
206
231
|
this.gl.uniform1f(this.uniformLocations.u_time, this.currentFrame * 1e-3);
|
|
207
232
|
if (this.resolutionChanged) {
|
|
208
233
|
this.gl.uniform2f(this.uniformLocations.u_resolution, this.gl.canvas.width, this.gl.canvas.height);
|
|
@@ -227,21 +252,8 @@ class ShaderMount {
|
|
|
227
252
|
if (!image.complete || image.naturalWidth === 0) {
|
|
228
253
|
throw new Error(`Paper Shaders: image for uniform ${uniformName} must be fully loaded`);
|
|
229
254
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
this.gl.deleteTexture(existingTexture);
|
|
233
|
-
}
|
|
234
|
-
if (!this.textureUnitMap.has(uniformName)) {
|
|
235
|
-
this.textureUnitMap.set(uniformName, this.textureUnitMap.size);
|
|
236
|
-
}
|
|
237
|
-
const textureUnit = this.textureUnitMap.get(uniformName);
|
|
238
|
-
this.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);
|
|
239
|
-
const texture = this.gl.createTexture();
|
|
240
|
-
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
241
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
242
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
243
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
244
|
-
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
255
|
+
this.unsetHtmlUniform(uniformName);
|
|
256
|
+
const { texture, textureUnit } = this.createTexture(uniformName);
|
|
245
257
|
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);
|
|
246
258
|
if (this.mipmaps.includes(uniformName)) {
|
|
247
259
|
this.gl.generateMipmap(this.gl.TEXTURE_2D);
|
|
@@ -262,8 +274,71 @@ class ShaderMount {
|
|
|
262
274
|
const aspectRatio = image.naturalWidth / image.naturalHeight;
|
|
263
275
|
this.gl.uniform1f(aspectRatioLocation, aspectRatio);
|
|
264
276
|
}
|
|
277
|
+
this.gl.uniform1f(this.uniformLocations[`${uniformName}IsHtml`] ?? null, 0);
|
|
265
278
|
}
|
|
266
279
|
};
|
|
280
|
+
createTexture = (uniformName) => {
|
|
281
|
+
const existingTexture = this.textures.get(uniformName);
|
|
282
|
+
if (existingTexture) {
|
|
283
|
+
this.gl.deleteTexture(existingTexture);
|
|
284
|
+
}
|
|
285
|
+
if (!this.textureUnitMap.has(uniformName)) {
|
|
286
|
+
this.textureUnitMap.set(uniformName, this.textureUnitMap.size);
|
|
287
|
+
}
|
|
288
|
+
const textureUnit = this.textureUnitMap.get(uniformName);
|
|
289
|
+
this.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);
|
|
290
|
+
const texture = this.gl.createTexture();
|
|
291
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
|
|
292
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
|
|
293
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
|
|
294
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
|
|
295
|
+
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
296
|
+
return { texture, textureUnit };
|
|
297
|
+
};
|
|
298
|
+
/** Moves the element into the shader canvas and redraws it into the texture on every canvas paint */
|
|
299
|
+
setHtmlUniform = (uniformName, element) => {
|
|
300
|
+
this.unsetHtmlUniform(uniformName);
|
|
301
|
+
const { texture, textureUnit } = this.createTexture(uniformName);
|
|
302
|
+
if (texture === null) return;
|
|
303
|
+
this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, 1, 1, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);
|
|
304
|
+
this.textures.set(uniformName, texture);
|
|
305
|
+
this.gl.uniform1i(this.uniformLocations[uniformName] ?? null, textureUnit);
|
|
306
|
+
this.gl.uniform1f(this.uniformLocations[`${uniformName}IsHtml`] ?? null, 1);
|
|
307
|
+
if (!isHtmlInCanvasSupported()) {
|
|
308
|
+
console.warn(
|
|
309
|
+
`Paper Shaders: HTML for ${uniformName} needs HTML in canvas support (chrome://flags/#canvas-draw-element)`
|
|
310
|
+
);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const canvas = this.canvasElement;
|
|
314
|
+
this.htmlUniforms.set(uniformName, { element, detach: attachHtml(canvas, element), hasGeometry: false });
|
|
315
|
+
canvas.requestPaint();
|
|
316
|
+
};
|
|
317
|
+
/** Captures each HTML uniform into its texture. On resize only HTML that has a snapshot already, so it can't throw */
|
|
318
|
+
captureHtml = (isResize) => {
|
|
319
|
+
const canvas = this.canvasElement;
|
|
320
|
+
this.htmlUniforms.forEach((html, uniformName) => {
|
|
321
|
+
if (isResize && html.layout === void 0) return;
|
|
322
|
+
this.gl.activeTexture(this.gl.TEXTURE0 + this.textureUnitMap.get(uniformName));
|
|
323
|
+
this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.get(uniformName));
|
|
324
|
+
html.layout = drawHtml(this.gl, canvas, html.element, html.layout);
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
unsetHtmlUniform = (uniformName) => {
|
|
328
|
+
this.htmlUniforms.get(uniformName)?.detach();
|
|
329
|
+
this.htmlUniforms.delete(uniformName);
|
|
330
|
+
};
|
|
331
|
+
handleCanvasPaint = () => {
|
|
332
|
+
const canvas = this.canvasElement;
|
|
333
|
+
this.captureHtml(false);
|
|
334
|
+
this.htmlUniforms.forEach((html) => {
|
|
335
|
+
if (!html.hasGeometry) {
|
|
336
|
+
canvas.updateElementGeometry(html.element, { canvasTransform: new DOMMatrix() });
|
|
337
|
+
html.hasGeometry = true;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
this.renderUnlessAnimating();
|
|
341
|
+
};
|
|
267
342
|
/** Utility: recursive equality test for all the uniforms */
|
|
268
343
|
areUniformValuesEqual = (a, b) => {
|
|
269
344
|
if (a === b) return true;
|
|
@@ -274,7 +349,6 @@ class ShaderMount {
|
|
|
274
349
|
};
|
|
275
350
|
/** Sets the provided uniform values into the WebGL program, can be a partial list of uniforms that have changed */
|
|
276
351
|
setUniformValues = (updatedUniforms) => {
|
|
277
|
-
this.gl.useProgram(this.program);
|
|
278
352
|
Object.entries(updatedUniforms).forEach(([key, value]) => {
|
|
279
353
|
let cacheValue = value;
|
|
280
354
|
if (value instanceof HTMLImageElement) {
|
|
@@ -289,6 +363,8 @@ class ShaderMount {
|
|
|
289
363
|
}
|
|
290
364
|
if (value instanceof HTMLImageElement) {
|
|
291
365
|
this.setTextureUniform(key, value);
|
|
366
|
+
} else if (isHtmlUniform(value)) {
|
|
367
|
+
this.setHtmlUniform(key, value);
|
|
292
368
|
} else if (Array.isArray(value)) {
|
|
293
369
|
let flatArray = null;
|
|
294
370
|
let valueLength = null;
|
|
@@ -341,7 +417,7 @@ class ShaderMount {
|
|
|
341
417
|
setFrame = (newFrame) => {
|
|
342
418
|
this.currentFrame = newFrame;
|
|
343
419
|
this.lastRenderTime = performance.now();
|
|
344
|
-
this.
|
|
420
|
+
this.renderUnlessAnimating();
|
|
345
421
|
};
|
|
346
422
|
/** Set an animation speed (or 0 to stop animation) */
|
|
347
423
|
setSpeed = (newSpeed = 1) => {
|
|
@@ -377,7 +453,13 @@ class ShaderMount {
|
|
|
377
453
|
setUniforms = (newUniforms) => {
|
|
378
454
|
this.setUniformValues(newUniforms);
|
|
379
455
|
this.providedUniforms = { ...this.providedUniforms, ...newUniforms };
|
|
380
|
-
this.
|
|
456
|
+
this.renderUnlessAnimating();
|
|
457
|
+
};
|
|
458
|
+
/** Render right away only when the rAF loop isn't running */
|
|
459
|
+
renderUnlessAnimating = () => {
|
|
460
|
+
if (this.rafId === null) {
|
|
461
|
+
this.render(performance.now());
|
|
462
|
+
}
|
|
381
463
|
};
|
|
382
464
|
handleDocumentVisibilityChange = () => {
|
|
383
465
|
this.updateCurrentSpeed();
|
|
@@ -389,6 +471,9 @@ class ShaderMount {
|
|
|
389
471
|
cancelAnimationFrame(this.rafId);
|
|
390
472
|
this.rafId = null;
|
|
391
473
|
}
|
|
474
|
+
this.canvasElement.removeEventListener("paint", this.handleCanvasPaint);
|
|
475
|
+
this.htmlUniforms.forEach(({ detach }) => detach());
|
|
476
|
+
this.htmlUniforms.clear();
|
|
392
477
|
if (this.gl && this.program) {
|
|
393
478
|
this.textures.forEach((texture) => {
|
|
394
479
|
this.gl.deleteTexture(texture);
|
|
@@ -413,7 +498,9 @@ class ShaderMount {
|
|
|
413
498
|
visualViewport?.removeEventListener("resize", this.handleVisualViewportChange);
|
|
414
499
|
this.ownerDocument.removeEventListener("visibilitychange", this.handleDocumentVisibilityChange);
|
|
415
500
|
this.uniformLocations = {};
|
|
416
|
-
this.
|
|
501
|
+
if (!this.isReactCanvas) {
|
|
502
|
+
this.canvasElement.remove();
|
|
503
|
+
}
|
|
417
504
|
delete this.parentElement.paperShaderMount;
|
|
418
505
|
};
|
|
419
506
|
}
|
|
@@ -462,7 +549,7 @@ const defaultStyle = `@layer paper-shaders {
|
|
|
462
549
|
isolation: isolate;
|
|
463
550
|
position: relative;
|
|
464
551
|
|
|
465
|
-
& canvas {
|
|
552
|
+
& > canvas {
|
|
466
553
|
contain: strict;
|
|
467
554
|
display: block;
|
|
468
555
|
position: absolute;
|
|
@@ -473,6 +560,13 @@ const defaultStyle = `@layer paper-shaders {
|
|
|
473
560
|
border-radius: inherit;
|
|
474
561
|
corner-shape: inherit;
|
|
475
562
|
}
|
|
563
|
+
|
|
564
|
+
& > canvas > [drawable],
|
|
565
|
+
& > [drawable] {
|
|
566
|
+
box-sizing: border-box;
|
|
567
|
+
width: 100%;
|
|
568
|
+
height: 100%;
|
|
569
|
+
}
|
|
476
570
|
}
|
|
477
571
|
}`;
|
|
478
572
|
function isPaperShaderElement(element) {
|