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 +9 -3
- package/dist/components/VideoAscii.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/ascii-props.d.ts +6 -1
- package/dist/lib/click-effect.d.ts +4 -1
- package/dist/lib/create-gl-resources.d.ts +2 -0
- package/dist/lib/device-pixel-size.d.ts +7 -0
- package/dist/lib/scatter-effect.d.ts +1 -1
- package/dist/lib/spread-effect.d.ts +1 -1
- package/dist/react-video-ascii.js +295 -218
- package/dist/react-video-ascii.umd.cjs +16 -11
- package/package.json +2 -2
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
|
-
| `
|
|
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;
|
|
@@ -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
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
102
|
-
let t =
|
|
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 =
|
|
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.
|
|
125
|
-
let
|
|
126
|
-
e.uniform1i(
|
|
127
|
-
let
|
|
128
|
-
e.activeTexture(e.TEXTURE1), e.bindTexture(e.TEXTURE_2D,
|
|
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 _ =
|
|
139
|
+
let _ = u(e, e.FRAGMENT_SHADER, m);
|
|
134
140
|
if (!_) return null;
|
|
135
|
-
let v =
|
|
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,
|
|
140
|
-
let
|
|
141
|
-
e.activeTexture(e.TEXTURE4), e.bindTexture(e.TEXTURE_2D,
|
|
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
|
-
|
|
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:
|
|
159
|
+
atlasTexture: l,
|
|
154
160
|
charVectorsTexture: g,
|
|
155
|
-
fboTexture:
|
|
156
|
-
fbo:
|
|
157
|
-
scatterAtlasTexture:
|
|
158
|
-
scatterStateTexture:
|
|
159
|
-
spreadStateTexture:
|
|
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
|
|
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
|
|
202
|
-
i = new Uint8Array(
|
|
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),
|
|
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,
|
|
225
|
+
tick(r, x) {
|
|
218
226
|
if (!e.current || m === 0 || h === 0) return;
|
|
219
|
-
let
|
|
220
|
-
f =
|
|
221
|
-
let
|
|
222
|
-
if (c &&
|
|
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 && (
|
|
238
|
+
Math.hypot(u, d) > g * 2 && (T = !0);
|
|
231
239
|
} else u *= .6, d *= .6;
|
|
232
|
-
if (s.fill(0),
|
|
233
|
-
let e = c.x, t = c.y, n = Math.max(0, Math.floor((e -
|
|
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) >
|
|
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
|
|
242
|
-
if (
|
|
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] /
|
|
246
|
-
a[n] -= d *
|
|
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,
|
|
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
|
|
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
|
|
278
|
-
function
|
|
279
|
-
let
|
|
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
|
|
284
|
-
|
|
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
|
-
}),
|
|
296
|
+
}), i.length > v && i.shift();
|
|
289
297
|
},
|
|
290
|
-
tick(
|
|
298
|
+
tick(a, o, s, c, l) {
|
|
291
299
|
if (!e.current) return;
|
|
292
|
-
let
|
|
293
|
-
for (;
|
|
294
|
-
for (let e = 0; e <
|
|
295
|
-
let
|
|
296
|
-
|
|
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
|
-
|
|
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
|
|
305
|
-
let i = new Uint8Array(), a = new Uint8Array(), o = 0, s = 0, c = 1, l = 1, u =
|
|
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,
|
|
313
|
-
o = t, s = n, c = r, l =
|
|
314
|
-
let
|
|
315
|
-
i = new Uint8Array(
|
|
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
|
|
320
|
-
if (
|
|
321
|
-
let
|
|
322
|
-
i[
|
|
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 =
|
|
327
|
-
|
|
328
|
-
let l =
|
|
329
|
-
if (!l &&
|
|
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
|
-
|
|
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
|
|
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 +
|
|
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
|
|
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,
|
|
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
|
|
358
|
-
let
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
382
|
-
|
|
425
|
+
X,
|
|
426
|
+
N,
|
|
427
|
+
u
|
|
383
428
|
]);
|
|
384
|
-
let
|
|
385
|
-
|
|
386
|
-
$.current &&
|
|
387
|
-
}, [
|
|
388
|
-
|
|
389
|
-
}, [
|
|
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 =
|
|
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
|
-
|
|
398
|
-
let f = p(d);
|
|
440
|
+
let f = se ? j.current : A.current;
|
|
399
441
|
if (!f) return;
|
|
400
|
-
let
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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
|
-
}),
|
|
408
|
-
brightenEnabledRef:
|
|
409
|
-
trailLenRef:
|
|
410
|
-
durationRef:
|
|
411
|
-
trailDecayRef:
|
|
412
|
-
}),
|
|
413
|
-
clickEnabledRef:
|
|
414
|
-
clickSpeedRef:
|
|
415
|
-
clickBrightnessRef:
|
|
416
|
-
|
|
417
|
-
|
|
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:
|
|
420
|
-
spreadSpeedRef:
|
|
421
|
-
}),
|
|
422
|
-
let
|
|
423
|
-
r = Math.max(1, Math.floor(
|
|
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 (
|
|
426
|
-
e = a(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
437
|
-
for (let e = 0; e <
|
|
438
|
-
|
|
439
|
-
},
|
|
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
|
-
|
|
442
|
-
for (let t = 0; t < e.length; t++)
|
|
443
|
-
|
|
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
|
-
|
|
446
|
-
let
|
|
447
|
-
|
|
448
|
-
let n =
|
|
449
|
-
if (
|
|
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
|
-
|
|
452
|
-
let e =
|
|
453
|
-
|
|
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
|
-
|
|
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
|
-
|
|
458
|
-
let
|
|
459
|
-
if (!
|
|
460
|
-
let t =
|
|
461
|
-
|
|
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
|
-
|
|
464
|
-
let
|
|
465
|
-
|
|
466
|
-
let
|
|
467
|
-
|
|
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
|
-
|
|
470
|
-
let
|
|
471
|
-
if (
|
|
472
|
-
let e =
|
|
473
|
-
|
|
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 &&
|
|
476
|
-
},
|
|
477
|
-
let e =
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
])
|
|
496
|
-
|
|
497
|
-
|
|
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("
|
|
503
|
-
ref:
|
|
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:
|
|
587
|
+
src: Re,
|
|
511
588
|
type: "video/mp4"
|
|
512
589
|
})
|
|
513
590
|
}), /* @__PURE__ */ n("canvas", {
|
|
514
|
-
ref:
|
|
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 {
|
|
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
|
|
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
|
-
}`,
|
|
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
|
|
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(
|
|
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
|
-
}`,
|
|
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.
|
|
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",
|