react-video-ascii 1.1.0 → 1.3.0

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
@@ -1,6 +1,6 @@
1
1
  # react-video-ascii
2
2
 
3
- React component optimized for rendering videos as ASCII using WebGL2.
3
+ React component optimized for rendering videos and images as ASCII using WebGL2.
4
4
 
5
5
  <p align="center">
6
6
  <img width="1512" height="949" alt="demo" src="https://github.com/user-attachments/assets/2b41b0af-e864-430d-ade5-0249335d1aac" />
@@ -22,6 +22,10 @@ import { VideoAscii } from 'react-video-ascii';
22
22
  // Basic usage
23
23
  <VideoAscii src="/video.mp4" />
24
24
 
25
+ // Images work too (detected by extension, or force it with mediaType)
26
+ <VideoAscii src="/photo.jpg" />
27
+ <VideoAscii src="/api/photo?id=1" mediaType="image" />
28
+
25
29
  // Multiple videos (loop sequentially)
26
30
  const sources = ['/video1.mp4', '/video2.mp4'];
27
31
  <VideoAscii src={sources} />
@@ -65,8 +69,9 @@ const sources = ['/video1.mp4', '/video2.mp4'];
65
69
 
66
70
  | Prop | Type | Default | Range | Description |
67
71
  |------|------|---------|-------|-------------|
68
- | `src` | `string \| string[]` | — | — | Video source URL(s). Multiple URLs play sequentially. |
69
- | `videoMode` | `boolean` | `false` | — | Show original video colors instead of ASCII. |
72
+ | `src` | `string \| string[]` | — | — | Video or image source URL(s). Multiple video URLs play sequentially. |
73
+ | `mediaType` | `'auto' \| 'video' \| 'image'` | `'auto'` | — | How to load `src`. `auto` treats common image extensions as images and everything else as video. |
74
+ | `videoMode` | `boolean` | `false` | — | Show original video/image colors instead of ASCII. |
70
75
  | `numColsRaw` | `number` | `250` | `20–350` | Number of character columns. |
71
76
  | `brightnessRaw` | `number` | `1.0` | `0.0–2.0` | Brightness multiplier. |
72
77
  | `saturationRaw` | `number` | `1.0` | `0.0–2.0` | Saturation multiplier. |
@@ -77,6 +82,7 @@ const sources = ['/video1.mp4', '/video2.mp4'];
77
82
  | `clickEffect` | `boolean \| ClickEffectOptions` | `true` | — | Click effects. `true` uses defaults. |
78
83
  | `revealEffect` | `boolean \| RevealEffectOptions` | `false` | — | Reveal animation on load. `true` uses defaults. |
79
84
  | `cropFocus` | `'left' \| 'center' \| 'right'` | `'center'` | — | Determines where to anchor the cropping around. |
85
+ | `maxDpr` | `number` | *(uncapped)* | `1–4` | Caps the device-pixel ratio the canvas renders at (renders normally at sharpest res). |
80
86
  | `className` | `string` | — | — | CSS class on the outer container. |
81
87
 
82
88
  ---
@@ -1,3 +1,3 @@
1
1
  import { Props } from '../lib/ascii-props';
2
- declare function VideoAscii({ src, videoMode, numColsRaw, brightnessRaw, saturationRaw, bgOpacityRaw, revealEffect, chars, mouseEffect, clickEffect, charMode, className, cropFocus, }: Props): import("react/jsx-runtime").JSX.Element;
2
+ declare function VideoAscii({ src, mediaType, videoMode, numColsRaw, brightnessRaw, saturationRaw, bgOpacityRaw, revealEffect, chars, mouseEffect, clickEffect, charMode, className, cropFocus, maxDpr: maxDprRaw, }: Props): import("react/jsx-runtime").JSX.Element;
3
3
  export default VideoAscii;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { default as VideoAscii } from './components/VideoAscii';
2
- export type { Props } from './lib/ascii-props';
2
+ export type { Props, MediaType } from './lib/ascii-props';
@@ -19,8 +19,11 @@ export interface RevealEffectOptions {
19
19
  type?: 'diagonal' | 'radial' | 'random';
20
20
  duration?: number;
21
21
  }
22
+ export type MediaType = 'auto' | 'video' | 'image';
23
+ export declare function resolveMediaType(src: string | string[], mediaType: MediaType): 'video' | 'image';
22
24
  export interface Props {
23
25
  src: string | string[];
26
+ mediaType?: MediaType;
24
27
  videoMode?: boolean;
25
28
  numColsRaw?: number;
26
29
  brightnessRaw?: number;
@@ -33,6 +36,7 @@ export interface Props {
33
36
  charMode?: 'shape' | 'luminance';
34
37
  className?: string;
35
38
  cropFocus?: 'left' | 'center' | 'right';
39
+ maxDpr?: number;
36
40
  }
37
41
  export interface ParsedProps {
38
42
  numCols: number;
@@ -59,5 +63,6 @@ export interface ParsedProps {
59
63
  revealType: string;
60
64
  revealDuration: number;
61
65
  revealEffectFlag: number;
66
+ maxDpr: number;
62
67
  }
63
- export declare function parseProps(numColsRaw: number, brightnessRaw: number, saturationRaw: number, bgOpacityRaw: number, mouseEffect: boolean | MouseEffectOptions, clickEffect: boolean | ClickEffectOptions, revealEffect: boolean | RevealEffectOptions): ParsedProps;
68
+ export declare function parseProps(numColsRaw: number, brightnessRaw: number, saturationRaw: number, bgOpacityRaw: number, mouseEffect: boolean | MouseEffectOptions, clickEffect: boolean | ClickEffectOptions, revealEffect: boolean | RevealEffectOptions, maxDprRaw?: number): ParsedProps;
@@ -8,8 +8,11 @@ interface ClickEffectRefs {
8
8
  clickBrightnessRef: {
9
9
  current: number;
10
10
  };
11
+ pixelScaleRef: {
12
+ current: number;
13
+ };
11
14
  }
12
- export declare function createClickEffect({ clickEnabledRef, clickSpeedRef, clickBrightnessRef, }: ClickEffectRefs): {
15
+ export declare function createClickEffect({ clickEnabledRef, clickSpeedRef, clickBrightnessRef, pixelScaleRef, }: ClickEffectRefs): {
13
16
  handleClick(e: MouseEvent, canvas: HTMLCanvasElement): void;
14
17
  tick(gl: WebGL2RenderingContext, canvas: HTMLCanvasElement, ripplePositionsLoc: WebGLUniformLocation | null, rippleRadiiLoc: WebGLUniformLocation | null, rippleBrightnessesLoc: WebGLUniformLocation | null): void;
15
18
  };
@@ -20,6 +20,7 @@ export interface GLResources {
20
20
  p1ExponentLoc: WebGLUniformLocation | null;
21
21
  p1CropOffsetLoc: WebGLUniformLocation | null;
22
22
  p1CropScaleLoc: WebGLUniformLocation | null;
23
+ p1GridOffsetLoc: WebGLUniformLocation | null;
23
24
  revealEffectFlagLoc: WebGLUniformLocation | null;
24
25
  mouseEffectFlagLoc: WebGLUniformLocation | null;
25
26
  clickEffectFlagLoc: WebGLUniformLocation | null;
@@ -45,5 +46,6 @@ export interface GLResources {
45
46
  gridSizeLoc: WebGLUniformLocation | null;
46
47
  cropOffsetLoc: WebGLUniformLocation | null;
47
48
  cropScaleLoc: WebGLUniformLocation | null;
49
+ gridOffsetLoc: WebGLUniformLocation | null;
48
50
  }
49
51
  export declare function createGLResources(gl: WebGL2RenderingContext): GLResources | null;
@@ -0,0 +1,7 @@
1
+ export interface DevicePixelSize {
2
+ width: number;
3
+ height: number;
4
+ cssWidth: number;
5
+ cssHeight: number;
6
+ }
7
+ export declare function observeDevicePixelSize(el: Element, cb: (size: DevicePixelSize) => void): () => void;
@@ -13,7 +13,7 @@ interface ScatterRefs {
13
13
  };
14
14
  }
15
15
  export declare function createScatterEffect({ scatterEnabledRef, mouseRadiusRef, durationRef, scatterCharsRef, }: ScatterRefs): {
16
- setup(gl: WebGL2RenderingContext, cols: number, rows: number, cw: number, ch: number, scatterStateTexture: WebGLTexture): void;
16
+ setup(gl: WebGL2RenderingContext, cols: number, rows: number, cw: number, ch: number, offX: number, offY: number, scatterStateTexture: WebGLTexture): void;
17
17
  handleMouseMove(x: number, y: number, t: number): void;
18
18
  handleMouseLeave(): void;
19
19
  reset(gl: WebGL2RenderingContext): void;
@@ -13,7 +13,7 @@ interface SpreadRefs {
13
13
  };
14
14
  }
15
15
  export declare function createSpreadEffect({ spreadEnabledRef, scatterCharsRef, spreadExpandDurationRef, spreadSpeedRef, }: SpreadRefs): {
16
- setup(gl: WebGL2RenderingContext, cols: number, rows: number, cw: number, ch: number, spreadStateTexture: WebGLTexture): void;
16
+ setup(gl: WebGL2RenderingContext, cols: number, rows: number, cw: number, ch: number, offX: number, offY: number, spreadStateTexture: WebGLTexture): void;
17
17
  handleClick(e: MouseEvent, canvas: HTMLCanvasElement): void;
18
18
  tick(gl: WebGL2RenderingContext): void;
19
19
  };
@@ -50,58 +50,64 @@ function a(e, t, n) {
50
50
  }
51
51
  //#endregion
52
52
  //#region src/lib/ascii-props.ts
53
- var o = " `.',-_:!;|\"~+^lr[](\\/L)>t<v=Tz?icf1{sIxY*jJno}CZyVwmSXRqM$O%#9&NW0Q@";
54
- function s(e, t, n, r, i, a, o) {
55
- let s = !!i, c = typeof i == "object" ? i : {}, l = c.style ?? "brighten", u = s && l !== "scatter", d = s && l === "scatter", f = c.scatterChars ?? "->o", p = c.trailLen ?? 15, m = c.trailDecay ?? 10, h = c.duration ?? 1, g = c.radius ?? (l === "scatter" ? .05 : .08), _ = c.brightness ?? 2, v = !!a, y = typeof a == "object" ? a : {}, b = y.style ?? "ripple", x = v && b !== "spread", S = v && b === "spread", C = y.brightness ?? 1.1, w = y.speed ?? 2, T = y.spreadExpandDuration ?? 1.5, E = y.spreadSpeed ?? 7.5, D = !!o, O = typeof o == "object" ? o : {}, k = O.type ?? "random", A = O.duration ?? .4, j = Math.max(20, Math.min(350, Math.round(e))), M = Math.max(0, Math.min(2, t)), N = Math.max(0, Math.min(2, n)), P = Math.max(0, Math.min(1, r));
56
- A = Math.max(.1, Math.min(4, A)), p = Math.max(0, Math.min(30, Math.round(p))), m = Math.max(1, Math.min(15, m)), h = Math.max(.1, Math.min(4, h)), g = Math.max(.03, Math.min(.2, g)), _ = Math.max(.2, Math.min(5, _)), C = Math.max(1.05, Math.min(2, C)), w = Math.max(.5, Math.min(4, w)), T = Math.max(.5, Math.min(5, T)), E = Math.max(.5, Math.min(10, E));
57
- let F;
58
- return F = D ? k === "diagonal" ? 1 : k === "radial" ? 2 : 3 : 0, {
59
- numCols: j,
60
- brightness: M,
61
- saturation: N,
62
- bgOpacity: P,
63
- mouseEnabled: s,
64
- mouseStyle: l,
65
- brightenEnabled: u,
66
- scatterEnabled: d,
67
- scatterChars: f,
68
- trailLen: p,
69
- trailDecay: m,
70
- duration: h,
71
- mouseRadius: g,
72
- mouseBrightness: _,
73
- clickEnabled: x,
74
- clickBrightness: C,
75
- clickSpeed: w,
76
- spreadEnabled: S,
77
- spreadExpandDuration: T,
78
- spreadSpeed: E,
79
- revealEnabled: D,
80
- revealType: k,
81
- revealDuration: A,
82
- revealEffectFlag: F
53
+ var o = " `.',-_:!;|\"~+^lr[](\\/L)>t<v=Tz?icf1{sIxY*jJno}CZyVwmSXRqM$O%#9&NW0Q@", s = /\.(png|jpe?g|gif|webp|avif|bmp|svg)(?:[?#].*)?$/i;
54
+ function c(e, t) {
55
+ if (t !== "auto") return t;
56
+ let n = Array.isArray(e) ? e[0] : e;
57
+ return s.test(n) ? "image" : "video";
58
+ }
59
+ function l(e, t, n, r, i, a, o, s) {
60
+ let c = !!i, l = typeof i == "object" ? i : {}, u = l.style ?? "brighten", d = c && u !== "scatter", f = c && u === "scatter", p = l.scatterChars ?? "->o", m = l.trailLen ?? 15, h = l.trailDecay ?? 10, g = l.duration ?? 1, _ = l.radius ?? (u === "scatter" ? .05 : .08), v = l.brightness ?? 2, y = !!a, b = typeof a == "object" ? a : {}, x = b.style ?? "ripple", S = y && x !== "spread", C = y && x === "spread", w = b.brightness ?? 1.1, T = b.speed ?? 2, E = b.spreadExpandDuration ?? 1.5, D = b.spreadSpeed ?? 7.5, O = !!o, k = typeof o == "object" ? o : {}, A = k.type ?? "random", j = k.duration ?? .4, M = Math.max(20, Math.min(350, Math.round(e))), ee = Math.max(0, Math.min(2, t)), te = Math.max(0, Math.min(2, n)), N = Math.max(0, Math.min(1, r));
61
+ j = Math.max(.1, Math.min(4, j)), m = Math.max(0, Math.min(30, Math.round(m))), h = Math.max(1, Math.min(15, h)), g = Math.max(.1, Math.min(4, g)), _ = Math.max(.03, Math.min(.2, _)), v = Math.max(.2, Math.min(5, v)), w = Math.max(1.05, Math.min(2, w)), T = Math.max(.5, Math.min(4, T)), E = Math.max(.5, Math.min(5, E)), D = Math.max(.5, Math.min(10, D));
62
+ let P = s === void 0 ? Infinity : Math.max(1, Math.min(4, s)), F;
63
+ return F = O ? A === "diagonal" ? 1 : A === "radial" ? 2 : 3 : 0, {
64
+ numCols: M,
65
+ brightness: ee,
66
+ saturation: te,
67
+ bgOpacity: N,
68
+ mouseEnabled: c,
69
+ mouseStyle: u,
70
+ brightenEnabled: d,
71
+ scatterEnabled: f,
72
+ scatterChars: p,
73
+ trailLen: m,
74
+ trailDecay: h,
75
+ duration: g,
76
+ mouseRadius: _,
77
+ mouseBrightness: v,
78
+ clickEnabled: S,
79
+ clickBrightness: w,
80
+ clickSpeed: T,
81
+ spreadEnabled: C,
82
+ spreadExpandDuration: E,
83
+ spreadSpeed: D,
84
+ revealEnabled: O,
85
+ revealType: A,
86
+ revealDuration: j,
87
+ revealEffectFlag: F,
88
+ maxDpr: P
83
89
  };
84
90
  }
85
91
  //#endregion
86
92
  //#region src/lib/webgl-utils.ts
87
- function c(e, t, n) {
93
+ function u(e, t, n) {
88
94
  let r = e.createShader(t);
89
95
  if (!r) throw Error("Failed to create shader");
90
96
  return e.shaderSource(r, n), e.compileShader(r), e.getShaderParameter(r, e.COMPILE_STATUS) ? r : (console.log(e.getShaderInfoLog(r)), e.deleteShader(r), null);
91
97
  }
92
- function l(e, t, n) {
98
+ function d(e, t, n) {
93
99
  let r = e.createProgram();
94
100
  return e.attachShader(r, t), e.attachShader(r, n), e.linkProgram(r), e.getProgramParameter(r, e.LINK_STATUS) ? r : (console.log(e.getProgramInfoLog(r)), e.deleteProgram(r), null);
95
101
  }
96
102
  //#endregion
97
103
  //#region src/shaders/vertex.glsl
98
- var u = "#version 300 es\n\nin vec2 a_position;\n\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n}", d = "#version 300 es\n\nprecision highp float;\nprecision highp usampler2D;\n\nuniform int u_revealEffectFlag;\nuniform bool u_videoMode;\n\nuniform float u_revealProgress;\nuniform float u_brightness;\nuniform float u_saturation;\nuniform float u_bgOpacity;\n\nuniform bool u_mouseEffect;\n#define MOUSE_TRAIL_LEN 30 \nuniform vec2 u_mousePositions[MOUSE_TRAIL_LEN];\nuniform float u_mouseLifeFracs[MOUSE_TRAIL_LEN]; \nuniform float u_mouseRadius;\nuniform float u_mouseBrightness;\n\nuniform bool u_clickEffect;\n#define MAX_RIPPLES 10\nuniform vec2 u_ripplePositions[MAX_RIPPLES];\nuniform float u_rippleRadii[MAX_RIPPLES]; \nuniform float u_rippleBrightnesses[MAX_RIPPLES]; \n\nuniform bool u_scatterEffect;\nuniform usampler2D u_scatterStateTexture; \nuniform sampler2D u_scatterAtlas; \nuniform float u_scatterNumChars;\n\nuniform bool u_spreadEffect;\nuniform usampler2D u_spreadStateTexture;\n\nuniform bool u_shapeMatching;\n\nuniform sampler2D u_texture;\nuniform sampler2D u_atlas;\nuniform usampler2D u_fboTexture;\nuniform vec2 u_resolution;\nuniform vec2 u_cellsize;\nuniform float u_numChars;\nuniform vec2 u_gridSize;\nuniform vec2 u_cropOffset;\nuniform vec2 u_cropScale;\n\nout vec4 fragColor;\n\nfloat hash(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * 0.1031); \n p3 += dot(p3, p3.yzx + 33.33); \n return fract((p3.x + p3.y) * p3.z); \n}\n\nvec3 rgb2hsl(vec3 c) {\n float maxC = max(c.r, max(c.g, c.b));\n float minC = min(c.r, min(c.g, c.b));\n float l = (maxC + minC) * 0.5;\n float d = maxC - minC;\n float h = 0.0, s = 0.0;\n if (d > 0.0) {\n s = d / (1.0 - abs(2.0 * l - 1.0));\n if (maxC == c.r) h = mod((c.g - c.b) / d, 6.0) / 6.0;\n else if (maxC == c.g) h = ((c.b - c.r) / d + 2.0) / 6.0;\n else h = ((c.r - c.g) / d + 4.0) / 6.0;\n }\n return vec3(h, s, l);\n}\n\nvec3 hsl2rgb(vec3 c) {\n float h = c.x, s = c.y, l = c.z;\n float a = s * (1.0 - abs(2.0 * l - 1.0));\n vec3 rgb = clamp(abs(mod(h * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n return l + a * (rgb - 0.5);\n}\n\nvoid main() {\n vec2 fragCoord = vec2(gl_FragCoord.x, u_resolution.y - gl_FragCoord.y); \n vec2 cellCoord = floor(fragCoord / u_cellsize);\n\n if (u_revealEffectFlag == 1) {\n \n float revealThreshold = (cellCoord.x + cellCoord.y) / (u_gridSize.x + u_gridSize.y - 2.0);\n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n } else if (u_revealEffectFlag == 2) {\n float dist = length(cellCoord / u_gridSize - vec2(0.5));\n float revealThreshold = dist / 0.7071; \n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n } else if (u_revealEffectFlag == 3) {\n float revealThreshold = hash(cellCoord);\n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n }\n\n vec2 cellCenter = (cellCoord + 0.5) * u_cellsize; \n \n vec2 rawUV = u_videoMode ? (fragCoord / u_resolution) : (cellCenter / u_resolution);\n vec2 sampleUV = u_cropOffset + rawUV * u_cropScale;\n\n vec3 cellColor = texture(u_texture, sampleUV).rgb;\n float luminosity = dot(cellColor, vec3(0.299, 0.587, 0.114)); \n vec3 hsl = rgb2hsl(cellColor);\n hsl.z = clamp(hsl.z * u_brightness, 0.0, 1.0);\n hsl.y = clamp(hsl.y * u_saturation, 0.0, 1.0);\n cellColor = hsl2rgb(hsl);\n\n vec2 withinCellPos = fract(fragCoord / u_cellsize);\n\n \n float glyphMask = 0.0;\n if (!u_videoMode) {\n uint charInd;\n if (u_shapeMatching) {\n charInd = texelFetch(u_fboTexture, ivec2(cellCoord), 0).r;\n } else {\n charInd = uint(floor(luminosity * (u_numChars - 1.0)));\n }\n float atlasU = (float(charInd) + withinCellPos.x) / u_numChars;\n float atlasV = withinCellPos.y;\n glyphMask = texture(u_atlas, vec2(atlasU, atlasV)).r;\n }\n\n vec3 bgColor = cellColor * u_bgOpacity;\n\n bool scatterHit = false;\n vec3 scatterColor = vec3(0.0);\n if (u_scatterEffect) {\n uint state = texelFetch(u_scatterStateTexture, ivec2(cellCoord), 0).r;\n if (state > 0u) {\n int idx = int(state) - 1;\n float su = (float(idx) + withinCellPos.x) / u_scatterNumChars;\n float mask = texture(u_scatterAtlas, vec2(su, withinCellPos.y)).r;\n \n vec3 scatterBg = u_videoMode ? cellColor : bgColor;\n scatterColor = mix(scatterBg, vec3(1.0), mask);\n scatterHit = true;\n }\n }\n \n if (!scatterHit && u_spreadEffect) { \n uint state = texelFetch(u_spreadStateTexture, ivec2(cellCoord), 0).r;\n if (state > 0u) {\n int idx = int(state) - 1;\n float su = (float(idx) + withinCellPos.x) / u_scatterNumChars;\n float mask = texture(u_scatterAtlas, vec2(su, withinCellPos.y)).r;\n vec3 scatterBg = u_videoMode ? cellColor : bgColor;\n scatterColor = mix(scatterBg, vec3(1.0), mask);\n scatterHit = true;\n }\n }\n\n vec3 finalColor;\n if (scatterHit) {\n finalColor = scatterColor;\n } else {\n finalColor = u_videoMode ? cellColor : mix(bgColor, cellColor, glyphMask);\n\n if (u_mouseEffect) {\n bool inside = false;\n for (int i = 0; i < MOUSE_TRAIL_LEN; i++) {\n if (u_mouseLifeFracs[i] <= 0.0) {\n continue;\n }\n float r = u_mouseRadius * u_mouseLifeFracs[i];\n if (distance(cellCenter, u_mousePositions[i]) < r) {\n inside = true;\n break;\n }\n }\n if (inside) {\n finalColor = clamp(finalColor * u_mouseBrightness, 0.0, 1.0);\n }\n }\n\n if (u_clickEffect) {\n float boost = 1.0;\n for (int i = 0; i < MAX_RIPPLES; i++) {\n if (u_rippleBrightnesses[i] <= 1.0) {\n continue;\n }\n if (distance(cellCenter, u_ripplePositions[i]) < u_rippleRadii[i]) {\n boost *= u_rippleBrightnesses[i];\n }\n }\n if (boost > 1.0) {\n finalColor = clamp(finalColor * boost, 0.0, 1.0);\n }\n }\n }\n\n fragColor = vec4(finalColor, 1.0);\n}", f = "#version 300 es\n\nprecision highp float;\nprecision highp usampler2D;\n\nuniform sampler2D u_texture;\nuniform vec2 u_resolution;\nuniform vec2 u_cellsize;\nuniform int u_circleN;\nuniform sampler2D u_charVectors;\nuniform int u_numCharsInt;\nuniform float u_shapeExponent;\nuniform vec2 u_cropOffset;\nuniform vec2 u_cropScale;\n\nout uvec4 fragCharInd;\n\nvoid main() {\n \n ivec2 cellCoord = ivec2(floor(gl_FragCoord.xy));\n\n const vec2 CIRCLES[6] = vec2[6](\n vec2(0.25, 0.25), vec2(0.75, 0.25),\n vec2(0.25, 0.50), vec2(0.75, 0.50),\n vec2(0.25, 0.75), vec2(0.75, 0.75)\n );\n vec2 radiusUV = vec2(u_cellsize.x / 5.0) / u_resolution * u_cropScale; \n\n float sv[6];\n for (int ci = 0; ci < 6; ci++) {\n \n vec2 centerUV = u_cropOffset + (vec2(cellCoord) + CIRCLES[ci]) * u_cellsize / u_resolution * u_cropScale;\n float total = 0.0;\n int count = 0;\n for (int dx = -u_circleN; dx <= u_circleN; dx++) {\n for (int dy = -u_circleN; dy <= u_circleN; dy++) {\n if (dx*dx + dy*dy <= u_circleN*u_circleN) {\n vec2 sampleUV = centerUV + vec2(float(dx), float(dy)) * radiusUV / float(u_circleN);\n vec3 sc = texture(u_texture, sampleUV).rgb;\n total += dot(sc, vec3(0.299, 0.587, 0.114));\n count++;\n }\n }\n }\n \n sv[ci] = count > 0 ? total / float(count) : 0.0;\n }\n\n float maxVal = 0.0;\n for (int d = 0; d < 6; d++) maxVal = max(maxVal, sv[d]);\n if (maxVal > 0.0) {\n for (int d = 0; d < 6; d++) sv[d] = pow(sv[d] / maxVal, u_shapeExponent) * maxVal;\n }\n\n \n uint bestChar = 0u;\n float bestDist = 1e10;\n for (int i = 0; i < u_numCharsInt; i++) {\n vec4 r0 = texelFetch(u_charVectors, ivec2(i, 0), 0);\n vec4 r1 = texelFetch(u_charVectors, ivec2(i, 1), 0);\n float dist = 0.0;\n float diffs[6] = float[6](\n sv[0] - r0.r, sv[1] - r0.g, sv[2] - r0.b, sv[3] - r0.a,\n sv[4] - r1.r, sv[5] - r1.g\n );\n for (int d = 0; d < 6; d++) {\n dist += diffs[d] * diffs[d];\n }\n if (dist < bestDist) { \n bestDist = dist; bestChar = uint(i); \n }\n }\n\n fragCharInd = uvec4(bestChar, 0u, 0u, 0u);\n}";
104
+ var f = "#version 300 es\n\nin vec2 a_position;\n\nvoid main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n}", p = "#version 300 es\n\nprecision highp float;\nprecision highp usampler2D;\n\nuniform int u_revealEffectFlag;\nuniform bool u_videoMode;\n\nuniform float u_revealProgress;\nuniform float u_brightness;\nuniform float u_saturation;\nuniform float u_bgOpacity;\n\nuniform bool u_mouseEffect;\n#define MOUSE_TRAIL_LEN 30 \nuniform vec2 u_mousePositions[MOUSE_TRAIL_LEN];\nuniform float u_mouseLifeFracs[MOUSE_TRAIL_LEN]; \nuniform float u_mouseRadius;\nuniform float u_mouseBrightness;\n\nuniform bool u_clickEffect;\n#define MAX_RIPPLES 10\nuniform vec2 u_ripplePositions[MAX_RIPPLES];\nuniform float u_rippleRadii[MAX_RIPPLES]; \nuniform float u_rippleBrightnesses[MAX_RIPPLES]; \n\nuniform bool u_scatterEffect;\nuniform usampler2D u_scatterStateTexture; \nuniform sampler2D u_scatterAtlas; \nuniform float u_scatterNumChars;\n\nuniform bool u_spreadEffect;\nuniform usampler2D u_spreadStateTexture;\n\nuniform bool u_shapeMatching;\n\nuniform sampler2D u_texture;\nuniform sampler2D u_atlas;\nuniform usampler2D u_fboTexture;\nuniform vec2 u_resolution;\nuniform vec2 u_cellsize;\nuniform float u_numChars;\nuniform vec2 u_gridSize;\nuniform vec2 u_cropOffset;\nuniform vec2 u_cropScale;\nuniform vec2 u_gridOffset;\n\nout vec4 fragColor;\n\nfloat hash(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * 0.1031); \n p3 += dot(p3, p3.yzx + 33.33); \n return fract((p3.x + p3.y) * p3.z); \n}\n\nvec3 rgb2hsl(vec3 c) {\n float maxC = max(c.r, max(c.g, c.b));\n float minC = min(c.r, min(c.g, c.b));\n float l = (maxC + minC) * 0.5;\n float d = maxC - minC;\n float h = 0.0, s = 0.0;\n if (d > 0.0) {\n s = d / (1.0 - abs(2.0 * l - 1.0));\n if (maxC == c.r) h = mod((c.g - c.b) / d, 6.0) / 6.0;\n else if (maxC == c.g) h = ((c.b - c.r) / d + 2.0) / 6.0;\n else h = ((c.r - c.g) / d + 4.0) / 6.0;\n }\n return vec3(h, s, l);\n}\n\nvec3 hsl2rgb(vec3 c) {\n float h = c.x, s = c.y, l = c.z;\n float a = s * (1.0 - abs(2.0 * l - 1.0));\n vec3 rgb = clamp(abs(mod(h * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n return l + a * (rgb - 0.5);\n}\n\nvoid main() {\n vec2 fragCoord = vec2(gl_FragCoord.x, u_resolution.y - gl_FragCoord.y); \n vec2 gridCoord = fragCoord - u_gridOffset;\n vec2 cellCoordF = floor(gridCoord / u_cellsize);\n bool inGrid = all(greaterThanEqual(cellCoordF, vec2(0.0))) && all(lessThan(cellCoordF, u_gridSize));\n vec2 cellCoord = clamp(cellCoordF, vec2(0.0), u_gridSize - 1.0);\n\n if (u_revealEffectFlag == 1) {\n \n float revealThreshold = (cellCoord.x + cellCoord.y) / (u_gridSize.x + u_gridSize.y - 2.0);\n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n } else if (u_revealEffectFlag == 2) {\n float dist = length(cellCoord / u_gridSize - vec2(0.5));\n float revealThreshold = dist / 0.7071; \n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n } else if (u_revealEffectFlag == 3) {\n float revealThreshold = hash(cellCoord);\n if (revealThreshold > u_revealProgress) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n }\n\n vec2 cellCenter = u_gridOffset + (cellCoord + 0.5) * u_cellsize; \n \n vec2 rawUV = u_videoMode ? (fragCoord / u_resolution) : (cellCenter / u_resolution);\n vec2 sampleUV = u_cropOffset + rawUV * u_cropScale;\n\n vec3 cellColor = texture(u_texture, sampleUV).rgb;\n float luminosity = dot(cellColor, vec3(0.299, 0.587, 0.114)); \n vec3 hsl = rgb2hsl(cellColor);\n hsl.z = clamp(hsl.z * u_brightness, 0.0, 1.0);\n hsl.y = clamp(hsl.y * u_saturation, 0.0, 1.0);\n cellColor = hsl2rgb(hsl);\n\n vec2 withinCellPos = fract(gridCoord / u_cellsize);\n\n \n float glyphMask = 0.0;\n if (!u_videoMode && inGrid) {\n uint charInd;\n if (u_shapeMatching) {\n charInd = texelFetch(u_fboTexture, ivec2(cellCoord), 0).r;\n } else {\n charInd = uint(floor(luminosity * (u_numChars - 1.0)));\n }\n float atlasU = (float(charInd) + withinCellPos.x) / u_numChars;\n float atlasV = withinCellPos.y;\n glyphMask = texture(u_atlas, vec2(atlasU, atlasV)).r;\n }\n\n vec3 bgColor = cellColor * u_bgOpacity;\n\n bool scatterHit = false;\n vec3 scatterColor = vec3(0.0);\n if (u_scatterEffect && inGrid) {\n uint state = texelFetch(u_scatterStateTexture, ivec2(cellCoord), 0).r;\n if (state > 0u) {\n int idx = int(state) - 1;\n float su = (float(idx) + withinCellPos.x) / u_scatterNumChars;\n float mask = texture(u_scatterAtlas, vec2(su, withinCellPos.y)).r;\n \n vec3 scatterBg = u_videoMode ? cellColor : bgColor;\n scatterColor = mix(scatterBg, vec3(1.0), mask);\n scatterHit = true;\n }\n }\n \n if (!scatterHit && u_spreadEffect && inGrid) { \n uint state = texelFetch(u_spreadStateTexture, ivec2(cellCoord), 0).r;\n if (state > 0u) {\n int idx = int(state) - 1;\n float su = (float(idx) + withinCellPos.x) / u_scatterNumChars;\n float mask = texture(u_scatterAtlas, vec2(su, withinCellPos.y)).r;\n vec3 scatterBg = u_videoMode ? cellColor : bgColor;\n scatterColor = mix(scatterBg, vec3(1.0), mask);\n scatterHit = true;\n }\n }\n\n vec3 finalColor;\n if (scatterHit) {\n finalColor = scatterColor;\n } else {\n finalColor = u_videoMode ? cellColor : mix(bgColor, cellColor, glyphMask);\n\n if (u_mouseEffect) {\n bool inside = false;\n for (int i = 0; i < MOUSE_TRAIL_LEN; i++) {\n if (u_mouseLifeFracs[i] <= 0.0) {\n continue;\n }\n float r = u_mouseRadius * u_mouseLifeFracs[i];\n if (distance(cellCenter, u_mousePositions[i]) < r) {\n inside = true;\n break;\n }\n }\n if (inside) {\n finalColor = clamp(finalColor * u_mouseBrightness, 0.0, 1.0);\n }\n }\n\n if (u_clickEffect) {\n float boost = 1.0;\n for (int i = 0; i < MAX_RIPPLES; i++) {\n if (u_rippleBrightnesses[i] <= 1.0) {\n continue;\n }\n if (distance(cellCenter, u_ripplePositions[i]) < u_rippleRadii[i]) {\n boost *= u_rippleBrightnesses[i];\n }\n }\n if (boost > 1.0) {\n finalColor = clamp(finalColor * boost, 0.0, 1.0);\n }\n }\n }\n\n fragColor = vec4(finalColor, 1.0);\n}", m = "#version 300 es\n\nprecision highp float;\nprecision highp usampler2D;\n\nuniform sampler2D u_texture;\nuniform vec2 u_resolution;\nuniform vec2 u_cellsize;\nuniform int u_circleN;\nuniform sampler2D u_charVectors;\nuniform int u_numCharsInt;\nuniform float u_shapeExponent;\nuniform vec2 u_cropOffset;\nuniform vec2 u_cropScale;\nuniform vec2 u_gridOffset;\n\nout uvec4 fragCharInd;\n\nvoid main() {\n \n ivec2 cellCoord = ivec2(floor(gl_FragCoord.xy));\n\n const vec2 CIRCLES[6] = vec2[6](\n vec2(0.25, 0.25), vec2(0.75, 0.25),\n vec2(0.25, 0.50), vec2(0.75, 0.50),\n vec2(0.25, 0.75), vec2(0.75, 0.75)\n );\n vec2 radiusUV = vec2(u_cellsize.x / 5.0) / u_resolution * u_cropScale; \n\n float sv[6];\n for (int ci = 0; ci < 6; ci++) {\n \n vec2 centerUV = u_cropOffset + (u_gridOffset + (vec2(cellCoord) + CIRCLES[ci]) * u_cellsize) / u_resolution * u_cropScale;\n float total = 0.0;\n int count = 0;\n for (int dx = -u_circleN; dx <= u_circleN; dx++) {\n for (int dy = -u_circleN; dy <= u_circleN; dy++) {\n if (dx*dx + dy*dy <= u_circleN*u_circleN) {\n vec2 sampleUV = centerUV + vec2(float(dx), float(dy)) * radiusUV / float(u_circleN);\n vec3 sc = texture(u_texture, sampleUV).rgb;\n total += dot(sc, vec3(0.299, 0.587, 0.114));\n count++;\n }\n }\n }\n \n sv[ci] = count > 0 ? total / float(count) : 0.0;\n }\n\n float maxVal = 0.0;\n for (int d = 0; d < 6; d++) maxVal = max(maxVal, sv[d]);\n if (maxVal > 0.0) {\n for (int d = 0; d < 6; d++) sv[d] = pow(sv[d] / maxVal, u_shapeExponent) * maxVal;\n }\n\n \n uint bestChar = 0u;\n float bestDist = 1e10;\n for (int i = 0; i < u_numCharsInt; i++) {\n vec4 r0 = texelFetch(u_charVectors, ivec2(i, 0), 0);\n vec4 r1 = texelFetch(u_charVectors, ivec2(i, 1), 0);\n float dist = 0.0;\n float diffs[6] = float[6](\n sv[0] - r0.r, sv[1] - r0.g, sv[2] - r0.b, sv[3] - r0.a,\n sv[4] - r1.r, sv[5] - r1.g\n );\n for (int d = 0; d < 6; d++) {\n dist += diffs[d] * diffs[d];\n }\n if (dist < bestDist) { \n bestDist = dist; bestChar = uint(i); \n }\n }\n\n fragCharInd = uvec4(bestChar, 0u, 0u, 0u);\n}";
99
105
  //#endregion
100
106
  //#region src/lib/create-gl-resources.ts
101
- function p(e) {
102
- let t = c(e, e.VERTEX_SHADER, u), n = c(e, e.FRAGMENT_SHADER, d);
107
+ function h(e) {
108
+ let t = u(e, e.VERTEX_SHADER, f), n = u(e, e.FRAGMENT_SHADER, p);
103
109
  if (!t || !n) return null;
104
- let r = l(e, t, n);
110
+ let r = d(e, t, n);
105
111
  if (!r) return null;
106
112
  let i = new Float32Array([
107
113
  1,
@@ -121,28 +127,28 @@ function p(e) {
121
127
  let o = e.getAttribLocation(r, "a_position");
122
128
  e.vertexAttribPointer(o, 2, e.FLOAT, !1, 0, 0), e.enableVertexAttribArray(o), e.useProgram(r);
123
129
  let s = e.createTexture();
124
- e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, s), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
125
- let p = e.getUniformLocation(r, "u_texture");
126
- e.uniform1i(p, 0);
127
- let m = e.createTexture();
128
- e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, m), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
130
+ e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, s), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR);
131
+ let c = e.getUniformLocation(r, "u_texture");
132
+ e.uniform1i(c, 0);
133
+ let l = e.createTexture();
134
+ e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D, l), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
129
135
  let h = e.getUniformLocation(r, "u_atlas");
130
136
  e.uniform1i(h, 1);
131
137
  let g = e.createTexture();
132
138
  e.activeTexture(e.TEXTURE2), e.bindTexture(e.TEXTURE_2D, g), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
133
- let _ = c(e, e.FRAGMENT_SHADER, f);
139
+ let _ = u(e, e.FRAGMENT_SHADER, m);
134
140
  if (!_) return null;
135
- let v = l(e, t, _);
141
+ let v = d(e, t, _);
136
142
  if (!v) return null;
137
143
  e.useProgram(v), e.uniform1i(e.getUniformLocation(v, "u_texture"), 0), e.uniform1i(e.getUniformLocation(v, "u_charVectors"), 2);
138
- let y = e.getUniformLocation(v, "u_resolution"), b = e.getUniformLocation(v, "u_cellsize"), x = e.getUniformLocation(v, "u_circleN"), S = e.getUniformLocation(v, "u_numCharsInt"), C = e.getUniformLocation(v, "u_shapeExponent"), w = e.getUniformLocation(v, "u_cropOffset"), T = e.getUniformLocation(v, "u_cropScale"), E = e.createTexture();
139
- e.activeTexture(e.TEXTURE3), e.bindTexture(e.TEXTURE_2D, E), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
140
- let D = e.createFramebuffer(), O = e.createTexture();
141
- e.activeTexture(e.TEXTURE4), e.bindTexture(e.TEXTURE_2D, O), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
142
- let k = e.createTexture();
143
- e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, k), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
144
+ let y = e.getUniformLocation(v, "u_resolution"), b = e.getUniformLocation(v, "u_cellsize"), x = e.getUniformLocation(v, "u_circleN"), S = e.getUniformLocation(v, "u_numCharsInt"), C = e.getUniformLocation(v, "u_shapeExponent"), w = e.getUniformLocation(v, "u_cropOffset"), T = e.getUniformLocation(v, "u_cropScale"), E = e.getUniformLocation(v, "u_gridOffset"), D = e.createTexture();
145
+ e.activeTexture(e.TEXTURE3), e.bindTexture(e.TEXTURE_2D, D), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
146
+ let O = e.createFramebuffer(), k = e.createTexture();
147
+ e.activeTexture(e.TEXTURE4), e.bindTexture(e.TEXTURE_2D, k), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
144
148
  let A = e.createTexture();
145
- return e.activeTexture(e.TEXTURE6), e.bindTexture(e.TEXTURE_2D, A), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.useProgram(r), e.uniform1i(e.getUniformLocation(r, "u_fboTexture"), 3), e.uniform1i(e.getUniformLocation(r, "u_scatterAtlas"), 4), e.uniform1i(e.getUniformLocation(r, "u_scatterStateTexture"), 5), e.uniform1i(e.getUniformLocation(r, "u_spreadStateTexture"), 6), {
149
+ e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, A), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);
150
+ let j = e.createTexture();
151
+ return e.activeTexture(e.TEXTURE6), e.bindTexture(e.TEXTURE_2D, j), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST), e.useProgram(r), e.uniform1i(e.getUniformLocation(r, "u_fboTexture"), 3), e.uniform1i(e.getUniformLocation(r, "u_scatterAtlas"), 4), e.uniform1i(e.getUniformLocation(r, "u_scatterStateTexture"), 5), e.uniform1i(e.getUniformLocation(r, "u_spreadStateTexture"), 6), {
146
152
  program: r,
147
153
  pass1Program: v,
148
154
  buffer: a,
@@ -150,13 +156,13 @@ function p(e) {
150
156
  fragShader: n,
151
157
  pass1FragShader: _,
152
158
  texture: s,
153
- atlasTexture: m,
159
+ atlasTexture: l,
154
160
  charVectorsTexture: g,
155
- fboTexture: E,
156
- fbo: D,
157
- scatterAtlasTexture: O,
158
- scatterStateTexture: k,
159
- spreadStateTexture: A,
161
+ fboTexture: D,
162
+ fbo: O,
163
+ scatterAtlasTexture: k,
164
+ scatterStateTexture: A,
165
+ spreadStateTexture: j,
160
166
  p1ResLoc: y,
161
167
  p1CellsizeLoc: b,
162
168
  p1CircleNLoc: x,
@@ -164,6 +170,7 @@ function p(e) {
164
170
  p1ExponentLoc: C,
165
171
  p1CropOffsetLoc: w,
166
172
  p1CropScaleLoc: T,
173
+ p1GridOffsetLoc: E,
167
174
  revealEffectFlagLoc: e.getUniformLocation(r, "u_revealEffectFlag"),
168
175
  mouseEffectFlagLoc: e.getUniformLocation(r, "u_mouseEffect"),
169
176
  clickEffectFlagLoc: e.getUniformLocation(r, "u_clickEffect"),
@@ -188,18 +195,19 @@ function p(e) {
188
195
  numLoc: e.getUniformLocation(r, "u_numChars"),
189
196
  gridSizeLoc: e.getUniformLocation(r, "u_gridSize"),
190
197
  cropOffsetLoc: e.getUniformLocation(r, "u_cropOffset"),
191
- cropScaleLoc: e.getUniformLocation(r, "u_cropScale")
198
+ cropScaleLoc: e.getUniformLocation(r, "u_cropScale"),
199
+ gridOffsetLoc: e.getUniformLocation(r, "u_gridOffset")
192
200
  };
193
201
  }
194
202
  //#endregion
195
203
  //#region src/lib/scatter-effect.ts
196
- function m({ scatterEnabledRef: e, mouseRadiusRef: t, durationRef: n, scatterCharsRef: r }) {
197
- let i = new Uint8Array(), a = new Float32Array(), o = new Float32Array(), s = new Uint8Array(), c = null, l = null, u = 0, d = 0, f = -1, p = () => Math.floor(Math.random() * r.current.length), m = 0, h = 0, g = 1, _ = 1, v = null;
204
+ function g({ scatterEnabledRef: e, mouseRadiusRef: t, durationRef: n, scatterCharsRef: r }) {
205
+ let i = new Uint8Array(), a = new Float32Array(), o = new Float32Array(), s = new Uint8Array(), c = null, l = null, u = 0, d = 0, f = -1, p = () => Math.floor(Math.random() * r.current.length), m = 0, h = 0, g = 1, _ = 1, v = 0, y = 0, b = null;
198
206
  return {
199
- setup(e, t, n, r, f, p) {
200
- m = t, h = n, g = r, _ = f, v = p;
201
- let y = t * n;
202
- i = new Uint8Array(y), a = new Float32Array(y), o = new Float32Array(y), s = new Uint8Array(y), c = null, l = null, u = 0, d = 0, e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, p), e.texImage2D(e.TEXTURE_2D, 0, e.R8UI, t, n, 0, e.RED_INTEGER, e.UNSIGNED_BYTE, i);
207
+ setup(e, t, n, r, f, p, x, S) {
208
+ m = t, h = n, g = r, _ = f, v = p, y = x, b = S;
209
+ let C = t * n;
210
+ i = new Uint8Array(C), a = new Float32Array(C), o = new Float32Array(C), s = new Uint8Array(C), c = null, l = null, u = 0, d = 0, e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, S), e.texImage2D(e.TEXTURE_2D, 0, e.R8UI, t, n, 0, e.RED_INTEGER, e.UNSIGNED_BYTE, i);
203
211
  },
204
212
  handleMouseMove(t, n, r) {
205
213
  e.current && (l = c, c = {
@@ -212,14 +220,14 @@ function m({ scatterEnabledRef: e, mouseRadiusRef: t, durationRef: n, scatterCha
212
220
  c = null, l = null, u = 0, d = 0;
213
221
  },
214
222
  reset(e) {
215
- i.fill(0), v && m > 0 && (e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, v), e.texSubImage2D(e.TEXTURE_2D, 0, 0, 0, m, h, e.RED_INTEGER, e.UNSIGNED_BYTE, i));
223
+ i.fill(0), b && m > 0 && (e.activeTexture(e.TEXTURE5), e.bindTexture(e.TEXTURE_2D, b), e.texSubImage2D(e.TEXTURE_2D, 0, 0, 0, m, h, e.RED_INTEGER, e.UNSIGNED_BYTE, i));
216
224
  },
217
- tick(r, y) {
225
+ tick(r, x) {
218
226
  if (!e.current || m === 0 || h === 0) return;
219
- let b = performance.now(), x = f < 0 ? 0 : Math.min(.1, (b - f) / 1e3);
220
- f = b;
221
- let S = Math.min(y.width, y.height) * t.current, C = !1;
222
- if (c && b - c.t < 80) {
227
+ let S = performance.now(), C = f < 0 ? 0 : Math.min(.1, (S - f) / 1e3);
228
+ f = S;
229
+ let w = Math.min(x.width, x.height) * t.current, T = !1;
230
+ if (c && S - c.t < 80) {
223
231
  if (l) {
224
232
  let e = (c.t - l.t) / 1e3;
225
233
  if (e > 0 && e < .2) {
@@ -227,31 +235,31 @@ function m({ scatterEnabledRef: e, mouseRadiusRef: t, durationRef: n, scatterCha
227
235
  u = u * .7 + t * .3, d = d * .7 + n * .3;
228
236
  }
229
237
  } else u = 0, d = 0;
230
- Math.hypot(u, d) > g * 2 && (C = !0);
238
+ Math.hypot(u, d) > g * 2 && (T = !0);
231
239
  } else u *= .6, d *= .6;
232
- if (s.fill(0), C && c && S > 0) {
233
- let e = c.x, t = c.y, n = Math.max(0, Math.floor((e - S) / g)), r = Math.min(m - 1, Math.floor((e + S) / g)), l = Math.max(0, Math.floor((t - S) / _)), u = Math.min(h - 1, Math.floor((t + S) / _));
240
+ if (s.fill(0), T && c && w > 0) {
241
+ let e = c.x, t = c.y, n = Math.max(0, Math.floor((e - v - w) / g)), r = Math.min(m - 1, Math.floor((e - v + w) / g)), l = Math.max(0, Math.floor((t - y - w) / _)), u = Math.min(h - 1, Math.floor((t - y + w) / _));
234
242
  for (let c = l; c <= u; c++) for (let l = n; l <= r; l++) {
235
- let n = (l + .5) * g, r = (c + .5) * _;
236
- if (Math.hypot(n - e, r - t) > S) continue;
243
+ let n = v + (l + .5) * g, r = y + (c + .5) * _;
244
+ if (Math.hypot(n - e, r - t) > w) continue;
237
245
  let u = c * m + l;
238
246
  s[u] = 1, i[u] === 0 && (i[u] = 1 + p(), o[u] = .5 + Math.random() * 2), a[u] = 1;
239
247
  }
240
248
  }
241
- let w = n.current;
242
- if (x > 0) for (let e = 0; e < h; e++) for (let t = 0; t < m; t++) {
249
+ let E = n.current;
250
+ if (C > 0) for (let e = 0; e < h; e++) for (let t = 0; t < m; t++) {
243
251
  let n = e * m + t;
244
252
  if (i[n] === 0 || s[n]) continue;
245
- let r = t > 0 ? i[n - 1] !== 0 : !1, c = t < m - 1 ? i[n + 1] !== 0 : !1, l = e > 0 ? i[n - m] !== 0 : !1, u = e < h - 1 ? i[n + m] !== 0 : !1, d = (!r || !c || !l || !u ? 5 : 1) * o[n] / w;
246
- a[n] -= d * x, a[n] <= 0 && (i[n] = 0);
253
+ let r = t > 0 ? i[n - 1] !== 0 : !1, c = t < m - 1 ? i[n + 1] !== 0 : !1, l = e > 0 ? i[n - m] !== 0 : !1, u = e < h - 1 ? i[n + m] !== 0 : !1, d = (!r || !c || !l || !u ? 5 : 1) * o[n] / E;
254
+ a[n] -= d * C, a[n] <= 0 && (i[n] = 0);
247
255
  }
248
- r.activeTexture(r.TEXTURE5), r.bindTexture(r.TEXTURE_2D, v), r.texSubImage2D(r.TEXTURE_2D, 0, 0, 0, m, h, r.RED_INTEGER, r.UNSIGNED_BYTE, i);
256
+ r.activeTexture(r.TEXTURE5), r.bindTexture(r.TEXTURE_2D, b), r.texSubImage2D(r.TEXTURE_2D, 0, 0, 0, m, h, r.RED_INTEGER, r.UNSIGNED_BYTE, i);
249
257
  }
250
258
  };
251
259
  }
252
260
  //#endregion
253
261
  //#region src/lib/brighten-effect.ts
254
- function h({ brightenEnabledRef: e, trailLenRef: t, durationRef: n, trailDecayRef: r }) {
262
+ function _({ brightenEnabledRef: e, trailLenRef: t, durationRef: n, trailDecayRef: r }) {
255
263
  let i = [];
256
264
  return {
257
265
  handleMouseMove(n, r, a) {
@@ -274,72 +282,72 @@ function h({ brightenEnabledRef: e, trailLenRef: t, durationRef: n, trailDecayRe
274
282
  }
275
283
  //#endregion
276
284
  //#region src/lib/click-effect.ts
277
- var g = 10;
278
- function _({ clickEnabledRef: e, clickSpeedRef: t, clickBrightnessRef: n }) {
279
- let r = [];
285
+ var v = 10;
286
+ function y({ clickEnabledRef: e, clickSpeedRef: t, clickBrightnessRef: n, pixelScaleRef: r }) {
287
+ let i = [];
280
288
  return {
281
289
  handleClick(t, n) {
282
290
  if (!e.current) return;
283
- let i = n.getBoundingClientRect(), a = (t.clientX - i.left) * (n.width / i.width), o = (t.clientY - i.top) * (n.height / i.height);
284
- r.push({
291
+ let r = n.getBoundingClientRect(), a = (t.clientX - r.left) * (n.width / r.width), o = (t.clientY - r.top) * (n.height / r.height);
292
+ i.push({
285
293
  x: a,
286
294
  y: o,
287
295
  t: performance.now()
288
- }), r.length > g && r.shift();
296
+ }), i.length > v && i.shift();
289
297
  },
290
- tick(i, a, o, s, c) {
298
+ tick(a, o, s, c, l) {
291
299
  if (!e.current) return;
292
- let l = performance.now(), u = Math.hypot(a.width, a.height), d = new Float32Array(g * 2), f = new Float32Array(g), p = new Float32Array(g);
293
- for (; r.length > 0 && (l - r[0].t) * t.current >= u;) r.shift();
294
- for (let e = 0; e < r.length; e++) {
295
- let i = (l - r[e].t) * t.current, a = i / u, o = 1 + (n.current - 1) * (1 - a ** 2);
296
- d[e * 2] = r[e].x, d[e * 2 + 1] = r[e].y, f[e] = i, p[e] = o;
300
+ let u = performance.now(), d = Math.hypot(o.width, o.height), f = t.current * r.current, p = new Float32Array(v * 2), m = new Float32Array(v), h = new Float32Array(v);
301
+ for (; i.length > 0 && (u - i[0].t) * f >= d;) i.shift();
302
+ for (let e = 0; e < i.length; e++) {
303
+ let t = (u - i[e].t) * f, r = t / d, a = 1 + (n.current - 1) * (1 - r ** 2);
304
+ p[e * 2] = i[e].x, p[e * 2 + 1] = i[e].y, m[e] = t, h[e] = a;
297
305
  }
298
- i.uniform2fv(o, d), i.uniform1fv(s, f), i.uniform1fv(c, p);
306
+ a.uniform2fv(s, p), a.uniform1fv(c, m), a.uniform1fv(l, h);
299
307
  }
300
308
  };
301
309
  }
302
310
  //#endregion
303
311
  //#region src/lib/spread-effect.ts
304
- function v({ spreadEnabledRef: e, scatterCharsRef: t, spreadExpandDurationRef: n, spreadSpeedRef: r }) {
305
- let i = new Uint8Array(), a = new Uint8Array(), o = 0, s = 0, c = 1, l = 1, u = null, d = -1, f = -1, p = () => Math.floor(Math.random() * t.current.length), m = [
312
+ function b({ spreadEnabledRef: e, scatterCharsRef: t, spreadExpandDurationRef: n, spreadSpeedRef: r }) {
313
+ let i = new Uint8Array(), a = new Uint8Array(), o = 0, s = 0, c = 1, l = 1, u = 0, d = 0, f = null, p = -1, m = -1, h = () => Math.floor(Math.random() * t.current.length), g = [
306
314
  [-1, 0],
307
315
  [1, 0],
308
316
  [0, -1],
309
317
  [0, 1]
310
318
  ];
311
319
  return {
312
- setup(e, t, n, r, p, m) {
313
- o = t, s = n, c = r, l = p, u = m;
314
- let h = t * n;
315
- i = new Uint8Array(h), a = new Uint8Array(h), f = -1, d = -1, e.activeTexture(e.TEXTURE6), e.bindTexture(e.TEXTURE_2D, m), e.texImage2D(e.TEXTURE_2D, 0, e.R8UI, t, n, 0, e.RED_INTEGER, e.UNSIGNED_BYTE, i);
320
+ setup(e, t, n, r, h, g, _, v) {
321
+ o = t, s = n, c = r, l = h, u = g, d = _, f = v;
322
+ let y = t * n;
323
+ i = new Uint8Array(y), a = new Uint8Array(y), m = -1, p = -1, e.activeTexture(e.TEXTURE6), e.bindTexture(e.TEXTURE_2D, v), e.texImage2D(e.TEXTURE_2D, 0, e.R8UI, t, n, 0, e.RED_INTEGER, e.UNSIGNED_BYTE, i);
316
324
  },
317
325
  handleClick(t, r) {
318
326
  if (!e.current || o === 0) return;
319
- let u = r.getBoundingClientRect(), d = (t.clientX - u.left) * (r.width / u.width), m = (t.clientY - u.top) * (r.height / u.height), h = Math.floor(d / c), g = Math.floor(m / l);
320
- if (h < 0 || h >= o || g < 0 || g >= s) return;
321
- let _ = g * o + h;
322
- i[_] = 1 + p(), a[_] = 1, f = performance.now() + n.current * 1e3;
327
+ let f = r.getBoundingClientRect(), p = (t.clientX - f.left) * (r.width / f.width), g = (t.clientY - f.top) * (r.height / f.height), _ = Math.floor((p - u) / c), v = Math.floor((g - d) / l);
328
+ if (_ < 0 || _ >= o || v < 0 || v >= s) return;
329
+ let y = v * o + _;
330
+ i[y] = 1 + h(), a[y] = 1, m = performance.now() + n.current * 1e3;
323
331
  },
324
332
  tick(t) {
325
333
  if (!e.current || o === 0 || s === 0) return;
326
- let n = performance.now(), c = d < 0 ? 0 : Math.min(.1, (n - d) / 1e3);
327
- d = n;
328
- let l = f > 0 && n < f;
329
- if (!l && f > 0) {
334
+ let n = performance.now(), c = p < 0 ? 0 : Math.min(.1, (n - p) / 1e3);
335
+ p = n;
336
+ let l = m > 0 && n < m;
337
+ if (!l && m > 0) {
330
338
  for (let e = 0; e < i.length; e++) a[e] === 1 && (a[e] = 2);
331
- f = -1;
339
+ m = -1;
332
340
  }
333
341
  if (c > 0) for (let e = 0; e < s; e++) for (let t = 0; t < o; t++) {
334
342
  let n = e * o + t;
335
343
  if (a[n] !== 0) {
336
- if (l && a[n] === 1) for (let [n, l] of m) {
344
+ if (l && a[n] === 1) for (let [n, l] of g) {
337
345
  let u = e + n, d = t + l;
338
346
  if (u < 0 || u >= s || d < 0 || d >= o) continue;
339
347
  let f = u * o + d;
340
- a[f] === 0 && Math.random() < r.current * c && (i[f] = 1 + p(), a[f] = 1);
348
+ a[f] === 0 && Math.random() < r.current * c && (i[f] = 1 + h(), a[f] = 1);
341
349
  }
342
- else if (a[n] === 2) for (let [l, u] of m) {
350
+ else if (a[n] === 2) for (let [l, u] of g) {
343
351
  let d = e + l, f = t + u;
344
352
  if (d < 0 || d >= s || f < 0 || f >= o || i[d * o + f] === 0) {
345
353
  Math.random() < r.current * c && (i[n] = 0, a[n] = 0);
@@ -348,170 +356,239 @@ function v({ spreadEnabledRef: e, scatterCharsRef: t, spreadExpandDurationRef: n
348
356
  }
349
357
  }
350
358
  }
351
- t.activeTexture(t.TEXTURE6), t.bindTexture(t.TEXTURE_2D, u), t.texSubImage2D(t.TEXTURE_2D, 0, 0, 0, o, s, t.RED_INTEGER, t.UNSIGNED_BYTE, i);
359
+ t.activeTexture(t.TEXTURE6), t.bindTexture(t.TEXTURE_2D, f), t.texSubImage2D(t.TEXTURE_2D, 0, 0, 0, o, s, t.RED_INTEGER, t.UNSIGNED_BYTE, i);
352
360
  }
353
361
  };
354
362
  }
355
363
  //#endregion
364
+ //#region src/lib/device-pixel-size.ts
365
+ function x(e, t) {
366
+ let n = 0, r = 0, i = !1, a = null, o = () => {
367
+ let e = window.devicePixelRatio || 1;
368
+ t({
369
+ width: Math.round(n * e),
370
+ height: Math.round(r * e),
371
+ cssWidth: n,
372
+ cssHeight: r
373
+ });
374
+ }, s = () => {
375
+ a?.();
376
+ let e = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`), t = () => {
377
+ i || (o(), s());
378
+ };
379
+ e.addEventListener("change", t, { once: !0 }), a = () => e.removeEventListener("change", t);
380
+ }, c = new ResizeObserver((e) => {
381
+ let i = e[0], a = i.contentBoxSize?.[0];
382
+ n = a ? a.inlineSize : i.contentRect.width, r = a ? a.blockSize : i.contentRect.height;
383
+ let s = i.devicePixelContentBoxSize?.[0];
384
+ s ? t({
385
+ width: s.inlineSize,
386
+ height: s.blockSize,
387
+ cssWidth: n,
388
+ cssHeight: r
389
+ }) : o();
390
+ });
391
+ try {
392
+ c.observe(e, { box: "device-pixel-content-box" });
393
+ } catch {
394
+ c.observe(e), s();
395
+ }
396
+ return () => {
397
+ i = !0, c.disconnect(), a?.();
398
+ };
399
+ }
400
+ //#endregion
356
401
  //#region src/components/VideoAscii.tsx
357
- function y({ src: i, videoMode: c = !1, numColsRaw: l = 250, brightnessRaw: u = 1, saturationRaw: d = 1, bgOpacityRaw: f = .3, revealEffect: g = !1, chars: y = o, mouseEffect: b = !0, clickEffect: x = !0, charMode: S = "shape", className: C, cropFocus: w = "center" }) {
358
- let T = t(null), E = t(null), D = t(null), O = t(null), k = t(null), { numCols: A, brightness: j, saturation: M, bgOpacity: N, mouseEnabled: P, mouseStyle: F, brightenEnabled: I, scatterEnabled: L, scatterChars: R, trailLen: z, trailDecay: B, duration: V, mouseRadius: H, mouseBrightness: U, clickEnabled: W, clickBrightness: G, clickSpeed: K, spreadEnabled: q, spreadExpandDuration: J, spreadSpeed: Y, revealEnabled: ee, revealDuration: te, revealEffectFlag: ne } = s(l, u, d, f, b, x, g), re = t(j), ie = t(M), ae = t(N), oe = t(P), se = t(F), X = t(I), Z = t(L), ce = t(U), le = t(H), ue = t(z), de = t(B), fe = t(V), Q = t(R), pe = t(W), me = t(G), he = t(K), ge = t(q), _e = t(J), ve = t(Y), ye = t(A), be = t(c), xe = t(w), Se = t(0), Ce = t(0);
402
+ function S({ src: i, mediaType: s = "auto", videoMode: u = !1, numColsRaw: d = 250, brightnessRaw: f = 1, saturationRaw: p = 1, bgOpacityRaw: m = .3, revealEffect: v = !1, chars: S = o, mouseEffect: C = !0, clickEffect: w = !0, charMode: T = "shape", className: E, cropFocus: D = "center", maxDpr: O }) {
403
+ let k = t(null), A = t(null), j = t(null), M = t(null), ee = t(null), te = t(null), { numCols: N, brightness: P, saturation: F, bgOpacity: I, mouseEnabled: L, mouseStyle: R, brightenEnabled: z, scatterEnabled: B, scatterChars: V, trailLen: H, trailDecay: U, duration: ne, mouseRadius: re, mouseBrightness: W, clickEnabled: G, clickBrightness: K, clickSpeed: q, spreadEnabled: J, spreadExpandDuration: Y, spreadSpeed: X, revealEnabled: ie, revealDuration: ae, revealEffectFlag: oe, maxDpr: Z } = l(d, f, p, m, C, w, v, O), se = c(i, s) === "image", ce = t(P), le = t(F), ue = t(I), de = t(L), fe = t(R), pe = t(z), me = t(B), he = t(W), ge = t(re), _e = t(H), ve = t(U), ye = t(ne), Q = t(V), be = t(G), xe = t(K), Se = t(q), Ce = t(J), we = t(Y), Te = t(X), Ee = t(N), De = t(u), Oe = t(D), ke = t(0), Ae = t(0), je = t(Z), Me = t(1), Ne = t(null), Pe = t(null);
359
404
  e(() => {
360
- re.current = j, ie.current = M, ae.current = N, oe.current = P, se.current = F, X.current = I, Z.current = L, ce.current = U, le.current = H, ue.current = z, de.current = B, fe.current = V, Q.current !== R && $.current ? (Q.current = R, Te.current?.()) : Q.current = R, pe.current = W, me.current = G, he.current = K, ge.current = q, _e.current = J, ve.current = Y, ye.current = A, be.current = c;
405
+ ce.current = P, le.current = F, ue.current = I, de.current = L, fe.current = R, pe.current = z, me.current = B, he.current = W, ge.current = re, _e.current = H, ve.current = U, ye.current = ne, Q.current !== V && $.current ? (Q.current = V, Ie.current?.()) : Q.current = V, be.current = G, xe.current = K, Se.current = q, Ce.current = J, we.current = Y, Te.current = X, Ee.current = N, De.current = u;
361
406
  }, [
362
- j,
363
- M,
364
- N,
365
407
  P,
366
408
  F,
367
409
  I,
368
410
  L,
369
- U,
370
- H,
411
+ R,
371
412
  z,
372
413
  B,
373
- V,
374
- R,
375
414
  W,
415
+ re,
416
+ H,
417
+ U,
418
+ ne,
419
+ V,
376
420
  G,
377
421
  K,
378
422
  q,
379
423
  J,
380
424
  Y,
381
- A,
382
- c
425
+ X,
426
+ N,
427
+ u
383
428
  ]);
384
- let we = t(null), Te = t(null), Ee = t(null), $ = t(!1);
385
- return e(() => {
386
- $.current && we.current?.(A);
387
- }, [A]), e(() => {
388
- xe.current = w, $.current && Se.current > 0 && Ee.current?.(Se.current, Ce.current);
389
- }, [w]), e(() => {
429
+ let Fe = t(null), Ie = t(null), Le = t(null), $ = t(!1);
430
+ e(() => {
431
+ $.current && Fe.current?.(N);
432
+ }, [N]), e(() => {
433
+ Oe.current = D, $.current && ke.current > 0 && Le.current?.(ke.current, Ae.current);
434
+ }, [D]), e(() => {
435
+ je.current = Z, $.current && Ne.current && Pe.current?.(Ne.current);
436
+ }, [Z]), e(() => {
390
437
  $.current = !1;
391
- let e = [], t = 0, n = 0, r = 1, o = 1, s = 0, c = 0, l = T.current;
392
- if (!l) return;
393
- let u = E.current;
394
- if (!u) return;
395
- let d = l.getContext("webgl2");
438
+ let e = [], t = 0, n = 0, r = 1, o = 1, s = 0, c = 0, l = 0, u = 0, d = k.current;
396
439
  if (!d) return;
397
- d.pixelStorei(d.UNPACK_ALIGNMENT, 1);
398
- let f = p(d);
440
+ let f = se ? j.current : A.current;
399
441
  if (!f) return;
400
- let { program: g, pass1Program: b } = f;
401
- O.current = f.atlasTexture, k.current = f.scatterAtlasTexture, d.uniform1i(f.shapeMatchingLoc, +(S === "shape")), d.uniform1i(f.revealEffectFlagLoc, ne), d.uniform1f(f.revealProgressLoc, 0);
402
- let x = m({
403
- scatterEnabledRef: Z,
404
- mouseRadiusRef: le,
405
- durationRef: fe,
442
+ let p = f instanceof HTMLVideoElement ? f : null, m = f instanceof HTMLImageElement ? f : null, v = () => f instanceof HTMLVideoElement ? {
443
+ width: f.videoWidth,
444
+ height: f.videoHeight
445
+ } : {
446
+ width: f.naturalWidth,
447
+ height: f.naturalHeight
448
+ }, C = d.getContext("webgl2");
449
+ if (!C) return;
450
+ C.pixelStorei(C.UNPACK_ALIGNMENT, 1);
451
+ let w = h(C);
452
+ if (!w) return;
453
+ let { program: E, pass1Program: D } = w;
454
+ ee.current = w.atlasTexture, te.current = w.scatterAtlasTexture, C.uniform1i(w.shapeMatchingLoc, +(T === "shape")), C.uniform1i(w.revealEffectFlagLoc, oe), C.uniform1f(w.revealProgressLoc, 0);
455
+ let O = g({
456
+ scatterEnabledRef: me,
457
+ mouseRadiusRef: ge,
458
+ durationRef: ye,
406
459
  scatterCharsRef: Q
407
- }), C = h({
408
- brightenEnabledRef: X,
409
- trailLenRef: ue,
410
- durationRef: fe,
411
- trailDecayRef: de
412
- }), w = _({
413
- clickEnabledRef: pe,
414
- clickSpeedRef: he,
415
- clickBrightnessRef: me
416
- }), A = v({
417
- spreadEnabledRef: ge,
460
+ }), N = _({
461
+ brightenEnabledRef: pe,
462
+ trailLenRef: _e,
463
+ durationRef: ye,
464
+ trailDecayRef: ve
465
+ }), P = y({
466
+ clickEnabledRef: be,
467
+ clickSpeedRef: Se,
468
+ clickBrightnessRef: xe,
469
+ pixelScaleRef: Me
470
+ }), F = b({
471
+ spreadEnabledRef: Ce,
418
472
  scatterCharsRef: Q,
419
- spreadExpandDurationRef: _e,
420
- spreadSpeedRef: ve
421
- }), j, M = -1, N = -1, P = 0, F = Array.isArray(i) ? i : [i], I = F.length > 1, L = document.createElement("canvas"), R = L.getContext("2d"), z = (i) => {
422
- let u = s > 0 ? s : l.width, p = c > 0 ? c : l.height;
423
- r = Math.max(1, Math.floor(u / i));
473
+ spreadExpandDurationRef: we,
474
+ spreadSpeedRef: Te
475
+ }), I, L = -1, R = -1, z = 0, B = Array.isArray(i) ? i : [i], V = B.length > 1, H = document.createElement("canvas"), U = H.getContext("2d"), ne = (i) => {
476
+ let f = l > 0 ? l : d.width, p = u > 0 ? u : d.height;
477
+ r = Math.max(1, Math.floor(f / i));
424
478
  let m = r * 2;
425
- if (R.font = `${m}px monospace`, o = Math.max(1, Math.round(m * r / R.measureText("M").width)), t = Math.floor(u / r), n = Math.floor(p / o), l.width = t * r, l.height = n * o, d.viewport(0, 0, l.width, l.height), d.useProgram(g), d.uniform2f(f.resLoc, l.width, l.height), d.useProgram(b), d.uniform2f(f.p1ResLoc, l.width, l.height), d.useProgram(g), x.setup(d, t, n, r, o, f.scatterStateTexture), A.setup(d, t, n, r, o, f.spreadStateTexture), S === "shape") {
426
- e = a(y, r, o);
479
+ if (U.font = `${m}px monospace`, o = Math.max(1, Math.round(m * r / U.measureText("M").width)), t = Math.ceil(f / r), n = Math.ceil(p / o), s = Math.floor((f - t * r) / 2), c = Math.floor((p - n * o) / 2), C.viewport(0, 0, d.width, d.height), C.useProgram(E), C.uniform2f(w.resLoc, d.width, d.height), C.uniform2f(w.gridOffsetLoc, s, c), C.useProgram(D), C.uniform2f(w.p1ResLoc, d.width, d.height), C.uniform2f(w.p1GridOffsetLoc, s, c), C.useProgram(E), O.setup(C, t, n, r, o, s, c, w.scatterStateTexture), F.setup(C, t, n, r, o, s, c, w.spreadStateTexture), T === "shape") {
480
+ e = a(S, r, o);
427
481
  let i = e.length, s = new Float32Array(i * 8);
428
482
  for (let t = 0; t < i; t++) {
429
483
  let n = e[t].vector;
430
484
  s[t * 4 + 0] = n[0], s[t * 4 + 1] = n[1], s[t * 4 + 2] = n[2], s[t * 4 + 3] = n[3], s[i * 4 + t * 4 + 0] = n[4], s[i * 4 + t * 4 + 1] = n[5];
431
485
  }
432
- d.activeTexture(d.TEXTURE2), d.bindTexture(d.TEXTURE_2D, f.charVectorsTexture), d.texImage2D(d.TEXTURE_2D, 0, d.RGBA32F, i, 2, 0, d.RGBA, d.FLOAT, s), d.activeTexture(d.TEXTURE3), d.bindTexture(d.TEXTURE_2D, f.fboTexture), d.texImage2D(d.TEXTURE_2D, 0, d.R8UI, t, n, 0, d.RED_INTEGER, d.UNSIGNED_BYTE, null), d.bindFramebuffer(d.FRAMEBUFFER, f.fbo), d.framebufferTexture2D(d.FRAMEBUFFER, d.COLOR_ATTACHMENT0, d.TEXTURE_2D, f.fboTexture, 0), d.bindFramebuffer(d.FRAMEBUFFER, null);
486
+ C.activeTexture(C.TEXTURE2), C.bindTexture(C.TEXTURE_2D, w.charVectorsTexture), C.texImage2D(C.TEXTURE_2D, 0, C.RGBA32F, i, 2, 0, C.RGBA, C.FLOAT, s), C.activeTexture(C.TEXTURE3), C.bindTexture(C.TEXTURE_2D, w.fboTexture), C.texImage2D(C.TEXTURE_2D, 0, C.R8UI, t, n, 0, C.RED_INTEGER, C.UNSIGNED_BYTE, null), C.bindFramebuffer(C.FRAMEBUFFER, w.fbo), C.framebufferTexture2D(C.FRAMEBUFFER, C.COLOR_ATTACHMENT0, C.TEXTURE_2D, w.fboTexture, 0), C.bindFramebuffer(C.FRAMEBUFFER, null);
433
487
  let c = Math.max(1, Math.round(r / 5));
434
- d.useProgram(b), d.uniform2f(f.p1CellsizeLoc, r, o), d.uniform1i(f.p1CircleNLoc, c), d.uniform1i(f.p1NumCharsLoc, i), d.uniform1f(f.p1ExponentLoc, 2), d.useProgram(g);
488
+ C.useProgram(D), C.uniform2f(w.p1CellsizeLoc, r, o), C.uniform1i(w.p1CircleNLoc, c), C.uniform1i(w.p1NumCharsLoc, i), C.uniform1f(w.p1ExponentLoc, 2), C.useProgram(E);
435
489
  }
436
- d.uniform2f(f.gridSizeLoc, t, n), L.width = y.length * r, L.height = o, R.font = `${o}px monospace`, R.fillStyle = "black", R.fillRect(0, 0, y.length * r, o), R.fillStyle = "white", R.textBaseline = "top";
437
- for (let e = 0; e < y.length; e++) R.fillText(y[e], e * r, 0);
438
- d.activeTexture(d.TEXTURE1), d.bindTexture(d.TEXTURE_2D, O.current), d.texImage2D(d.TEXTURE_2D, 0, d.RGBA, d.RGBA, d.UNSIGNED_BYTE, L), d.uniform1f(f.numLoc, y.length), d.uniform2f(f.sizeLoc, r, o), B();
439
- }, B = () => {
490
+ C.uniform2f(w.gridSizeLoc, t, n), H.width = S.length * r, H.height = o, U.font = `${o}px monospace`, U.fillStyle = "black", U.fillRect(0, 0, S.length * r, o), U.fillStyle = "white", U.textBaseline = "top";
491
+ for (let e = 0; e < S.length; e++) U.fillText(S[e], e * r, 0);
492
+ C.activeTexture(C.TEXTURE1), C.bindTexture(C.TEXTURE_2D, ee.current), C.texImage2D(C.TEXTURE_2D, 0, C.RGBA, C.RGBA, C.UNSIGNED_BYTE, H), C.uniform1f(w.numLoc, S.length), C.uniform2f(w.sizeLoc, r, o), re();
493
+ }, re = () => {
440
494
  let e = Q.current;
441
- L.width = e.length * r, L.height = o, R.fillStyle = "black", R.fillRect(0, 0, L.width, o), R.fillStyle = "white", R.textBaseline = "top", R.font = `${o}px monospace`;
442
- for (let t = 0; t < e.length; t++) R.fillText(e[t], t * r, 0);
443
- d.activeTexture(d.TEXTURE4), d.bindTexture(d.TEXTURE_2D, k.current), d.texImage2D(d.TEXTURE_2D, 0, d.RGBA, d.RGBA, d.UNSIGNED_BYTE, L), d.uniform1f(f.scatterNumCharsLoc, e.length), x.reset(d);
495
+ H.width = e.length * r, H.height = o, U.fillStyle = "black", U.fillRect(0, 0, H.width, o), U.fillStyle = "white", U.textBaseline = "top", U.font = `${o}px monospace`;
496
+ for (let t = 0; t < e.length; t++) U.fillText(e[t], t * r, 0);
497
+ C.activeTexture(C.TEXTURE4), C.bindTexture(C.TEXTURE_2D, te.current), C.texImage2D(C.TEXTURE_2D, 0, C.RGBA, C.RGBA, C.UNSIGNED_BYTE, H), C.uniform1f(w.scatterNumCharsLoc, e.length), O.reset(C);
444
498
  };
445
- we.current = z, Te.current = B;
446
- let V = (e, t) => {
447
- s = Math.round(e), c = Math.round(t), Se.current = s, Ce.current = c, l.width = s, l.height = c, z(ye.current);
448
- let n = u.videoWidth / u.videoHeight, r = l.width / l.height, i = 1, a = 1, o = 0, p = 0;
449
- if (r > n) a = n / r, p = (1 - a) / 2;
499
+ Fe.current = ne, Ie.current = re;
500
+ let W = (e, t) => {
501
+ l = Math.round(e), u = Math.round(t), ke.current = l, Ae.current = u, d.width = l, d.height = u, ne(Ee.current);
502
+ let n = v(), r = n.width / n.height, i = d.width / d.height, a = 1, o = 1, s = 0, c = 0;
503
+ if (i > r) o = r / i, c = (1 - o) / 2;
450
504
  else {
451
- i = r / n;
452
- let e = xe.current, t = e === "left" ? .25 : e === "right" ? .75 : .5;
453
- o = Math.max(0, Math.min(1 - i, t - i / 2));
505
+ a = i / r;
506
+ let e = Oe.current, t = e === "left" ? .25 : e === "right" ? .75 : .5;
507
+ s = Math.max(0, Math.min(1 - a, t - a / 2));
454
508
  }
455
- d.uniform2f(f.cropOffsetLoc, o, p), d.uniform2f(f.cropScaleLoc, i, a), d.useProgram(b), d.uniform2f(f.p1CropOffsetLoc, o, p), d.uniform2f(f.p1CropScaleLoc, i, a), d.useProgram(g);
509
+ C.uniform2f(w.cropOffsetLoc, s, c), C.uniform2f(w.cropScaleLoc, a, o), C.useProgram(D), C.uniform2f(w.p1CropOffsetLoc, s, c), C.uniform2f(w.p1CropScaleLoc, a, o), C.useProgram(E);
510
+ };
511
+ Le.current = W;
512
+ let G = (e) => {
513
+ Ne.current = e;
514
+ let t = Math.min(1, je.current / (window.devicePixelRatio || 1)), n = Math.max(1, Math.round(e.width * t)), r = Math.max(1, Math.round(e.height * t));
515
+ Me.current = e.cssWidth > 0 ? n / e.cssWidth : 1, W(n, r);
456
516
  };
457
- Ee.current = V;
458
- let H = (e) => {
459
- if (!oe.current) return;
460
- let t = l.getBoundingClientRect(), n = (e.clientX - t.left) * (l.width / t.width), r = (e.clientY - t.top) * (l.height / t.height), i = performance.now();
461
- C.handleMouseMove(n, r, i), x.handleMouseMove(n, r, i);
517
+ Pe.current = G;
518
+ let K = (e) => {
519
+ if (!de.current) return;
520
+ let t = d.getBoundingClientRect(), n = (e.clientX - t.left) * (d.width / t.width), r = (e.clientY - t.top) * (d.height / t.height), i = performance.now();
521
+ N.handleMouseMove(n, r, i), O.handleMouseMove(n, r, i);
462
522
  };
463
- l.addEventListener("mousemove", H);
464
- let U = () => x.handleMouseLeave();
465
- l.addEventListener("mouseleave", U);
466
- let W = (e) => {
467
- w.handleClick(e, l), A.handleClick(e, l);
523
+ d.addEventListener("mousemove", K);
524
+ let q = () => O.handleMouseLeave();
525
+ d.addEventListener("mouseleave", q);
526
+ let J = (e) => {
527
+ P.handleClick(e, d), F.handleClick(e, d);
468
528
  };
469
- l.addEventListener("click", W);
470
- let G = () => {
471
- if (d.uniform1i(f.videoModeLoc, +!!be.current), d.uniform1f(f.brightnessLoc, re.current), d.uniform1f(f.saturationLoc, ie.current), d.uniform1f(f.bgOpacityLoc, ae.current), d.uniform1i(f.mouseEffectFlagLoc, +!!X.current), d.uniform1i(f.scatterEffectFlagLoc, +!!Z.current), d.uniform1i(f.clickEffectFlagLoc, +!!pe.current), d.uniform1i(f.spreadEffectFlagLoc, +!!ge.current), d.uniform1f(f.mouseBrightnessLoc, ce.current), d.uniform1f(f.mouseRadiusLoc, Math.min(l.width, l.height) * le.current), ee) {
472
- let e = N < 0 ? 0 : Math.min(1, (performance.now() - N) / (te * 1e3));
473
- d.uniform1f(f.revealProgressLoc, e);
529
+ d.addEventListener("click", J);
530
+ let Y = () => {
531
+ if (C.uniform1i(w.videoModeLoc, +!!De.current), C.uniform1f(w.brightnessLoc, ce.current), C.uniform1f(w.saturationLoc, le.current), C.uniform1f(w.bgOpacityLoc, ue.current), C.uniform1i(w.mouseEffectFlagLoc, +!!pe.current), C.uniform1i(w.scatterEffectFlagLoc, +!!me.current), C.uniform1i(w.clickEffectFlagLoc, +!!be.current), C.uniform1i(w.spreadEffectFlagLoc, +!!Ce.current), C.uniform1f(w.mouseBrightnessLoc, he.current), C.uniform1f(w.mouseRadiusLoc, Math.min(d.width, d.height) * ge.current), ie) {
532
+ let e = R < 0 ? 0 : Math.min(1, (performance.now() - R) / (ae * 1e3));
533
+ C.uniform1f(w.revealProgressLoc, e);
474
534
  }
475
- $.current && u.currentTime != M && u.readyState >= 2 && (d.activeTexture(d.TEXTURE0), d.bindTexture(d.TEXTURE_2D, f.texture), d.texSubImage2D(d.TEXTURE_2D, 0, 0, 0, d.RGBA, d.UNSIGNED_BYTE, u), M = u.currentTime), C.tick(d, f.mousePositionsLoc, f.mouseLifeFracsLoc), x.tick(d, l), w.tick(d, l, f.ripplePositionsLoc, f.rippleRadiiLoc, f.rippleBrightnessesLoc), A.tick(d), S === "shape" && (d.bindFramebuffer(d.FRAMEBUFFER, f.fbo), d.viewport(0, 0, t, n), d.useProgram(b), d.drawArrays(d.TRIANGLES, 0, 6), d.bindFramebuffer(d.FRAMEBUFFER, null), d.viewport(0, 0, l.width, l.height), d.useProgram(g)), d.drawArrays(d.TRIANGLES, 0, 6), j = requestAnimationFrame(G);
476
- }, K = () => {
477
- let e = D.current;
478
- V(e.clientWidth || u.videoWidth, e.clientHeight || u.videoHeight), d.activeTexture(d.TEXTURE0), d.bindTexture(d.TEXTURE_2D, f.texture), d.texImage2D(d.TEXTURE_2D, 0, d.RGBA, d.RGBA, d.UNSIGNED_BYTE, u), u.play(), N = performance.now(), $.current = !0, j = requestAnimationFrame(G);
479
- }, q = () => {
480
- P = (P + 1) % F.length, u.src = F[P], u.load(), u.addEventListener("canplay", () => u.play(), { once: !0 });
481
- }, J = new ResizeObserver((e) => {
482
- let { width: t, height: n } = e[0].contentRect;
483
- $.current && t > 0 && n > 0 && V(t, n);
484
- });
485
- return D.current && J.observe(D.current), u.addEventListener("loadeddata", K, { once: !0 }), I && u.addEventListener("ended", q), u.readyState >= 2 && u.currentSrc.endsWith(F[0]) ? K() : u.currentSrc.endsWith(F[0]) || u.load(), () => {
486
- J.disconnect(), we.current = null, Te.current = null, Ee.current = null, $.current = !1, cancelAnimationFrame(j), u.removeEventListener("loadeddata", K), I && u.removeEventListener("ended", q), l.removeEventListener("mousemove", H), l.removeEventListener("mouseleave", U), l.removeEventListener("click", W), d.deleteTexture(f.texture), d.deleteTexture(f.charVectorsTexture), d.deleteFramebuffer(f.fbo), d.deleteTexture(f.fboTexture), d.deleteBuffer(f.buffer), d.deleteShader(f.vertShader), d.deleteShader(f.fragShader), d.deleteShader(f.pass1FragShader), d.deleteProgram(g), d.deleteProgram(b), d.deleteTexture(O.current), d.deleteTexture(k.current), d.deleteTexture(f.scatterStateTexture), d.deleteTexture(f.spreadStateTexture);
535
+ $.current && p && p.currentTime != L && p.readyState >= 2 && (C.activeTexture(C.TEXTURE0), C.bindTexture(C.TEXTURE_2D, w.texture), C.texSubImage2D(C.TEXTURE_2D, 0, 0, 0, C.RGBA, C.UNSIGNED_BYTE, p), L = p.currentTime), N.tick(C, w.mousePositionsLoc, w.mouseLifeFracsLoc), O.tick(C, d), P.tick(C, d, w.ripplePositionsLoc, w.rippleRadiiLoc, w.rippleBrightnessesLoc), F.tick(C), T === "shape" && (C.bindFramebuffer(C.FRAMEBUFFER, w.fbo), C.viewport(0, 0, t, n), C.useProgram(D), C.drawArrays(C.TRIANGLES, 0, 6), C.bindFramebuffer(C.FRAMEBUFFER, null), C.viewport(0, 0, d.width, d.height), C.useProgram(E)), C.drawArrays(C.TRIANGLES, 0, 6), I = requestAnimationFrame(Y);
536
+ }, X = () => {
537
+ let e = M.current, t = Ne.current;
538
+ if (t && t.width > 0 && t.height > 0) G(t);
539
+ else {
540
+ let t = window.devicePixelRatio || 1, n = v(), r = e.clientWidth || n.width, i = e.clientHeight || n.height;
541
+ G({
542
+ width: Math.round(r * t),
543
+ height: Math.round(i * t),
544
+ cssWidth: r,
545
+ cssHeight: i
546
+ });
547
+ }
548
+ C.activeTexture(C.TEXTURE0), C.bindTexture(C.TEXTURE_2D, w.texture), C.texImage2D(C.TEXTURE_2D, 0, C.RGBA, C.RGBA, C.UNSIGNED_BYTE, f), p?.play(), R = performance.now(), $.current = !0, I = requestAnimationFrame(Y);
549
+ }, Z = () => {
550
+ p && (z = (z + 1) % B.length, p.src = B[z], p.load(), p.addEventListener("canplay", () => p.play(), { once: !0 }));
551
+ }, fe = M.current ? x(M.current, (e) => {
552
+ Ne.current = e, $.current && e.width > 0 && e.height > 0 && G(e);
553
+ }) : () => {};
554
+ return p ? (p.addEventListener("loadeddata", X, { once: !0 }), V && p.addEventListener("ended", Z), p.readyState >= 2 && p.currentSrc.endsWith(B[0]) ? X() : p.currentSrc.endsWith(B[0]) || p.load()) : m && (m.complete && m.naturalWidth > 0 ? X() : m.addEventListener("load", X, { once: !0 })), () => {
555
+ fe(), Fe.current = null, Ie.current = null, Le.current = null, Pe.current = null, $.current = !1, cancelAnimationFrame(I), p ? (p.removeEventListener("loadeddata", X), V && p.removeEventListener("ended", Z)) : m?.removeEventListener("load", X), d.removeEventListener("mousemove", K), d.removeEventListener("mouseleave", q), d.removeEventListener("click", J), C.deleteTexture(w.texture), C.deleteTexture(w.charVectorsTexture), C.deleteFramebuffer(w.fbo), C.deleteTexture(w.fboTexture), C.deleteBuffer(w.buffer), C.deleteShader(w.vertShader), C.deleteShader(w.fragShader), C.deleteShader(w.pass1FragShader), C.deleteProgram(E), C.deleteProgram(D), C.deleteTexture(ee.current), C.deleteTexture(te.current), C.deleteTexture(w.scatterStateTexture), C.deleteTexture(w.spreadStateTexture);
487
556
  };
488
557
  }, [
489
558
  i,
559
+ T,
490
560
  S,
491
- y,
492
- ne,
493
- te,
494
- ee
495
- ]), /* @__PURE__ */ r("div", {
496
- ref: D,
497
- className: C,
561
+ oe,
562
+ ae,
563
+ ie,
564
+ se
565
+ ]);
566
+ let Re = Array.isArray(i) ? i[0] : i;
567
+ return /* @__PURE__ */ r("div", {
568
+ ref: M,
569
+ className: E,
498
570
  style: {
499
571
  height: "100%",
500
572
  width: "100%"
501
573
  },
502
- children: [/* @__PURE__ */ n("video", {
503
- ref: E,
574
+ children: [se ? /* @__PURE__ */ n("img", {
575
+ ref: j,
576
+ src: Re,
577
+ alt: "",
578
+ style: { display: "none" }
579
+ }) : /* @__PURE__ */ n("video", {
580
+ ref: A,
504
581
  muted: !0,
505
582
  playsInline: !0,
506
583
  autoPlay: !0,
507
584
  loop: !Array.isArray(i) || i.length === 1,
508
585
  style: { display: "none" },
509
586
  children: /* @__PURE__ */ n("source", {
510
- src: Array.isArray(i) ? i[0] : i,
587
+ src: Re,
511
588
  type: "video/mp4"
512
589
  })
513
590
  }), /* @__PURE__ */ n("canvas", {
514
- ref: T,
591
+ ref: k,
515
592
  style: {
516
593
  width: "100%",
517
594
  height: "100%",
@@ -521,4 +598,4 @@ function y({ src: i, videoMode: c = !1, numColsRaw: l = 250, brightnessRaw: u =
521
598
  });
522
599
  }
523
600
  //#endregion
524
- export { y as VideoAscii };
601
+ export { S as VideoAscii };
@@ -1,10 +1,10 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactVideoAscii={},e.React,e.ReactJSXRuntime))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=[[.25,.25],[.75,.25],[.25,.5],[.75,.5],[.25,.75],[.75,.75]];function i(e,t,n){let i=[],a=document.createElement(`canvas`);a.width=t,a.height=n;let o=a.getContext(`2d`,{willReadFrequently:!0});if(!o)return[];o.font=`${n}px monospace`,o.textBaseline=`top`;let s=t/5;for(let a of e){o.fillStyle=`black`,o.fillRect(0,0,t,n),o.fillStyle=`white`,o.fillText(a,0,0);let e=o.getImageData(0,0,t,n),c=[];for(let[i,a]of r){let r=i*t,o=a*n,l=0,u=0;for(let n=Math.floor(r-s);n<=Math.ceil(r+s);n+=1)for(let i=Math.floor(o-s);i<=Math.ceil(o+s);i+=1){let a=r-n,c=o-i;if(a*a+c*c<=s*s){let r=(i*t+n)*4,a=e.data[r];l+=a/255,u++}}let d=u>0?l/u:0;c.push(d)}i.push({char:a,vector:c})}let c=[,,,,,,].fill(0);for(let{vector:e}of i)for(let t=0;t<6;++t)e[t]>c[t]&&(c[t]=e[t]);for(let{vector:e}of i)for(let t=0;t<6;++t)e[t]/=c[t];return i}var a=` \`.',-_:!;|"~+^lr[](\\/L)>t<v=Tz?icf1{sIxY*jJno}CZyVwmSXRqM$O%#9&NW0Q@`;function o(e,t,n,r,i,a,o){let s=!!i,c=typeof i==`object`?i:{},l=c.style??`brighten`,u=s&&l!==`scatter`,d=s&&l===`scatter`,f=c.scatterChars??`->o`,p=c.trailLen??15,m=c.trailDecay??10,h=c.duration??1,g=c.radius??(l===`scatter`?.05:.08),_=c.brightness??2,v=!!a,y=typeof a==`object`?a:{},b=y.style??`ripple`,x=v&&b!==`spread`,S=v&&b===`spread`,C=y.brightness??1.1,w=y.speed??2,T=y.spreadExpandDuration??1.5,E=y.spreadSpeed??7.5,D=!!o,O=typeof o==`object`?o:{},k=O.type??`random`,A=O.duration??.4,j=Math.max(20,Math.min(350,Math.round(e))),M=Math.max(0,Math.min(2,t)),N=Math.max(0,Math.min(2,n)),P=Math.max(0,Math.min(1,r));A=Math.max(.1,Math.min(4,A)),p=Math.max(0,Math.min(30,Math.round(p))),m=Math.max(1,Math.min(15,m)),h=Math.max(.1,Math.min(4,h)),g=Math.max(.03,Math.min(.2,g)),_=Math.max(.2,Math.min(5,_)),C=Math.max(1.05,Math.min(2,C)),w=Math.max(.5,Math.min(4,w)),T=Math.max(.5,Math.min(5,T)),E=Math.max(.5,Math.min(10,E));let F;return F=D?k===`diagonal`?1:k===`radial`?2:3:0,{numCols:j,brightness:M,saturation:N,bgOpacity:P,mouseEnabled:s,mouseStyle:l,brightenEnabled:u,scatterEnabled:d,scatterChars:f,trailLen:p,trailDecay:m,duration:h,mouseRadius:g,mouseBrightness:_,clickEnabled:x,clickBrightness:C,clickSpeed:w,spreadEnabled:S,spreadExpandDuration:T,spreadSpeed:E,revealEnabled:D,revealType:k,revealDuration:A,revealEffectFlag:F}}function s(e,t,n){let r=e.createShader(t);if(!r)throw Error(`Failed to create shader`);return e.shaderSource(r,n),e.compileShader(r),e.getShaderParameter(r,e.COMPILE_STATUS)?r:(console.log(e.getShaderInfoLog(r)),e.deleteShader(r),null)}function c(e,t,n){let r=e.createProgram();return e.attachShader(r,t),e.attachShader(r,n),e.linkProgram(r),e.getProgramParameter(r,e.LINK_STATUS)?r:(console.log(e.getProgramInfoLog(r)),e.deleteProgram(r),null)}var l=`#version 300 es
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`react`),require(`react/jsx-runtime`)):typeof define==`function`&&define.amd?define([`exports`,`react`,`react/jsx-runtime`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.ReactVideoAscii={},e.React,e.ReactJSXRuntime))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=[[.25,.25],[.75,.25],[.25,.5],[.75,.5],[.25,.75],[.75,.75]];function i(e,t,n){let i=[],a=document.createElement(`canvas`);a.width=t,a.height=n;let o=a.getContext(`2d`,{willReadFrequently:!0});if(!o)return[];o.font=`${n}px monospace`,o.textBaseline=`top`;let s=t/5;for(let a of e){o.fillStyle=`black`,o.fillRect(0,0,t,n),o.fillStyle=`white`,o.fillText(a,0,0);let e=o.getImageData(0,0,t,n),c=[];for(let[i,a]of r){let r=i*t,o=a*n,l=0,u=0;for(let n=Math.floor(r-s);n<=Math.ceil(r+s);n+=1)for(let i=Math.floor(o-s);i<=Math.ceil(o+s);i+=1){let a=r-n,c=o-i;if(a*a+c*c<=s*s){let r=(i*t+n)*4,a=e.data[r];l+=a/255,u++}}let d=u>0?l/u:0;c.push(d)}i.push({char:a,vector:c})}let c=[,,,,,,].fill(0);for(let{vector:e}of i)for(let t=0;t<6;++t)e[t]>c[t]&&(c[t]=e[t]);for(let{vector:e}of i)for(let t=0;t<6;++t)e[t]/=c[t];return i}var a=` \`.',-_:!;|"~+^lr[](\\/L)>t<v=Tz?icf1{sIxY*jJno}CZyVwmSXRqM$O%#9&NW0Q@`,o=/\.(png|jpe?g|gif|webp|avif|bmp|svg)(?:[?#].*)?$/i;function s(e,t){if(t!==`auto`)return t;let n=Array.isArray(e)?e[0]:e;return o.test(n)?`image`:`video`}function c(e,t,n,r,i,a,o,s){let c=!!i,l=typeof i==`object`?i:{},u=l.style??`brighten`,d=c&&u!==`scatter`,f=c&&u===`scatter`,p=l.scatterChars??`->o`,m=l.trailLen??15,h=l.trailDecay??10,g=l.duration??1,_=l.radius??(u===`scatter`?.05:.08),v=l.brightness??2,y=!!a,b=typeof a==`object`?a:{},x=b.style??`ripple`,S=y&&x!==`spread`,C=y&&x===`spread`,w=b.brightness??1.1,T=b.speed??2,E=b.spreadExpandDuration??1.5,D=b.spreadSpeed??7.5,O=!!o,k=typeof o==`object`?o:{},A=k.type??`random`,j=k.duration??.4,ee=Math.max(20,Math.min(350,Math.round(e))),M=Math.max(0,Math.min(2,t)),N=Math.max(0,Math.min(2,n)),P=Math.max(0,Math.min(1,r));j=Math.max(.1,Math.min(4,j)),m=Math.max(0,Math.min(30,Math.round(m))),h=Math.max(1,Math.min(15,h)),g=Math.max(.1,Math.min(4,g)),_=Math.max(.03,Math.min(.2,_)),v=Math.max(.2,Math.min(5,v)),w=Math.max(1.05,Math.min(2,w)),T=Math.max(.5,Math.min(4,T)),E=Math.max(.5,Math.min(5,E)),D=Math.max(.5,Math.min(10,D));let F=s===void 0?1/0:Math.max(1,Math.min(4,s)),I;return I=O?A===`diagonal`?1:A===`radial`?2:3:0,{numCols:ee,brightness:M,saturation:N,bgOpacity:P,mouseEnabled:c,mouseStyle:u,brightenEnabled:d,scatterEnabled:f,scatterChars:p,trailLen:m,trailDecay:h,duration:g,mouseRadius:_,mouseBrightness:v,clickEnabled:S,clickBrightness:w,clickSpeed:T,spreadEnabled:C,spreadExpandDuration:E,spreadSpeed:D,revealEnabled:O,revealType:A,revealDuration:j,revealEffectFlag:I,maxDpr:F}}function l(e,t,n){let r=e.createShader(t);if(!r)throw Error(`Failed to create shader`);return e.shaderSource(r,n),e.compileShader(r),e.getShaderParameter(r,e.COMPILE_STATUS)?r:(console.log(e.getShaderInfoLog(r)),e.deleteShader(r),null)}function u(e,t,n){let r=e.createProgram();return e.attachShader(r,t),e.attachShader(r,n),e.linkProgram(r),e.getProgramParameter(r,e.LINK_STATUS)?r:(console.log(e.getProgramInfoLog(r)),e.deleteProgram(r),null)}var d=`#version 300 es
2
2
 
3
3
  in vec2 a_position;
4
4
 
5
5
  void main() {
6
6
  gl_Position = vec4(a_position, 0.0, 1.0);
7
- }`,u=`#version 300 es
7
+ }`,f=`#version 300 es
8
8
 
9
9
  precision highp float;
10
10
  precision highp usampler2D;
@@ -49,6 +49,7 @@ uniform float u_numChars;
49
49
  uniform vec2 u_gridSize;
50
50
  uniform vec2 u_cropOffset;
51
51
  uniform vec2 u_cropScale;
52
+ uniform vec2 u_gridOffset;
52
53
 
53
54
  out vec4 fragColor;
54
55
 
@@ -82,7 +83,10 @@ vec3 hsl2rgb(vec3 c) {
82
83
 
83
84
  void main() {
84
85
  vec2 fragCoord = vec2(gl_FragCoord.x, u_resolution.y - gl_FragCoord.y);
85
- vec2 cellCoord = floor(fragCoord / u_cellsize);
86
+ vec2 gridCoord = fragCoord - u_gridOffset;
87
+ vec2 cellCoordF = floor(gridCoord / u_cellsize);
88
+ bool inGrid = all(greaterThanEqual(cellCoordF, vec2(0.0))) && all(lessThan(cellCoordF, u_gridSize));
89
+ vec2 cellCoord = clamp(cellCoordF, vec2(0.0), u_gridSize - 1.0);
86
90
 
87
91
  if (u_revealEffectFlag == 1) {
88
92
 
@@ -106,7 +110,7 @@ void main() {
106
110
  }
107
111
  }
108
112
 
109
- vec2 cellCenter = (cellCoord + 0.5) * u_cellsize;
113
+ vec2 cellCenter = u_gridOffset + (cellCoord + 0.5) * u_cellsize;
110
114
 
111
115
  vec2 rawUV = u_videoMode ? (fragCoord / u_resolution) : (cellCenter / u_resolution);
112
116
  vec2 sampleUV = u_cropOffset + rawUV * u_cropScale;
@@ -118,11 +122,11 @@ void main() {
118
122
  hsl.y = clamp(hsl.y * u_saturation, 0.0, 1.0);
119
123
  cellColor = hsl2rgb(hsl);
120
124
 
121
- vec2 withinCellPos = fract(fragCoord / u_cellsize);
125
+ vec2 withinCellPos = fract(gridCoord / u_cellsize);
122
126
 
123
127
 
124
128
  float glyphMask = 0.0;
125
- if (!u_videoMode) {
129
+ if (!u_videoMode && inGrid) {
126
130
  uint charInd;
127
131
  if (u_shapeMatching) {
128
132
  charInd = texelFetch(u_fboTexture, ivec2(cellCoord), 0).r;
@@ -138,7 +142,7 @@ void main() {
138
142
 
139
143
  bool scatterHit = false;
140
144
  vec3 scatterColor = vec3(0.0);
141
- if (u_scatterEffect) {
145
+ if (u_scatterEffect && inGrid) {
142
146
  uint state = texelFetch(u_scatterStateTexture, ivec2(cellCoord), 0).r;
143
147
  if (state > 0u) {
144
148
  int idx = int(state) - 1;
@@ -151,7 +155,7 @@ void main() {
151
155
  }
152
156
  }
153
157
 
154
- if (!scatterHit && u_spreadEffect) {
158
+ if (!scatterHit && u_spreadEffect && inGrid) {
155
159
  uint state = texelFetch(u_spreadStateTexture, ivec2(cellCoord), 0).r;
156
160
  if (state > 0u) {
157
161
  int idx = int(state) - 1;
@@ -203,7 +207,7 @@ void main() {
203
207
  }
204
208
 
205
209
  fragColor = vec4(finalColor, 1.0);
206
- }`,d=`#version 300 es
210
+ }`,p=`#version 300 es
207
211
 
208
212
  precision highp float;
209
213
  precision highp usampler2D;
@@ -217,6 +221,7 @@ uniform int u_numCharsInt;
217
221
  uniform float u_shapeExponent;
218
222
  uniform vec2 u_cropOffset;
219
223
  uniform vec2 u_cropScale;
224
+ uniform vec2 u_gridOffset;
220
225
 
221
226
  out uvec4 fragCharInd;
222
227
 
@@ -234,7 +239,7 @@ void main() {
234
239
  float sv[6];
235
240
  for (int ci = 0; ci < 6; ci++) {
236
241
 
237
- vec2 centerUV = u_cropOffset + (vec2(cellCoord) + CIRCLES[ci]) * u_cellsize / u_resolution * u_cropScale;
242
+ vec2 centerUV = u_cropOffset + (u_gridOffset + (vec2(cellCoord) + CIRCLES[ci]) * u_cellsize) / u_resolution * u_cropScale;
238
243
  float total = 0.0;
239
244
  int count = 0;
240
245
  for (int dx = -u_circleN; dx <= u_circleN; dx++) {
@@ -277,4 +282,4 @@ void main() {
277
282
  }
278
283
 
279
284
  fragCharInd = uvec4(bestChar, 0u, 0u, 0u);
280
- }`;function f(e){let t=s(e,e.VERTEX_SHADER,l),n=s(e,e.FRAGMENT_SHADER,u);if(!t||!n)return null;let r=c(e,t,n);if(!r)return null;let i=new Float32Array([1,1,-1,1,1,-1,-1,-1,-1,1,1,-1]),a=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,a),e.bufferData(e.ARRAY_BUFFER,i,e.STATIC_DRAW);let o=e.getAttribLocation(r,`a_position`);e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(o),e.useProgram(r);let f=e.createTexture();e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,f),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let p=e.getUniformLocation(r,`u_texture`);e.uniform1i(p,0);let m=e.createTexture();e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,m),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let h=e.getUniformLocation(r,`u_atlas`);e.uniform1i(h,1);let g=e.createTexture();e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,g),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let _=s(e,e.FRAGMENT_SHADER,d);if(!_)return null;let v=c(e,t,_);if(!v)return null;e.useProgram(v),e.uniform1i(e.getUniformLocation(v,`u_texture`),0),e.uniform1i(e.getUniformLocation(v,`u_charVectors`),2);let y=e.getUniformLocation(v,`u_resolution`),b=e.getUniformLocation(v,`u_cellsize`),x=e.getUniformLocation(v,`u_circleN`),S=e.getUniformLocation(v,`u_numCharsInt`),C=e.getUniformLocation(v,`u_shapeExponent`),w=e.getUniformLocation(v,`u_cropOffset`),T=e.getUniformLocation(v,`u_cropScale`),E=e.createTexture();e.activeTexture(e.TEXTURE3),e.bindTexture(e.TEXTURE_2D,E),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let D=e.createFramebuffer(),O=e.createTexture();e.activeTexture(e.TEXTURE4),e.bindTexture(e.TEXTURE_2D,O),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let k=e.createTexture();e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,k),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let A=e.createTexture();return e.activeTexture(e.TEXTURE6),e.bindTexture(e.TEXTURE_2D,A),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.useProgram(r),e.uniform1i(e.getUniformLocation(r,`u_fboTexture`),3),e.uniform1i(e.getUniformLocation(r,`u_scatterAtlas`),4),e.uniform1i(e.getUniformLocation(r,`u_scatterStateTexture`),5),e.uniform1i(e.getUniformLocation(r,`u_spreadStateTexture`),6),{program:r,pass1Program:v,buffer:a,vertShader:t,fragShader:n,pass1FragShader:_,texture:f,atlasTexture:m,charVectorsTexture:g,fboTexture:E,fbo:D,scatterAtlasTexture:O,scatterStateTexture:k,spreadStateTexture:A,p1ResLoc:y,p1CellsizeLoc:b,p1CircleNLoc:x,p1NumCharsLoc:S,p1ExponentLoc:C,p1CropOffsetLoc:w,p1CropScaleLoc:T,revealEffectFlagLoc:e.getUniformLocation(r,`u_revealEffectFlag`),mouseEffectFlagLoc:e.getUniformLocation(r,`u_mouseEffect`),clickEffectFlagLoc:e.getUniformLocation(r,`u_clickEffect`),shapeMatchingLoc:e.getUniformLocation(r,`u_shapeMatching`),revealProgressLoc:e.getUniformLocation(r,`u_revealProgress`),brightnessLoc:e.getUniformLocation(r,`u_brightness`),saturationLoc:e.getUniformLocation(r,`u_saturation`),bgOpacityLoc:e.getUniformLocation(r,`u_bgOpacity`),mouseBrightnessLoc:e.getUniformLocation(r,`u_mouseBrightness`),mousePositionsLoc:e.getUniformLocation(r,`u_mousePositions`),mouseLifeFracsLoc:e.getUniformLocation(r,`u_mouseLifeFracs`),mouseRadiusLoc:e.getUniformLocation(r,`u_mouseRadius`),ripplePositionsLoc:e.getUniformLocation(r,`u_ripplePositions`),rippleRadiiLoc:e.getUniformLocation(r,`u_rippleRadii`),rippleBrightnessesLoc:e.getUniformLocation(r,`u_rippleBrightnesses`),scatterEffectFlagLoc:e.getUniformLocation(r,`u_scatterEffect`),scatterNumCharsLoc:e.getUniformLocation(r,`u_scatterNumChars`),spreadEffectFlagLoc:e.getUniformLocation(r,`u_spreadEffect`),videoModeLoc:e.getUniformLocation(r,`u_videoMode`),resLoc:e.getUniformLocation(r,`u_resolution`),sizeLoc:e.getUniformLocation(r,`u_cellsize`),numLoc:e.getUniformLocation(r,`u_numChars`),gridSizeLoc:e.getUniformLocation(r,`u_gridSize`),cropOffsetLoc:e.getUniformLocation(r,`u_cropOffset`),cropScaleLoc:e.getUniformLocation(r,`u_cropScale`)}}function p({scatterEnabledRef:e,mouseRadiusRef:t,durationRef:n,scatterCharsRef:r}){let i=new Uint8Array,a=new Float32Array,o=new Float32Array,s=new Uint8Array,c=null,l=null,u=0,d=0,f=-1,p=()=>Math.floor(Math.random()*r.current.length),m=0,h=0,g=1,_=1,v=null;return{setup(e,t,n,r,f,p){m=t,h=n,g=r,_=f,v=p;let y=t*n;i=new Uint8Array(y),a=new Float32Array(y),o=new Float32Array(y),s=new Uint8Array(y),c=null,l=null,u=0,d=0,e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,p),e.texImage2D(e.TEXTURE_2D,0,e.R8UI,t,n,0,e.RED_INTEGER,e.UNSIGNED_BYTE,i)},handleMouseMove(t,n,r){e.current&&(l=c,c={x:t,y:n,t:r})},handleMouseLeave(){c=null,l=null,u=0,d=0},reset(e){i.fill(0),v&&m>0&&(e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,v),e.texSubImage2D(e.TEXTURE_2D,0,0,0,m,h,e.RED_INTEGER,e.UNSIGNED_BYTE,i))},tick(r,y){if(!e.current||m===0||h===0)return;let b=performance.now(),x=f<0?0:Math.min(.1,(b-f)/1e3);f=b;let S=Math.min(y.width,y.height)*t.current,C=!1;if(c&&b-c.t<80){if(l){let e=(c.t-l.t)/1e3;if(e>0&&e<.2){let t=(c.x-l.x)/e,n=(c.y-l.y)/e;u=u*.7+t*.3,d=d*.7+n*.3}}else u=0,d=0;Math.hypot(u,d)>g*2&&(C=!0)}else u*=.6,d*=.6;if(s.fill(0),C&&c&&S>0){let e=c.x,t=c.y,n=Math.max(0,Math.floor((e-S)/g)),r=Math.min(m-1,Math.floor((e+S)/g)),l=Math.max(0,Math.floor((t-S)/_)),u=Math.min(h-1,Math.floor((t+S)/_));for(let c=l;c<=u;c++)for(let l=n;l<=r;l++){let n=(l+.5)*g,r=(c+.5)*_;if(Math.hypot(n-e,r-t)>S)continue;let u=c*m+l;s[u]=1,i[u]===0&&(i[u]=1+p(),o[u]=.5+Math.random()*2),a[u]=1}}let w=n.current;if(x>0)for(let e=0;e<h;e++)for(let t=0;t<m;t++){let n=e*m+t;if(i[n]===0||s[n])continue;let r=t>0?i[n-1]!==0:!1,c=t<m-1?i[n+1]!==0:!1,l=e>0?i[n-m]!==0:!1,u=e<h-1?i[n+m]!==0:!1,d=(!r||!c||!l||!u?5:1)*o[n]/w;a[n]-=d*x,a[n]<=0&&(i[n]=0)}r.activeTexture(r.TEXTURE5),r.bindTexture(r.TEXTURE_2D,v),r.texSubImage2D(r.TEXTURE_2D,0,0,0,m,h,r.RED_INTEGER,r.UNSIGNED_BYTE,i)}}}function m({brightenEnabledRef:e,trailLenRef:t,durationRef:n,trailDecayRef:r}){let i=[];return{handleMouseMove(n,r,a){e.current&&(i.push({x:n,y:r,t:a}),i.length>t.current&&i.shift())},tick(a,o,s){if(!e.current)return;let c=performance.now(),l=new Float32Array(t.current*2),u=new Float32Array(t.current);for(let e=0;e<i.length;e++){let t=c-i[e].t,a=Math.max(0,1-t/(n.current*1e3))**r.current;l[e*2]=i[e].x,l[e*2+1]=i[e].y,u[e]=a}a.uniform2fv(o,l),a.uniform1fv(s,u)}}}var h=10;function g({clickEnabledRef:e,clickSpeedRef:t,clickBrightnessRef:n}){let r=[];return{handleClick(t,n){if(!e.current)return;let i=n.getBoundingClientRect(),a=(t.clientX-i.left)*(n.width/i.width),o=(t.clientY-i.top)*(n.height/i.height);r.push({x:a,y:o,t:performance.now()}),r.length>h&&r.shift()},tick(i,a,o,s,c){if(!e.current)return;let l=performance.now(),u=Math.hypot(a.width,a.height),d=new Float32Array(h*2),f=new Float32Array(h),p=new Float32Array(h);for(;r.length>0&&(l-r[0].t)*t.current>=u;)r.shift();for(let e=0;e<r.length;e++){let i=(l-r[e].t)*t.current,a=i/u,o=1+(n.current-1)*(1-a**2);d[e*2]=r[e].x,d[e*2+1]=r[e].y,f[e]=i,p[e]=o}i.uniform2fv(o,d),i.uniform1fv(s,f),i.uniform1fv(c,p)}}}function _({spreadEnabledRef:e,scatterCharsRef:t,spreadExpandDurationRef:n,spreadSpeedRef:r}){let i=new Uint8Array,a=new Uint8Array,o=0,s=0,c=1,l=1,u=null,d=-1,f=-1,p=()=>Math.floor(Math.random()*t.current.length),m=[[-1,0],[1,0],[0,-1],[0,1]];return{setup(e,t,n,r,p,m){o=t,s=n,c=r,l=p,u=m;let h=t*n;i=new Uint8Array(h),a=new Uint8Array(h),f=-1,d=-1,e.activeTexture(e.TEXTURE6),e.bindTexture(e.TEXTURE_2D,m),e.texImage2D(e.TEXTURE_2D,0,e.R8UI,t,n,0,e.RED_INTEGER,e.UNSIGNED_BYTE,i)},handleClick(t,r){if(!e.current||o===0)return;let u=r.getBoundingClientRect(),d=(t.clientX-u.left)*(r.width/u.width),m=(t.clientY-u.top)*(r.height/u.height),h=Math.floor(d/c),g=Math.floor(m/l);if(h<0||h>=o||g<0||g>=s)return;let _=g*o+h;i[_]=1+p(),a[_]=1,f=performance.now()+n.current*1e3},tick(t){if(!e.current||o===0||s===0)return;let n=performance.now(),c=d<0?0:Math.min(.1,(n-d)/1e3);d=n;let l=f>0&&n<f;if(!l&&f>0){for(let e=0;e<i.length;e++)a[e]===1&&(a[e]=2);f=-1}if(c>0)for(let e=0;e<s;e++)for(let t=0;t<o;t++){let n=e*o+t;if(a[n]!==0){if(l&&a[n]===1)for(let[n,l]of m){let u=e+n,d=t+l;if(u<0||u>=s||d<0||d>=o)continue;let f=u*o+d;a[f]===0&&Math.random()<r.current*c&&(i[f]=1+p(),a[f]=1)}else if(a[n]===2)for(let[l,u]of m){let d=e+l,f=t+u;if(d<0||d>=s||f<0||f>=o||i[d*o+f]===0){Math.random()<r.current*c&&(i[n]=0,a[n]=0);break}}}}t.activeTexture(t.TEXTURE6),t.bindTexture(t.TEXTURE_2D,u),t.texSubImage2D(t.TEXTURE_2D,0,0,0,o,s,t.RED_INTEGER,t.UNSIGNED_BYTE,i)}}}function v({src:e,videoMode:r=!1,numColsRaw:s=250,brightnessRaw:c=1,saturationRaw:l=1,bgOpacityRaw:u=.3,revealEffect:d=!1,chars:h=a,mouseEffect:v=!0,clickEffect:y=!0,charMode:b=`shape`,className:x,cropFocus:S=`center`}){let C=(0,t.useRef)(null),w=(0,t.useRef)(null),T=(0,t.useRef)(null),E=(0,t.useRef)(null),D=(0,t.useRef)(null),{numCols:O,brightness:k,saturation:A,bgOpacity:j,mouseEnabled:M,mouseStyle:N,brightenEnabled:P,scatterEnabled:F,scatterChars:I,trailLen:L,trailDecay:R,duration:z,mouseRadius:B,mouseBrightness:V,clickEnabled:H,clickBrightness:U,clickSpeed:W,spreadEnabled:G,spreadExpandDuration:K,spreadSpeed:q,revealEnabled:ee,revealDuration:te,revealEffectFlag:ne}=o(s,c,l,u,v,y,d),re=(0,t.useRef)(k),ie=(0,t.useRef)(A),ae=(0,t.useRef)(j),oe=(0,t.useRef)(M),J=(0,t.useRef)(N),Y=(0,t.useRef)(P),X=(0,t.useRef)(F),se=(0,t.useRef)(V),Z=(0,t.useRef)(B),ce=(0,t.useRef)(L),le=(0,t.useRef)(R),ue=(0,t.useRef)(z),Q=(0,t.useRef)(I),de=(0,t.useRef)(H),fe=(0,t.useRef)(U),pe=(0,t.useRef)(W),me=(0,t.useRef)(G),he=(0,t.useRef)(K),ge=(0,t.useRef)(q),_e=(0,t.useRef)(O),ve=(0,t.useRef)(r),ye=(0,t.useRef)(S),be=(0,t.useRef)(0),xe=(0,t.useRef)(0);(0,t.useEffect)(()=>{re.current=k,ie.current=A,ae.current=j,oe.current=M,J.current=N,Y.current=P,X.current=F,se.current=V,Z.current=B,ce.current=L,le.current=R,ue.current=z,Q.current!==I&&$.current?(Q.current=I,Ce.current?.()):Q.current=I,de.current=H,fe.current=U,pe.current=W,me.current=G,he.current=K,ge.current=q,_e.current=O,ve.current=r},[k,A,j,M,N,P,F,V,B,L,R,z,I,H,U,W,G,K,q,O,r]);let Se=(0,t.useRef)(null),Ce=(0,t.useRef)(null),we=(0,t.useRef)(null),$=(0,t.useRef)(!1);return(0,t.useEffect)(()=>{$.current&&Se.current?.(O)},[O]),(0,t.useEffect)(()=>{ye.current=S,$.current&&be.current>0&&we.current?.(be.current,xe.current)},[S]),(0,t.useEffect)(()=>{$.current=!1;let t=[],n=0,r=0,a=1,o=1,s=0,c=0,l=C.current;if(!l)return;let u=w.current;if(!u)return;let d=l.getContext(`webgl2`);if(!d)return;d.pixelStorei(d.UNPACK_ALIGNMENT,1);let v=f(d);if(!v)return;let{program:y,pass1Program:x}=v;E.current=v.atlasTexture,D.current=v.scatterAtlasTexture,d.uniform1i(v.shapeMatchingLoc,+(b===`shape`)),d.uniform1i(v.revealEffectFlagLoc,ne),d.uniform1f(v.revealProgressLoc,0);let S=p({scatterEnabledRef:X,mouseRadiusRef:Z,durationRef:ue,scatterCharsRef:Q}),O=m({brightenEnabledRef:Y,trailLenRef:ce,durationRef:ue,trailDecayRef:le}),k=g({clickEnabledRef:de,clickSpeedRef:pe,clickBrightnessRef:fe}),A=_({spreadEnabledRef:me,scatterCharsRef:Q,spreadExpandDurationRef:he,spreadSpeedRef:ge}),j,M=-1,N=-1,P=0,F=Array.isArray(e)?e:[e],I=F.length>1,L=document.createElement(`canvas`),R=L.getContext(`2d`),z=e=>{let u=s>0?s:l.width,f=c>0?c:l.height;a=Math.max(1,Math.floor(u/e));let p=a*2;if(R.font=`${p}px monospace`,o=Math.max(1,Math.round(p*a/R.measureText(`M`).width)),n=Math.floor(u/a),r=Math.floor(f/o),l.width=n*a,l.height=r*o,d.viewport(0,0,l.width,l.height),d.useProgram(y),d.uniform2f(v.resLoc,l.width,l.height),d.useProgram(x),d.uniform2f(v.p1ResLoc,l.width,l.height),d.useProgram(y),S.setup(d,n,r,a,o,v.scatterStateTexture),A.setup(d,n,r,a,o,v.spreadStateTexture),b===`shape`){t=i(h,a,o);let e=t.length,s=new Float32Array(e*8);for(let n=0;n<e;n++){let r=t[n].vector;s[n*4+0]=r[0],s[n*4+1]=r[1],s[n*4+2]=r[2],s[n*4+3]=r[3],s[e*4+n*4+0]=r[4],s[e*4+n*4+1]=r[5]}d.activeTexture(d.TEXTURE2),d.bindTexture(d.TEXTURE_2D,v.charVectorsTexture),d.texImage2D(d.TEXTURE_2D,0,d.RGBA32F,e,2,0,d.RGBA,d.FLOAT,s),d.activeTexture(d.TEXTURE3),d.bindTexture(d.TEXTURE_2D,v.fboTexture),d.texImage2D(d.TEXTURE_2D,0,d.R8UI,n,r,0,d.RED_INTEGER,d.UNSIGNED_BYTE,null),d.bindFramebuffer(d.FRAMEBUFFER,v.fbo),d.framebufferTexture2D(d.FRAMEBUFFER,d.COLOR_ATTACHMENT0,d.TEXTURE_2D,v.fboTexture,0),d.bindFramebuffer(d.FRAMEBUFFER,null);let c=Math.max(1,Math.round(a/5));d.useProgram(x),d.uniform2f(v.p1CellsizeLoc,a,o),d.uniform1i(v.p1CircleNLoc,c),d.uniform1i(v.p1NumCharsLoc,e),d.uniform1f(v.p1ExponentLoc,2),d.useProgram(y)}d.uniform2f(v.gridSizeLoc,n,r),L.width=h.length*a,L.height=o,R.font=`${o}px monospace`,R.fillStyle=`black`,R.fillRect(0,0,h.length*a,o),R.fillStyle=`white`,R.textBaseline=`top`;for(let e=0;e<h.length;e++)R.fillText(h[e],e*a,0);d.activeTexture(d.TEXTURE1),d.bindTexture(d.TEXTURE_2D,E.current),d.texImage2D(d.TEXTURE_2D,0,d.RGBA,d.RGBA,d.UNSIGNED_BYTE,L),d.uniform1f(v.numLoc,h.length),d.uniform2f(v.sizeLoc,a,o),B()},B=()=>{let e=Q.current;L.width=e.length*a,L.height=o,R.fillStyle=`black`,R.fillRect(0,0,L.width,o),R.fillStyle=`white`,R.textBaseline=`top`,R.font=`${o}px monospace`;for(let t=0;t<e.length;t++)R.fillText(e[t],t*a,0);d.activeTexture(d.TEXTURE4),d.bindTexture(d.TEXTURE_2D,D.current),d.texImage2D(d.TEXTURE_2D,0,d.RGBA,d.RGBA,d.UNSIGNED_BYTE,L),d.uniform1f(v.scatterNumCharsLoc,e.length),S.reset(d)};Se.current=z,Ce.current=B;let V=(e,t)=>{s=Math.round(e),c=Math.round(t),be.current=s,xe.current=c,l.width=s,l.height=c,z(_e.current);let n=u.videoWidth/u.videoHeight,r=l.width/l.height,i=1,a=1,o=0,f=0;if(r>n)a=n/r,f=(1-a)/2;else{i=r/n;let e=ye.current,t=e===`left`?.25:e===`right`?.75:.5;o=Math.max(0,Math.min(1-i,t-i/2))}d.uniform2f(v.cropOffsetLoc,o,f),d.uniform2f(v.cropScaleLoc,i,a),d.useProgram(x),d.uniform2f(v.p1CropOffsetLoc,o,f),d.uniform2f(v.p1CropScaleLoc,i,a),d.useProgram(y)};we.current=V;let H=e=>{if(!oe.current)return;let t=l.getBoundingClientRect(),n=(e.clientX-t.left)*(l.width/t.width),r=(e.clientY-t.top)*(l.height/t.height),i=performance.now();O.handleMouseMove(n,r,i),S.handleMouseMove(n,r,i)};l.addEventListener(`mousemove`,H);let U=()=>S.handleMouseLeave();l.addEventListener(`mouseleave`,U);let W=e=>{k.handleClick(e,l),A.handleClick(e,l)};l.addEventListener(`click`,W);let G=()=>{if(d.uniform1i(v.videoModeLoc,+!!ve.current),d.uniform1f(v.brightnessLoc,re.current),d.uniform1f(v.saturationLoc,ie.current),d.uniform1f(v.bgOpacityLoc,ae.current),d.uniform1i(v.mouseEffectFlagLoc,+!!Y.current),d.uniform1i(v.scatterEffectFlagLoc,+!!X.current),d.uniform1i(v.clickEffectFlagLoc,+!!de.current),d.uniform1i(v.spreadEffectFlagLoc,+!!me.current),d.uniform1f(v.mouseBrightnessLoc,se.current),d.uniform1f(v.mouseRadiusLoc,Math.min(l.width,l.height)*Z.current),ee){let e=N<0?0:Math.min(1,(performance.now()-N)/(te*1e3));d.uniform1f(v.revealProgressLoc,e)}$.current&&u.currentTime!=M&&u.readyState>=2&&(d.activeTexture(d.TEXTURE0),d.bindTexture(d.TEXTURE_2D,v.texture),d.texSubImage2D(d.TEXTURE_2D,0,0,0,d.RGBA,d.UNSIGNED_BYTE,u),M=u.currentTime),O.tick(d,v.mousePositionsLoc,v.mouseLifeFracsLoc),S.tick(d,l),k.tick(d,l,v.ripplePositionsLoc,v.rippleRadiiLoc,v.rippleBrightnessesLoc),A.tick(d),b===`shape`&&(d.bindFramebuffer(d.FRAMEBUFFER,v.fbo),d.viewport(0,0,n,r),d.useProgram(x),d.drawArrays(d.TRIANGLES,0,6),d.bindFramebuffer(d.FRAMEBUFFER,null),d.viewport(0,0,l.width,l.height),d.useProgram(y)),d.drawArrays(d.TRIANGLES,0,6),j=requestAnimationFrame(G)},K=()=>{let e=T.current;V(e.clientWidth||u.videoWidth,e.clientHeight||u.videoHeight),d.activeTexture(d.TEXTURE0),d.bindTexture(d.TEXTURE_2D,v.texture),d.texImage2D(d.TEXTURE_2D,0,d.RGBA,d.RGBA,d.UNSIGNED_BYTE,u),u.play(),N=performance.now(),$.current=!0,j=requestAnimationFrame(G)},q=()=>{P=(P+1)%F.length,u.src=F[P],u.load(),u.addEventListener(`canplay`,()=>u.play(),{once:!0})},J=new ResizeObserver(e=>{let{width:t,height:n}=e[0].contentRect;$.current&&t>0&&n>0&&V(t,n)});return T.current&&J.observe(T.current),u.addEventListener(`loadeddata`,K,{once:!0}),I&&u.addEventListener(`ended`,q),u.readyState>=2&&u.currentSrc.endsWith(F[0])?K():u.currentSrc.endsWith(F[0])||u.load(),()=>{J.disconnect(),Se.current=null,Ce.current=null,we.current=null,$.current=!1,cancelAnimationFrame(j),u.removeEventListener(`loadeddata`,K),I&&u.removeEventListener(`ended`,q),l.removeEventListener(`mousemove`,H),l.removeEventListener(`mouseleave`,U),l.removeEventListener(`click`,W),d.deleteTexture(v.texture),d.deleteTexture(v.charVectorsTexture),d.deleteFramebuffer(v.fbo),d.deleteTexture(v.fboTexture),d.deleteBuffer(v.buffer),d.deleteShader(v.vertShader),d.deleteShader(v.fragShader),d.deleteShader(v.pass1FragShader),d.deleteProgram(y),d.deleteProgram(x),d.deleteTexture(E.current),d.deleteTexture(D.current),d.deleteTexture(v.scatterStateTexture),d.deleteTexture(v.spreadStateTexture)}},[e,b,h,ne,te,ee]),(0,n.jsxs)(`div`,{ref:T,className:x,style:{height:`100%`,width:`100%`},children:[(0,n.jsx)(`video`,{ref:w,muted:!0,playsInline:!0,autoPlay:!0,loop:!Array.isArray(e)||e.length===1,style:{display:`none`},children:(0,n.jsx)(`source`,{src:Array.isArray(e)?e[0]:e,type:`video/mp4`})}),(0,n.jsx)(`canvas`,{ref:C,style:{width:`100%`,height:`100%`,display:`block`}})]})}e.VideoAscii=v});
285
+ }`;function m(e){let t=l(e,e.VERTEX_SHADER,d),n=l(e,e.FRAGMENT_SHADER,f);if(!t||!n)return null;let r=u(e,t,n);if(!r)return null;let i=new Float32Array([1,1,-1,1,1,-1,-1,-1,-1,1,1,-1]),a=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,a),e.bufferData(e.ARRAY_BUFFER,i,e.STATIC_DRAW);let o=e.getAttribLocation(r,`a_position`);e.vertexAttribPointer(o,2,e.FLOAT,!1,0,0),e.enableVertexAttribArray(o),e.useProgram(r);let s=e.createTexture();e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,s),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR);let c=e.getUniformLocation(r,`u_texture`);e.uniform1i(c,0);let m=e.createTexture();e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,m),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let h=e.getUniformLocation(r,`u_atlas`);e.uniform1i(h,1);let g=e.createTexture();e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,g),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let _=l(e,e.FRAGMENT_SHADER,p);if(!_)return null;let v=u(e,t,_);if(!v)return null;e.useProgram(v),e.uniform1i(e.getUniformLocation(v,`u_texture`),0),e.uniform1i(e.getUniformLocation(v,`u_charVectors`),2);let y=e.getUniformLocation(v,`u_resolution`),b=e.getUniformLocation(v,`u_cellsize`),x=e.getUniformLocation(v,`u_circleN`),S=e.getUniformLocation(v,`u_numCharsInt`),C=e.getUniformLocation(v,`u_shapeExponent`),w=e.getUniformLocation(v,`u_cropOffset`),T=e.getUniformLocation(v,`u_cropScale`),E=e.getUniformLocation(v,`u_gridOffset`),D=e.createTexture();e.activeTexture(e.TEXTURE3),e.bindTexture(e.TEXTURE_2D,D),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let O=e.createFramebuffer(),k=e.createTexture();e.activeTexture(e.TEXTURE4),e.bindTexture(e.TEXTURE_2D,k),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let A=e.createTexture();e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,A),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);let j=e.createTexture();return e.activeTexture(e.TEXTURE6),e.bindTexture(e.TEXTURE_2D,j),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.useProgram(r),e.uniform1i(e.getUniformLocation(r,`u_fboTexture`),3),e.uniform1i(e.getUniformLocation(r,`u_scatterAtlas`),4),e.uniform1i(e.getUniformLocation(r,`u_scatterStateTexture`),5),e.uniform1i(e.getUniformLocation(r,`u_spreadStateTexture`),6),{program:r,pass1Program:v,buffer:a,vertShader:t,fragShader:n,pass1FragShader:_,texture:s,atlasTexture:m,charVectorsTexture:g,fboTexture:D,fbo:O,scatterAtlasTexture:k,scatterStateTexture:A,spreadStateTexture:j,p1ResLoc:y,p1CellsizeLoc:b,p1CircleNLoc:x,p1NumCharsLoc:S,p1ExponentLoc:C,p1CropOffsetLoc:w,p1CropScaleLoc:T,p1GridOffsetLoc:E,revealEffectFlagLoc:e.getUniformLocation(r,`u_revealEffectFlag`),mouseEffectFlagLoc:e.getUniformLocation(r,`u_mouseEffect`),clickEffectFlagLoc:e.getUniformLocation(r,`u_clickEffect`),shapeMatchingLoc:e.getUniformLocation(r,`u_shapeMatching`),revealProgressLoc:e.getUniformLocation(r,`u_revealProgress`),brightnessLoc:e.getUniformLocation(r,`u_brightness`),saturationLoc:e.getUniformLocation(r,`u_saturation`),bgOpacityLoc:e.getUniformLocation(r,`u_bgOpacity`),mouseBrightnessLoc:e.getUniformLocation(r,`u_mouseBrightness`),mousePositionsLoc:e.getUniformLocation(r,`u_mousePositions`),mouseLifeFracsLoc:e.getUniformLocation(r,`u_mouseLifeFracs`),mouseRadiusLoc:e.getUniformLocation(r,`u_mouseRadius`),ripplePositionsLoc:e.getUniformLocation(r,`u_ripplePositions`),rippleRadiiLoc:e.getUniformLocation(r,`u_rippleRadii`),rippleBrightnessesLoc:e.getUniformLocation(r,`u_rippleBrightnesses`),scatterEffectFlagLoc:e.getUniformLocation(r,`u_scatterEffect`),scatterNumCharsLoc:e.getUniformLocation(r,`u_scatterNumChars`),spreadEffectFlagLoc:e.getUniformLocation(r,`u_spreadEffect`),videoModeLoc:e.getUniformLocation(r,`u_videoMode`),resLoc:e.getUniformLocation(r,`u_resolution`),sizeLoc:e.getUniformLocation(r,`u_cellsize`),numLoc:e.getUniformLocation(r,`u_numChars`),gridSizeLoc:e.getUniformLocation(r,`u_gridSize`),cropOffsetLoc:e.getUniformLocation(r,`u_cropOffset`),cropScaleLoc:e.getUniformLocation(r,`u_cropScale`),gridOffsetLoc:e.getUniformLocation(r,`u_gridOffset`)}}function h({scatterEnabledRef:e,mouseRadiusRef:t,durationRef:n,scatterCharsRef:r}){let i=new Uint8Array,a=new Float32Array,o=new Float32Array,s=new Uint8Array,c=null,l=null,u=0,d=0,f=-1,p=()=>Math.floor(Math.random()*r.current.length),m=0,h=0,g=1,_=1,v=0,y=0,b=null;return{setup(e,t,n,r,f,p,x,S){m=t,h=n,g=r,_=f,v=p,y=x,b=S;let C=t*n;i=new Uint8Array(C),a=new Float32Array(C),o=new Float32Array(C),s=new Uint8Array(C),c=null,l=null,u=0,d=0,e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,S),e.texImage2D(e.TEXTURE_2D,0,e.R8UI,t,n,0,e.RED_INTEGER,e.UNSIGNED_BYTE,i)},handleMouseMove(t,n,r){e.current&&(l=c,c={x:t,y:n,t:r})},handleMouseLeave(){c=null,l=null,u=0,d=0},reset(e){i.fill(0),b&&m>0&&(e.activeTexture(e.TEXTURE5),e.bindTexture(e.TEXTURE_2D,b),e.texSubImage2D(e.TEXTURE_2D,0,0,0,m,h,e.RED_INTEGER,e.UNSIGNED_BYTE,i))},tick(r,x){if(!e.current||m===0||h===0)return;let S=performance.now(),C=f<0?0:Math.min(.1,(S-f)/1e3);f=S;let w=Math.min(x.width,x.height)*t.current,T=!1;if(c&&S-c.t<80){if(l){let e=(c.t-l.t)/1e3;if(e>0&&e<.2){let t=(c.x-l.x)/e,n=(c.y-l.y)/e;u=u*.7+t*.3,d=d*.7+n*.3}}else u=0,d=0;Math.hypot(u,d)>g*2&&(T=!0)}else u*=.6,d*=.6;if(s.fill(0),T&&c&&w>0){let e=c.x,t=c.y,n=Math.max(0,Math.floor((e-v-w)/g)),r=Math.min(m-1,Math.floor((e-v+w)/g)),l=Math.max(0,Math.floor((t-y-w)/_)),u=Math.min(h-1,Math.floor((t-y+w)/_));for(let c=l;c<=u;c++)for(let l=n;l<=r;l++){let n=v+(l+.5)*g,r=y+(c+.5)*_;if(Math.hypot(n-e,r-t)>w)continue;let u=c*m+l;s[u]=1,i[u]===0&&(i[u]=1+p(),o[u]=.5+Math.random()*2),a[u]=1}}let E=n.current;if(C>0)for(let e=0;e<h;e++)for(let t=0;t<m;t++){let n=e*m+t;if(i[n]===0||s[n])continue;let r=t>0?i[n-1]!==0:!1,c=t<m-1?i[n+1]!==0:!1,l=e>0?i[n-m]!==0:!1,u=e<h-1?i[n+m]!==0:!1,d=(!r||!c||!l||!u?5:1)*o[n]/E;a[n]-=d*C,a[n]<=0&&(i[n]=0)}r.activeTexture(r.TEXTURE5),r.bindTexture(r.TEXTURE_2D,b),r.texSubImage2D(r.TEXTURE_2D,0,0,0,m,h,r.RED_INTEGER,r.UNSIGNED_BYTE,i)}}}function g({brightenEnabledRef:e,trailLenRef:t,durationRef:n,trailDecayRef:r}){let i=[];return{handleMouseMove(n,r,a){e.current&&(i.push({x:n,y:r,t:a}),i.length>t.current&&i.shift())},tick(a,o,s){if(!e.current)return;let c=performance.now(),l=new Float32Array(t.current*2),u=new Float32Array(t.current);for(let e=0;e<i.length;e++){let t=c-i[e].t,a=Math.max(0,1-t/(n.current*1e3))**r.current;l[e*2]=i[e].x,l[e*2+1]=i[e].y,u[e]=a}a.uniform2fv(o,l),a.uniform1fv(s,u)}}}var _=10;function v({clickEnabledRef:e,clickSpeedRef:t,clickBrightnessRef:n,pixelScaleRef:r}){let i=[];return{handleClick(t,n){if(!e.current)return;let r=n.getBoundingClientRect(),a=(t.clientX-r.left)*(n.width/r.width),o=(t.clientY-r.top)*(n.height/r.height);i.push({x:a,y:o,t:performance.now()}),i.length>_&&i.shift()},tick(a,o,s,c,l){if(!e.current)return;let u=performance.now(),d=Math.hypot(o.width,o.height),f=t.current*r.current,p=new Float32Array(_*2),m=new Float32Array(_),h=new Float32Array(_);for(;i.length>0&&(u-i[0].t)*f>=d;)i.shift();for(let e=0;e<i.length;e++){let t=(u-i[e].t)*f,r=t/d,a=1+(n.current-1)*(1-r**2);p[e*2]=i[e].x,p[e*2+1]=i[e].y,m[e]=t,h[e]=a}a.uniform2fv(s,p),a.uniform1fv(c,m),a.uniform1fv(l,h)}}}function y({spreadEnabledRef:e,scatterCharsRef:t,spreadExpandDurationRef:n,spreadSpeedRef:r}){let i=new Uint8Array,a=new Uint8Array,o=0,s=0,c=1,l=1,u=0,d=0,f=null,p=-1,m=-1,h=()=>Math.floor(Math.random()*t.current.length),g=[[-1,0],[1,0],[0,-1],[0,1]];return{setup(e,t,n,r,h,g,_,v){o=t,s=n,c=r,l=h,u=g,d=_,f=v;let y=t*n;i=new Uint8Array(y),a=new Uint8Array(y),m=-1,p=-1,e.activeTexture(e.TEXTURE6),e.bindTexture(e.TEXTURE_2D,v),e.texImage2D(e.TEXTURE_2D,0,e.R8UI,t,n,0,e.RED_INTEGER,e.UNSIGNED_BYTE,i)},handleClick(t,r){if(!e.current||o===0)return;let f=r.getBoundingClientRect(),p=(t.clientX-f.left)*(r.width/f.width),g=(t.clientY-f.top)*(r.height/f.height),_=Math.floor((p-u)/c),v=Math.floor((g-d)/l);if(_<0||_>=o||v<0||v>=s)return;let y=v*o+_;i[y]=1+h(),a[y]=1,m=performance.now()+n.current*1e3},tick(t){if(!e.current||o===0||s===0)return;let n=performance.now(),c=p<0?0:Math.min(.1,(n-p)/1e3);p=n;let l=m>0&&n<m;if(!l&&m>0){for(let e=0;e<i.length;e++)a[e]===1&&(a[e]=2);m=-1}if(c>0)for(let e=0;e<s;e++)for(let t=0;t<o;t++){let n=e*o+t;if(a[n]!==0){if(l&&a[n]===1)for(let[n,l]of g){let u=e+n,d=t+l;if(u<0||u>=s||d<0||d>=o)continue;let f=u*o+d;a[f]===0&&Math.random()<r.current*c&&(i[f]=1+h(),a[f]=1)}else if(a[n]===2)for(let[l,u]of g){let d=e+l,f=t+u;if(d<0||d>=s||f<0||f>=o||i[d*o+f]===0){Math.random()<r.current*c&&(i[n]=0,a[n]=0);break}}}}t.activeTexture(t.TEXTURE6),t.bindTexture(t.TEXTURE_2D,f),t.texSubImage2D(t.TEXTURE_2D,0,0,0,o,s,t.RED_INTEGER,t.UNSIGNED_BYTE,i)}}}function b(e,t){let n=0,r=0,i=!1,a=null,o=()=>{let e=window.devicePixelRatio||1;t({width:Math.round(n*e),height:Math.round(r*e),cssWidth:n,cssHeight:r})},s=()=>{a?.();let e=window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),t=()=>{i||(o(),s())};e.addEventListener(`change`,t,{once:!0}),a=()=>e.removeEventListener(`change`,t)},c=new ResizeObserver(e=>{let i=e[0],a=i.contentBoxSize?.[0];n=a?a.inlineSize:i.contentRect.width,r=a?a.blockSize:i.contentRect.height;let s=i.devicePixelContentBoxSize?.[0];s?t({width:s.inlineSize,height:s.blockSize,cssWidth:n,cssHeight:r}):o()});try{c.observe(e,{box:`device-pixel-content-box`})}catch{c.observe(e),s()}return()=>{i=!0,c.disconnect(),a?.()}}function x({src:e,mediaType:r=`auto`,videoMode:o=!1,numColsRaw:l=250,brightnessRaw:u=1,saturationRaw:d=1,bgOpacityRaw:f=.3,revealEffect:p=!1,chars:_=a,mouseEffect:x=!0,clickEffect:S=!0,charMode:C=`shape`,className:w,cropFocus:T=`center`,maxDpr:E}){let D=(0,t.useRef)(null),O=(0,t.useRef)(null),k=(0,t.useRef)(null),A=(0,t.useRef)(null),j=(0,t.useRef)(null),ee=(0,t.useRef)(null),{numCols:M,brightness:N,saturation:P,bgOpacity:F,mouseEnabled:I,mouseStyle:L,brightenEnabled:R,scatterEnabled:z,scatterChars:B,trailLen:V,trailDecay:H,duration:U,mouseRadius:W,mouseBrightness:te,clickEnabled:ne,clickBrightness:G,clickSpeed:K,spreadEnabled:q,spreadExpandDuration:J,spreadSpeed:Y,revealEnabled:re,revealDuration:ie,revealEffectFlag:ae,maxDpr:X}=c(l,u,d,f,x,S,p,E),oe=s(e,r)===`image`,se=(0,t.useRef)(N),ce=(0,t.useRef)(P),le=(0,t.useRef)(F),ue=(0,t.useRef)(I),Z=(0,t.useRef)(L),de=(0,t.useRef)(R),fe=(0,t.useRef)(z),pe=(0,t.useRef)(te),me=(0,t.useRef)(W),he=(0,t.useRef)(V),ge=(0,t.useRef)(H),_e=(0,t.useRef)(U),Q=(0,t.useRef)(B),ve=(0,t.useRef)(ne),ye=(0,t.useRef)(G),be=(0,t.useRef)(K),xe=(0,t.useRef)(q),Se=(0,t.useRef)(J),Ce=(0,t.useRef)(Y),we=(0,t.useRef)(M),Te=(0,t.useRef)(o),Ee=(0,t.useRef)(T),De=(0,t.useRef)(0),Oe=(0,t.useRef)(0),ke=(0,t.useRef)(X),Ae=(0,t.useRef)(1),je=(0,t.useRef)(null),Me=(0,t.useRef)(null);(0,t.useEffect)(()=>{se.current=N,ce.current=P,le.current=F,ue.current=I,Z.current=L,de.current=R,fe.current=z,pe.current=te,me.current=W,he.current=V,ge.current=H,_e.current=U,Q.current!==B&&$.current?(Q.current=B,Pe.current?.()):Q.current=B,ve.current=ne,ye.current=G,be.current=K,xe.current=q,Se.current=J,Ce.current=Y,we.current=M,Te.current=o},[N,P,F,I,L,R,z,te,W,V,H,U,B,ne,G,K,q,J,Y,M,o]);let Ne=(0,t.useRef)(null),Pe=(0,t.useRef)(null),Fe=(0,t.useRef)(null),$=(0,t.useRef)(!1);(0,t.useEffect)(()=>{$.current&&Ne.current?.(M)},[M]),(0,t.useEffect)(()=>{Ee.current=T,$.current&&De.current>0&&Fe.current?.(De.current,Oe.current)},[T]),(0,t.useEffect)(()=>{ke.current=X,$.current&&je.current&&Me.current?.(je.current)},[X]),(0,t.useEffect)(()=>{$.current=!1;let t=[],n=0,r=0,a=1,o=1,s=0,c=0,l=0,u=0,d=D.current;if(!d)return;let f=oe?k.current:O.current;if(!f)return;let p=f instanceof HTMLVideoElement?f:null,x=f instanceof HTMLImageElement?f:null,S=()=>f instanceof HTMLVideoElement?{width:f.videoWidth,height:f.videoHeight}:{width:f.naturalWidth,height:f.naturalHeight},w=d.getContext(`webgl2`);if(!w)return;w.pixelStorei(w.UNPACK_ALIGNMENT,1);let T=m(w);if(!T)return;let{program:E,pass1Program:M}=T;j.current=T.atlasTexture,ee.current=T.scatterAtlasTexture,w.uniform1i(T.shapeMatchingLoc,+(C===`shape`)),w.uniform1i(T.revealEffectFlagLoc,ae),w.uniform1f(T.revealProgressLoc,0);let N=h({scatterEnabledRef:fe,mouseRadiusRef:me,durationRef:_e,scatterCharsRef:Q}),P=g({brightenEnabledRef:de,trailLenRef:he,durationRef:_e,trailDecayRef:ge}),F=v({clickEnabledRef:ve,clickSpeedRef:be,clickBrightnessRef:ye,pixelScaleRef:Ae}),I=y({spreadEnabledRef:xe,scatterCharsRef:Q,spreadExpandDurationRef:Se,spreadSpeedRef:Ce}),L,R=-1,z=-1,B=0,V=Array.isArray(e)?e:[e],H=V.length>1,U=document.createElement(`canvas`),W=U.getContext(`2d`),te=e=>{let f=l>0?l:d.width,p=u>0?u:d.height;a=Math.max(1,Math.floor(f/e));let m=a*2;if(W.font=`${m}px monospace`,o=Math.max(1,Math.round(m*a/W.measureText(`M`).width)),n=Math.ceil(f/a),r=Math.ceil(p/o),s=Math.floor((f-n*a)/2),c=Math.floor((p-r*o)/2),w.viewport(0,0,d.width,d.height),w.useProgram(E),w.uniform2f(T.resLoc,d.width,d.height),w.uniform2f(T.gridOffsetLoc,s,c),w.useProgram(M),w.uniform2f(T.p1ResLoc,d.width,d.height),w.uniform2f(T.p1GridOffsetLoc,s,c),w.useProgram(E),N.setup(w,n,r,a,o,s,c,T.scatterStateTexture),I.setup(w,n,r,a,o,s,c,T.spreadStateTexture),C===`shape`){t=i(_,a,o);let e=t.length,s=new Float32Array(e*8);for(let n=0;n<e;n++){let r=t[n].vector;s[n*4+0]=r[0],s[n*4+1]=r[1],s[n*4+2]=r[2],s[n*4+3]=r[3],s[e*4+n*4+0]=r[4],s[e*4+n*4+1]=r[5]}w.activeTexture(w.TEXTURE2),w.bindTexture(w.TEXTURE_2D,T.charVectorsTexture),w.texImage2D(w.TEXTURE_2D,0,w.RGBA32F,e,2,0,w.RGBA,w.FLOAT,s),w.activeTexture(w.TEXTURE3),w.bindTexture(w.TEXTURE_2D,T.fboTexture),w.texImage2D(w.TEXTURE_2D,0,w.R8UI,n,r,0,w.RED_INTEGER,w.UNSIGNED_BYTE,null),w.bindFramebuffer(w.FRAMEBUFFER,T.fbo),w.framebufferTexture2D(w.FRAMEBUFFER,w.COLOR_ATTACHMENT0,w.TEXTURE_2D,T.fboTexture,0),w.bindFramebuffer(w.FRAMEBUFFER,null);let c=Math.max(1,Math.round(a/5));w.useProgram(M),w.uniform2f(T.p1CellsizeLoc,a,o),w.uniform1i(T.p1CircleNLoc,c),w.uniform1i(T.p1NumCharsLoc,e),w.uniform1f(T.p1ExponentLoc,2),w.useProgram(E)}w.uniform2f(T.gridSizeLoc,n,r),U.width=_.length*a,U.height=o,W.font=`${o}px monospace`,W.fillStyle=`black`,W.fillRect(0,0,_.length*a,o),W.fillStyle=`white`,W.textBaseline=`top`;for(let e=0;e<_.length;e++)W.fillText(_[e],e*a,0);w.activeTexture(w.TEXTURE1),w.bindTexture(w.TEXTURE_2D,j.current),w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,U),w.uniform1f(T.numLoc,_.length),w.uniform2f(T.sizeLoc,a,o),ne()},ne=()=>{let e=Q.current;U.width=e.length*a,U.height=o,W.fillStyle=`black`,W.fillRect(0,0,U.width,o),W.fillStyle=`white`,W.textBaseline=`top`,W.font=`${o}px monospace`;for(let t=0;t<e.length;t++)W.fillText(e[t],t*a,0);w.activeTexture(w.TEXTURE4),w.bindTexture(w.TEXTURE_2D,ee.current),w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,U),w.uniform1f(T.scatterNumCharsLoc,e.length),N.reset(w)};Ne.current=te,Pe.current=ne;let G=(e,t)=>{l=Math.round(e),u=Math.round(t),De.current=l,Oe.current=u,d.width=l,d.height=u,te(we.current);let n=S(),r=n.width/n.height,i=d.width/d.height,a=1,o=1,s=0,c=0;if(i>r)o=r/i,c=(1-o)/2;else{a=i/r;let e=Ee.current,t=e===`left`?.25:e===`right`?.75:.5;s=Math.max(0,Math.min(1-a,t-a/2))}w.uniform2f(T.cropOffsetLoc,s,c),w.uniform2f(T.cropScaleLoc,a,o),w.useProgram(M),w.uniform2f(T.p1CropOffsetLoc,s,c),w.uniform2f(T.p1CropScaleLoc,a,o),w.useProgram(E)};Fe.current=G;let K=e=>{je.current=e;let t=Math.min(1,ke.current/(window.devicePixelRatio||1)),n=Math.max(1,Math.round(e.width*t)),r=Math.max(1,Math.round(e.height*t));Ae.current=e.cssWidth>0?n/e.cssWidth:1,G(n,r)};Me.current=K;let q=e=>{if(!ue.current)return;let t=d.getBoundingClientRect(),n=(e.clientX-t.left)*(d.width/t.width),r=(e.clientY-t.top)*(d.height/t.height),i=performance.now();P.handleMouseMove(n,r,i),N.handleMouseMove(n,r,i)};d.addEventListener(`mousemove`,q);let J=()=>N.handleMouseLeave();d.addEventListener(`mouseleave`,J);let Y=e=>{F.handleClick(e,d),I.handleClick(e,d)};d.addEventListener(`click`,Y);let X=()=>{if(w.uniform1i(T.videoModeLoc,+!!Te.current),w.uniform1f(T.brightnessLoc,se.current),w.uniform1f(T.saturationLoc,ce.current),w.uniform1f(T.bgOpacityLoc,le.current),w.uniform1i(T.mouseEffectFlagLoc,+!!de.current),w.uniform1i(T.scatterEffectFlagLoc,+!!fe.current),w.uniform1i(T.clickEffectFlagLoc,+!!ve.current),w.uniform1i(T.spreadEffectFlagLoc,+!!xe.current),w.uniform1f(T.mouseBrightnessLoc,pe.current),w.uniform1f(T.mouseRadiusLoc,Math.min(d.width,d.height)*me.current),re){let e=z<0?0:Math.min(1,(performance.now()-z)/(ie*1e3));w.uniform1f(T.revealProgressLoc,e)}$.current&&p&&p.currentTime!=R&&p.readyState>=2&&(w.activeTexture(w.TEXTURE0),w.bindTexture(w.TEXTURE_2D,T.texture),w.texSubImage2D(w.TEXTURE_2D,0,0,0,w.RGBA,w.UNSIGNED_BYTE,p),R=p.currentTime),P.tick(w,T.mousePositionsLoc,T.mouseLifeFracsLoc),N.tick(w,d),F.tick(w,d,T.ripplePositionsLoc,T.rippleRadiiLoc,T.rippleBrightnessesLoc),I.tick(w),C===`shape`&&(w.bindFramebuffer(w.FRAMEBUFFER,T.fbo),w.viewport(0,0,n,r),w.useProgram(M),w.drawArrays(w.TRIANGLES,0,6),w.bindFramebuffer(w.FRAMEBUFFER,null),w.viewport(0,0,d.width,d.height),w.useProgram(E)),w.drawArrays(w.TRIANGLES,0,6),L=requestAnimationFrame(X)},Z=()=>{let e=A.current,t=je.current;if(t&&t.width>0&&t.height>0)K(t);else{let t=window.devicePixelRatio||1,n=S(),r=e.clientWidth||n.width,i=e.clientHeight||n.height;K({width:Math.round(r*t),height:Math.round(i*t),cssWidth:r,cssHeight:i})}w.activeTexture(w.TEXTURE0),w.bindTexture(w.TEXTURE_2D,T.texture),w.texImage2D(w.TEXTURE_2D,0,w.RGBA,w.RGBA,w.UNSIGNED_BYTE,f),p?.play(),z=performance.now(),$.current=!0,L=requestAnimationFrame(X)},Ie=()=>{p&&(B=(B+1)%V.length,p.src=V[B],p.load(),p.addEventListener(`canplay`,()=>p.play(),{once:!0}))},Le=A.current?b(A.current,e=>{je.current=e,$.current&&e.width>0&&e.height>0&&K(e)}):()=>{};return p?(p.addEventListener(`loadeddata`,Z,{once:!0}),H&&p.addEventListener(`ended`,Ie),p.readyState>=2&&p.currentSrc.endsWith(V[0])?Z():p.currentSrc.endsWith(V[0])||p.load()):x&&(x.complete&&x.naturalWidth>0?Z():x.addEventListener(`load`,Z,{once:!0})),()=>{Le(),Ne.current=null,Pe.current=null,Fe.current=null,Me.current=null,$.current=!1,cancelAnimationFrame(L),p?(p.removeEventListener(`loadeddata`,Z),H&&p.removeEventListener(`ended`,Ie)):x?.removeEventListener(`load`,Z),d.removeEventListener(`mousemove`,q),d.removeEventListener(`mouseleave`,J),d.removeEventListener(`click`,Y),w.deleteTexture(T.texture),w.deleteTexture(T.charVectorsTexture),w.deleteFramebuffer(T.fbo),w.deleteTexture(T.fboTexture),w.deleteBuffer(T.buffer),w.deleteShader(T.vertShader),w.deleteShader(T.fragShader),w.deleteShader(T.pass1FragShader),w.deleteProgram(E),w.deleteProgram(M),w.deleteTexture(j.current),w.deleteTexture(ee.current),w.deleteTexture(T.scatterStateTexture),w.deleteTexture(T.spreadStateTexture)}},[e,C,_,ae,ie,re,oe]);let Ie=Array.isArray(e)?e[0]:e;return(0,n.jsxs)(`div`,{ref:A,className:w,style:{height:`100%`,width:`100%`},children:[oe?(0,n.jsx)(`img`,{ref:k,src:Ie,alt:``,style:{display:`none`}}):(0,n.jsx)(`video`,{ref:O,muted:!0,playsInline:!0,autoPlay:!0,loop:!Array.isArray(e)||e.length===1,style:{display:`none`},children:(0,n.jsx)(`source`,{src:Ie,type:`video/mp4`})}),(0,n.jsx)(`canvas`,{ref:D,style:{width:`100%`,height:`100%`,display:`block`}})]})}e.VideoAscii=x});
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "react-video-ascii",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "type": "module",
5
- "description": "React component that renders videos as ASCII animations using WebGL2.",
5
+ "description": "React component that renders videos and images as ASCII animations using WebGL2.",
6
6
  "author": "Lucas Jin",
7
7
  "repository": {
8
8
  "type": "git",