@toriistudio/shader-ui 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +553 -36
- package/dist/index.mjs +557 -36
- package/package.json +4 -1
package/dist/index.mjs
CHANGED
|
@@ -20,6 +20,7 @@ function useScene({
|
|
|
20
20
|
const onCreateRef = useRef(onCreate);
|
|
21
21
|
const onRenderRef = useRef(onRender);
|
|
22
22
|
const onResizeRef = useRef(onResize);
|
|
23
|
+
const sizeRef = useRef({ width: 0, height: 0 });
|
|
23
24
|
useEffect(() => {
|
|
24
25
|
onCreateRef.current = onCreate;
|
|
25
26
|
}, [onCreate]);
|
|
@@ -34,43 +35,83 @@ function useScene({
|
|
|
34
35
|
const container = containerRef.current;
|
|
35
36
|
if (!container) return;
|
|
36
37
|
const resolvedPixelRatio = pixelRatio ?? (typeof window !== "undefined" ? Math.min(window.devicePixelRatio, 2) : 1);
|
|
38
|
+
const initialWidth = container.clientWidth || 1;
|
|
39
|
+
const initialHeight = container.clientHeight || 1;
|
|
40
|
+
sizeRef.current = { width: initialWidth, height: initialHeight };
|
|
37
41
|
const renderer = new THREE.WebGLRenderer({
|
|
38
42
|
alpha: true,
|
|
39
43
|
antialias: true,
|
|
40
44
|
...rendererOptions
|
|
41
45
|
});
|
|
42
46
|
renderer.setPixelRatio(resolvedPixelRatio);
|
|
43
|
-
renderer.setSize(
|
|
47
|
+
renderer.setSize(initialWidth, initialHeight, false);
|
|
44
48
|
renderer.setClearColor(0, 0);
|
|
45
49
|
renderer.domElement.style.width = "100%";
|
|
46
50
|
renderer.domElement.style.height = "100%";
|
|
47
51
|
container.appendChild(renderer.domElement);
|
|
48
52
|
const scene = new THREE.Scene();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
let camera;
|
|
54
|
+
if (cameraOptions?.type === "orthographic") {
|
|
55
|
+
const halfWidth = initialWidth / 2;
|
|
56
|
+
const halfHeight = initialHeight / 2;
|
|
57
|
+
const orthoCamera = new THREE.OrthographicCamera(
|
|
58
|
+
-halfWidth,
|
|
59
|
+
halfWidth,
|
|
60
|
+
halfHeight,
|
|
61
|
+
-halfHeight,
|
|
62
|
+
cameraOptions?.near ?? 0.1,
|
|
63
|
+
cameraOptions?.far ?? 1e3
|
|
64
|
+
);
|
|
65
|
+
const [, , z = 10] = cameraOptions?.position ?? [];
|
|
66
|
+
orthoCamera.position.set(0, 0, z);
|
|
67
|
+
camera = orthoCamera;
|
|
68
|
+
} else {
|
|
69
|
+
const perspectiveCamera = new THREE.PerspectiveCamera(
|
|
70
|
+
cameraOptions?.fov ?? 55,
|
|
71
|
+
initialWidth / Math.max(1, initialHeight),
|
|
72
|
+
cameraOptions?.near ?? 0.1,
|
|
73
|
+
cameraOptions?.far ?? 500
|
|
74
|
+
);
|
|
75
|
+
const [x = 0, y = 0, z = 15] = cameraOptions?.position ?? [];
|
|
76
|
+
perspectiveCamera.position.set(x, y, z);
|
|
77
|
+
camera = perspectiveCamera;
|
|
78
|
+
}
|
|
57
79
|
const clock = new THREE.Clock();
|
|
58
|
-
const context = {
|
|
80
|
+
const context = {
|
|
81
|
+
renderer,
|
|
82
|
+
scene,
|
|
83
|
+
camera,
|
|
84
|
+
clock,
|
|
85
|
+
size: { ...sizeRef.current }
|
|
86
|
+
};
|
|
59
87
|
contextRef.current = context;
|
|
60
88
|
const teardownCreate = onCreateRef.current?.(context);
|
|
89
|
+
let elapsedTime = 0;
|
|
61
90
|
let animationFrameId = 0;
|
|
62
91
|
const renderLoop = () => {
|
|
63
|
-
|
|
92
|
+
const delta = clock.getDelta();
|
|
93
|
+
elapsedTime += delta;
|
|
94
|
+
context.size = { ...sizeRef.current };
|
|
95
|
+
onRenderRef.current?.(context, delta, elapsedTime);
|
|
64
96
|
renderer.render(scene, camera);
|
|
65
97
|
animationFrameId = requestAnimationFrame(renderLoop);
|
|
66
98
|
};
|
|
67
99
|
animationFrameId = requestAnimationFrame(renderLoop);
|
|
68
100
|
const resizeObserver = new ResizeObserver(() => {
|
|
69
|
-
const width = container.clientWidth;
|
|
70
|
-
const height = container.clientHeight;
|
|
101
|
+
const width = container.clientWidth || 1;
|
|
102
|
+
const height = container.clientHeight || 1;
|
|
71
103
|
renderer.setSize(width, height, false);
|
|
72
|
-
|
|
104
|
+
sizeRef.current = { width, height };
|
|
105
|
+
if (camera instanceof THREE.PerspectiveCamera) {
|
|
106
|
+
camera.aspect = width / Math.max(1, height);
|
|
107
|
+
} else if (camera instanceof THREE.OrthographicCamera) {
|
|
108
|
+
camera.left = -width / 2;
|
|
109
|
+
camera.right = width / 2;
|
|
110
|
+
camera.top = height / 2;
|
|
111
|
+
camera.bottom = -height / 2;
|
|
112
|
+
}
|
|
73
113
|
camera.updateProjectionMatrix();
|
|
114
|
+
context.size = { ...sizeRef.current };
|
|
74
115
|
onResizeRef.current?.(context, { width, height });
|
|
75
116
|
});
|
|
76
117
|
resizeObserver.observe(container);
|
|
@@ -130,15 +171,14 @@ function ShaderArt({
|
|
|
130
171
|
assetsRef.current = null;
|
|
131
172
|
};
|
|
132
173
|
}, []);
|
|
133
|
-
const handleRender = useCallback(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}, []);
|
|
174
|
+
const handleRender = useCallback(
|
|
175
|
+
(context, _delta, elapsedTime) => {
|
|
176
|
+
shaderUniformsRef.current.iTime.value = elapsedTime;
|
|
177
|
+
const { width: width2, height: height2 } = context.size;
|
|
178
|
+
shaderUniformsRef.current.iResolution.value.set(width2, height2, 1);
|
|
179
|
+
},
|
|
180
|
+
[]
|
|
181
|
+
);
|
|
142
182
|
const { containerRef } = useScene({
|
|
143
183
|
onCreate: handleCreate,
|
|
144
184
|
onRender: handleRender
|
|
@@ -285,7 +325,12 @@ function FractalFlower({
|
|
|
285
325
|
const points = new THREE3.Points(geometry, material);
|
|
286
326
|
points.frustumCulled = false;
|
|
287
327
|
scene.add(points);
|
|
288
|
-
assetsRef.current = {
|
|
328
|
+
assetsRef.current = {
|
|
329
|
+
points,
|
|
330
|
+
geometry,
|
|
331
|
+
material,
|
|
332
|
+
uniforms: uniformValues
|
|
333
|
+
};
|
|
289
334
|
return () => {
|
|
290
335
|
scene.remove(points);
|
|
291
336
|
geometry.dispose();
|
|
@@ -293,25 +338,29 @@ function FractalFlower({
|
|
|
293
338
|
assetsRef.current = null;
|
|
294
339
|
};
|
|
295
340
|
},
|
|
296
|
-
[
|
|
341
|
+
[
|
|
342
|
+
attributes.eValues,
|
|
343
|
+
attributes.kValues,
|
|
344
|
+
attributes.positions,
|
|
345
|
+
attributes.rotations
|
|
346
|
+
]
|
|
297
347
|
);
|
|
298
348
|
const handleRender = useCallback2(
|
|
299
|
-
(context) => {
|
|
349
|
+
(context, delta, elapsedTime) => {
|
|
300
350
|
const assets = assetsRef.current;
|
|
301
351
|
if (!assets) return;
|
|
302
352
|
const uniforms = assets.uniforms;
|
|
303
|
-
uniforms.uTime.value =
|
|
304
|
-
const
|
|
305
|
-
uniforms.uResolution.value.set(
|
|
353
|
+
uniforms.uTime.value = elapsedTime;
|
|
354
|
+
const { width: width2, height: height2 } = context.size;
|
|
355
|
+
uniforms.uResolution.value.set(width2, height2);
|
|
306
356
|
const basePointSize = Math.max(
|
|
307
357
|
2,
|
|
308
|
-
|
|
358
|
+
height2 / 400 * (uniforms.uPetalRadius.value * 32)
|
|
309
359
|
);
|
|
310
360
|
const pointSize = Math.min(basePointSize, 6);
|
|
311
361
|
uniforms.uPointSize.value = pointSize;
|
|
312
362
|
const morph = morphRef.current;
|
|
313
363
|
if (Math.abs(morph.target - morph.progress) > 1e-3) {
|
|
314
|
-
const delta = context.clock.getDelta();
|
|
315
364
|
const direction = Math.sign(morph.target - morph.progress);
|
|
316
365
|
morph.progress = clamp(
|
|
317
366
|
morph.progress + direction * delta * MORPH_SPEED,
|
|
@@ -462,11 +511,14 @@ function OranoParticles({
|
|
|
462
511
|
particlesRef.current = null;
|
|
463
512
|
};
|
|
464
513
|
}, []);
|
|
465
|
-
const handleRender = useCallback3(
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
514
|
+
const handleRender = useCallback3(
|
|
515
|
+
(_context, _delta, elapsedTime) => {
|
|
516
|
+
const assets = particlesRef.current;
|
|
517
|
+
if (!assets) return;
|
|
518
|
+
assets.uniforms.uTime.value = elapsedTime;
|
|
519
|
+
},
|
|
520
|
+
[]
|
|
521
|
+
);
|
|
470
522
|
const { containerRef } = useScene({
|
|
471
523
|
onCreate: handleCreate,
|
|
472
524
|
onRender: handleRender
|
|
@@ -525,8 +577,477 @@ function OranoParticles({
|
|
|
525
577
|
}
|
|
526
578
|
);
|
|
527
579
|
}
|
|
580
|
+
|
|
581
|
+
// src/components/MenuGlitch.tsx
|
|
582
|
+
import { gsap } from "gsap";
|
|
583
|
+
import {
|
|
584
|
+
useCallback as useCallback4,
|
|
585
|
+
useEffect as useEffect5,
|
|
586
|
+
useMemo as useMemo2,
|
|
587
|
+
useRef as useRef5
|
|
588
|
+
} from "react";
|
|
589
|
+
import * as THREE5 from "three";
|
|
590
|
+
|
|
591
|
+
// src/shaders/menu-glitch/fragment.glsl
|
|
592
|
+
var fragment_default4 = "#define M_PI 3.1415926535897932384626433832795\n\nuniform sampler2D tDiffuse;\nuniform sampler2D tGradient;\n\nuniform float uTime;\n\nuniform float uTileProgressVertical;\nuniform float uTileProgressHorizontal;\nuniform float uTileAmplitude;\nuniform vec2 uTileFrequency;\nuniform vec2 uTileOffset;\n\nuniform float uWaveProgress;\nuniform float uWaveAmplitude;\nuniform vec2 uWaveStrength;\n\nuniform float uGradientProgress;\nuniform float uGradientOffset;\nuniform float uGradientAmplitude;\n\nuniform float uBlueProgress;\nuniform float uBlueAmplitude;\n\nuniform float uWhiteTileChances;\nuniform float uWhiteTileFrequency;\nuniform float uWhiteTileStrength;\n\nuniform float uSaturation;\n\nvarying vec2 vUv;\n\n\n// --------------------------------------------------\n// Utilities\n// --------------------------------------------------\n\nfloat random(in vec2 st) {\n return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);\n}\n\nvec2 getTileCoord(vec2 pos, vec2 frequency) {\n vec2 coord = vec2(\n floor(pos.x * frequency.x),\n floor(pos.y * frequency.y)\n );\n\n coord /= frequency;\n return coord;\n}\n\nfloat toSin(float value) {\n return (sin((value - 0.5) * M_PI) + 1.0) * 0.5;\n}\n\n\n// --------------------------------------------------\n// Main\n// --------------------------------------------------\n\nvoid main() {\n\n // ------------------------\n // Tiles\n // ------------------------\n vec2 tileCoord1 = getTileCoord(vUv, uTileFrequency * 1.8942);\n vec2 tileCoord2 = getTileCoord(vUv, uTileFrequency * 1.0);\n vec2 tileCoord3 = getTileCoord(vUv, uTileFrequency * 2.1245);\n\n vec2 tileCoord = tileCoord2 +\n step(random(tileCoord1), 0.5) * (tileCoord3 - tileCoord2);\n\n float tileRandom = random(tileCoord);\n float tileAngle = tileRandom * M_PI * 2.0;\n\n vec2 tileOffset = vec2(sin(tileAngle), cos(tileAngle)) * uTileOffset;\n\n float tileProgress = 1.0 -\n (distance(tileCoord.y, uTileProgressVertical) / (uTileAmplitude * 0.5));\n\n tileProgress = clamp(tileProgress, 0.0, 1.0);\n\n float tileProgressHorizontal = 1.0 -\n (distance(tileCoord.x, uTileProgressHorizontal) / (uTileAmplitude * 0.5));\n tileProgressHorizontal = clamp(tileProgressHorizontal, 0.0, 1.0);\n\n // ------------------------\n // Wave\n // ------------------------\n float waveProgress = 1.0 -\n (distance(vUv.x, uWaveProgress) / (uWaveAmplitude * 0.5));\n\n waveProgress = clamp(waveProgress, 0.0, 1.0);\n\n vec2 waveOffset = toSin(waveProgress) * uWaveStrength;\n\n\n // ------------------------\n // Gradient\n // ------------------------\n float gradientProgress = (tileCoord.x - uGradientProgress) / uGradientAmplitude;\n gradientProgress += (tileRandom - 0.5) * uGradientOffset;\n\n vec4 gradientColor = texture2D(\n tGradient,\n vec2(clamp(gradientProgress, 0.0, 1.0), 0.0)\n );\n\n\n // ------------------------\n // Blue tint\n // ------------------------\n float blueProgress = (tileCoord.x - uBlueProgress) / uBlueAmplitude;\n blueProgress += tileOffset.x;\n blueProgress = clamp(blueProgress, 0.0, 1.0);\n\n\n // ------------------------\n // White flickering tiles\n // ------------------------\n float whiteTileProgress =\n sin(uTime * uWhiteTileFrequency + tileRandom * M_PI * 2.0) * 0.5 + 0.5;\n\n whiteTileProgress =\n clamp(whiteTileProgress - (1.0 - uWhiteTileChances), 0.0, 1.0) *\n (1.0 / uWhiteTileChances) *\n uWhiteTileStrength;\n\n\n // ------------------------\n // Final color pipeline\n // ------------------------\n vec2 uv = vUv;\n\n // Apply tile offset\n uv += tileOffset * tileProgress;\n\n // Apply waves (optional)\n // uv += waveOffset;\n\n // Repeat UV\n uv = mod(uv, vec2(1.0));\n\n // Base color removed so overlay only contains glitch elements\n vec4 color = vec4(0.0);\n\n // Add gradient\n color.rgb += gradientColor.rgb * gradientColor.a * tileProgressHorizontal;\n\n // Add white flicker effect\n color.rgb += vec3(whiteTileProgress) * tileProgressHorizontal;\n\n // Blue tone shift\n vec3 blueColor = vec3((color.r + color.g + color.b) / 3.0) *\n vec3(0.3, 0.5, 1.0);\n\n color.rgb = mix(color.rgb, blueColor, vec3(blueProgress));\n\n // Saturation\n color.rgb *= uSaturation;\n\n float effectAlpha =\n clamp(tileProgressHorizontal * (tileProgress * 0.6 + whiteTileProgress + gradientColor.a), 0.0, 1.0);\n\n // Output\n gl_FragColor = vec4(color.rgb, effectAlpha);\n}\n";
|
|
593
|
+
|
|
594
|
+
// src/shaders/menu-glitch/vertex.glsl
|
|
595
|
+
var vertex_default4 = "varying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n";
|
|
596
|
+
|
|
597
|
+
// src/components/MenuGlitch.tsx
|
|
598
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
599
|
+
var GRADIENT_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTVBRkY1OTJDREMyMTFFODhGRjFFRjgxRjM2QjM2MDMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTVBRkY1OTNDREMyMTFFODhGRjFFRjgxRjM2QjM2MDMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFNUFGRjU5MENEQzIxMUU4OEZGMUVGODFGMzZCMzYwMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFNUFGRjU5MUNEQzIxMUU4OEZGMUVGODFGMzZCMzYwMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pksi3ywAAADMSURBVHjarFDLDoMwDDMtUDjtME3TtMcn7f9/hngBCoTSTjsMydixnVZqxTcAX51Quwsad1M80PonWvdCUA7+rrii82eEulcG+hoTdwsrQtRB0UZu3KxrN8OPqIBKgRHxI8qaUTD1RuY2p90V+hOjmWix2uSSeGLPKrDdKc5GHzqZLPWY7XEG+F1PLBktpiuzf8ilkMvqcZfLLqf1ltnu7rLh4G88ZPxh4uUOmjMYO3aPqz8Yve0tGiaDduNr/xn8cWbBY8HLzQd8BBgAgOx+ERYDbIEAAAAASUVORK5CYII=";
|
|
600
|
+
var BASE_TRANSITION_PROGRESS = 0.5;
|
|
601
|
+
var SHOW_BASE_DURATION = 2.72;
|
|
602
|
+
var HIDE_BASE_DURATION = 1.8;
|
|
603
|
+
var SHOW_PRIMARY_DURATION = 1.1;
|
|
604
|
+
var MIN_GLITCH_DURATION = 0.25;
|
|
605
|
+
function MenuGlitch({
|
|
606
|
+
settings,
|
|
607
|
+
onShowDone,
|
|
608
|
+
onHideDone,
|
|
609
|
+
className,
|
|
610
|
+
style,
|
|
611
|
+
width,
|
|
612
|
+
height,
|
|
613
|
+
...divProps
|
|
614
|
+
}) {
|
|
615
|
+
const diffuseTexture = useMemo2(() => createDiffuseTexture(), []);
|
|
616
|
+
const gradientTextureRef = useRef5(new THREE5.Texture());
|
|
617
|
+
const sanitizedValues = useMemo2(() => {
|
|
618
|
+
const clamp2 = THREE5.MathUtils.clamp;
|
|
619
|
+
return {
|
|
620
|
+
tileAmplitude: Math.max(0.1, settings.tileAmplitude),
|
|
621
|
+
planeScale: Math.max(0.1, settings.planeScale ?? 1),
|
|
622
|
+
tileOffsetX: settings.tileOffset.x,
|
|
623
|
+
tileOffsetY: settings.tileOffset.y,
|
|
624
|
+
tileFrequencyX: Math.max(0.1, settings.tileFrequency.x),
|
|
625
|
+
tileFrequencyY: Math.max(0.1, settings.tileFrequency.y),
|
|
626
|
+
gradientAmplitude: Math.max(0.05, settings.gradientAmplitude),
|
|
627
|
+
gradientOffset: settings.gradientOffset,
|
|
628
|
+
gradientProgress: settings.gradientProgress ?? 1,
|
|
629
|
+
blueAmplitude: Math.max(0.05, settings.blueAmplitude),
|
|
630
|
+
blueProgress: settings.blueProgress ?? 1,
|
|
631
|
+
waveAmplitude: Math.max(0.05, settings.waveAmplitude),
|
|
632
|
+
waveProgress: settings.waveProgress ?? 0.5,
|
|
633
|
+
waveStrengthX: settings.waveStrength.x,
|
|
634
|
+
waveStrengthY: settings.waveStrength.y,
|
|
635
|
+
whiteTileChances: clamp2(settings.whiteTileChances, 0.05, 1),
|
|
636
|
+
whiteTileFrequency: Math.max(0.01, settings.whiteTileFrequency),
|
|
637
|
+
whiteTileStrength: Math.max(0, settings.whiteTileStrength),
|
|
638
|
+
saturation: Math.max(0, settings.saturation),
|
|
639
|
+
duration: Math.max(
|
|
640
|
+
MIN_GLITCH_DURATION,
|
|
641
|
+
settings.duration ?? SHOW_PRIMARY_DURATION
|
|
642
|
+
),
|
|
643
|
+
debug: settings.debug
|
|
644
|
+
};
|
|
645
|
+
}, [settings]);
|
|
646
|
+
const sanitizedRef = useRef5(sanitizedValues);
|
|
647
|
+
sanitizedRef.current = sanitizedValues;
|
|
648
|
+
const sizeRef = useRef5({ width: 0, height: 0 });
|
|
649
|
+
const assetsRef = useRef5(null);
|
|
650
|
+
const animationVisibleRef = useRef5(false);
|
|
651
|
+
const shaderUniforms = useRef5({
|
|
652
|
+
tDiffuse: { value: diffuseTexture },
|
|
653
|
+
tGradient: { value: gradientTextureRef.current },
|
|
654
|
+
uTime: { value: 0 },
|
|
655
|
+
uTileProgressVertical: { value: -0.5 },
|
|
656
|
+
uTileProgressHorizontal: { value: -0.5 },
|
|
657
|
+
uTileAmplitude: { value: settings.tileAmplitude },
|
|
658
|
+
uTileOffset: {
|
|
659
|
+
value: new THREE5.Vector2(settings.tileOffset.x, settings.tileOffset.y)
|
|
660
|
+
},
|
|
661
|
+
uTileFrequency: {
|
|
662
|
+
value: new THREE5.Vector2(
|
|
663
|
+
settings.tileFrequency.x,
|
|
664
|
+
settings.tileFrequency.y
|
|
665
|
+
)
|
|
666
|
+
},
|
|
667
|
+
uWaveProgress: { value: settings.waveProgress },
|
|
668
|
+
uWaveAmplitude: { value: settings.waveAmplitude },
|
|
669
|
+
uWaveStrength: {
|
|
670
|
+
value: new THREE5.Vector2(
|
|
671
|
+
settings.waveStrength.x,
|
|
672
|
+
settings.waveStrength.y
|
|
673
|
+
)
|
|
674
|
+
},
|
|
675
|
+
uGradientProgress: { value: settings.gradientProgress },
|
|
676
|
+
uGradientOffset: { value: settings.gradientOffset },
|
|
677
|
+
uGradientAmplitude: { value: settings.gradientAmplitude },
|
|
678
|
+
uBlueProgress: { value: settings.blueProgress },
|
|
679
|
+
uBlueAmplitude: { value: settings.blueAmplitude },
|
|
680
|
+
uWhiteTileChances: { value: settings.whiteTileChances },
|
|
681
|
+
uWhiteTileFrequency: { value: settings.whiteTileFrequency },
|
|
682
|
+
uWhiteTileStrength: { value: settings.whiteTileStrength },
|
|
683
|
+
uSaturation: { value: settings.saturation }
|
|
684
|
+
});
|
|
685
|
+
useEffect5(() => {
|
|
686
|
+
let disposed = false;
|
|
687
|
+
const loader = new THREE5.TextureLoader();
|
|
688
|
+
loader.load(
|
|
689
|
+
GRADIENT_DATA_URL,
|
|
690
|
+
(texture) => {
|
|
691
|
+
if (disposed) return;
|
|
692
|
+
texture.wrapS = THREE5.ClampToEdgeWrapping;
|
|
693
|
+
texture.wrapT = THREE5.ClampToEdgeWrapping;
|
|
694
|
+
texture.magFilter = THREE5.LinearFilter;
|
|
695
|
+
texture.minFilter = THREE5.LinearFilter;
|
|
696
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
697
|
+
gradientTextureRef.current = texture;
|
|
698
|
+
shaderUniforms.current.tGradient.value = texture;
|
|
699
|
+
},
|
|
700
|
+
void 0,
|
|
701
|
+
() => {
|
|
702
|
+
if (disposed) return;
|
|
703
|
+
gradientTextureRef.current = new THREE5.Texture();
|
|
704
|
+
shaderUniforms.current.tGradient.value = gradientTextureRef.current;
|
|
705
|
+
}
|
|
706
|
+
);
|
|
707
|
+
return () => {
|
|
708
|
+
disposed = true;
|
|
709
|
+
};
|
|
710
|
+
}, []);
|
|
711
|
+
const updateMeshScale = useCallback4(() => {
|
|
712
|
+
const assets = assetsRef.current;
|
|
713
|
+
if (!assets) return;
|
|
714
|
+
const base = Math.max(
|
|
715
|
+
sizeRef.current.width || 1,
|
|
716
|
+
sizeRef.current.height || 1
|
|
717
|
+
);
|
|
718
|
+
const scale = base * sanitizedRef.current.planeScale;
|
|
719
|
+
assets.mesh.scale.set(scale, scale, 1);
|
|
720
|
+
}, []);
|
|
721
|
+
const updateVisibility = useCallback4(() => {
|
|
722
|
+
const mesh = assetsRef.current?.mesh;
|
|
723
|
+
if (!mesh) return;
|
|
724
|
+
mesh.visible = sanitizedRef.current.debug || animationVisibleRef.current;
|
|
725
|
+
}, []);
|
|
726
|
+
const handleCreate = useCallback4(
|
|
727
|
+
({ scene, size }) => {
|
|
728
|
+
const geometry = new THREE5.PlaneGeometry(1, 1);
|
|
729
|
+
const material = new THREE5.ShaderMaterial({
|
|
730
|
+
vertexShader: vertex_default4,
|
|
731
|
+
fragmentShader: fragment_default4,
|
|
732
|
+
uniforms: shaderUniforms.current,
|
|
733
|
+
depthWrite: false,
|
|
734
|
+
depthTest: false,
|
|
735
|
+
transparent: true,
|
|
736
|
+
blending: THREE5.AdditiveBlending
|
|
737
|
+
});
|
|
738
|
+
const mesh = new THREE5.Mesh(geometry, material);
|
|
739
|
+
scene.add(mesh);
|
|
740
|
+
assetsRef.current = { mesh, geometry, material };
|
|
741
|
+
sizeRef.current = size;
|
|
742
|
+
updateMeshScale();
|
|
743
|
+
updateVisibility();
|
|
744
|
+
return () => {
|
|
745
|
+
scene.remove(mesh);
|
|
746
|
+
geometry.dispose();
|
|
747
|
+
material.dispose();
|
|
748
|
+
assetsRef.current = null;
|
|
749
|
+
};
|
|
750
|
+
},
|
|
751
|
+
[updateMeshScale, updateVisibility]
|
|
752
|
+
);
|
|
753
|
+
const handleRender = useCallback4(
|
|
754
|
+
(_context, _delta, elapsedTime) => {
|
|
755
|
+
shaderUniforms.current.uTime.value = elapsedTime;
|
|
756
|
+
},
|
|
757
|
+
[]
|
|
758
|
+
);
|
|
759
|
+
const handleResize = useCallback4(
|
|
760
|
+
(_context, size) => {
|
|
761
|
+
sizeRef.current = size;
|
|
762
|
+
updateMeshScale();
|
|
763
|
+
},
|
|
764
|
+
[updateMeshScale]
|
|
765
|
+
);
|
|
766
|
+
const { containerRef } = useScene({
|
|
767
|
+
camera: { type: "orthographic", position: [0, 0, 10], near: 0.1, far: 100 },
|
|
768
|
+
onCreate: handleCreate,
|
|
769
|
+
onRender: handleRender,
|
|
770
|
+
onResize: handleResize
|
|
771
|
+
});
|
|
772
|
+
const showTimeline = useRef5(null);
|
|
773
|
+
const hideTimeline = useRef5(null);
|
|
774
|
+
const transitionTimeline = useRef5(null);
|
|
775
|
+
const timelineParams = useMemo2(
|
|
776
|
+
() => ({
|
|
777
|
+
tileAmplitude: sanitizedValues.tileAmplitude,
|
|
778
|
+
gradientAmplitude: sanitizedValues.gradientAmplitude,
|
|
779
|
+
gradientOffset: sanitizedValues.gradientOffset,
|
|
780
|
+
tileOffsetX: sanitizedValues.tileOffsetX,
|
|
781
|
+
duration: sanitizedValues.duration
|
|
782
|
+
}),
|
|
783
|
+
[
|
|
784
|
+
sanitizedValues.duration,
|
|
785
|
+
sanitizedValues.gradientAmplitude,
|
|
786
|
+
sanitizedValues.gradientOffset,
|
|
787
|
+
sanitizedValues.tileAmplitude,
|
|
788
|
+
sanitizedValues.tileOffsetX
|
|
789
|
+
]
|
|
790
|
+
);
|
|
791
|
+
const primeShowAnimation = useCallback4(() => {
|
|
792
|
+
const uniforms = shaderUniforms.current;
|
|
793
|
+
uniforms.uTileProgressHorizontal.value = 1 + timelineParams.tileAmplitude * 0.5;
|
|
794
|
+
uniforms.uGradientProgress.value = 1 + timelineParams.gradientOffset;
|
|
795
|
+
uniforms.uBlueProgress.value = 1 + timelineParams.tileOffsetX;
|
|
796
|
+
uniforms.uSaturation.value = 1;
|
|
797
|
+
uniforms.uWhiteTileStrength.value = 0;
|
|
798
|
+
}, [
|
|
799
|
+
timelineParams.gradientOffset,
|
|
800
|
+
timelineParams.tileAmplitude,
|
|
801
|
+
timelineParams.tileOffsetX
|
|
802
|
+
]);
|
|
803
|
+
const buildTimelines = useCallback4(() => {
|
|
804
|
+
const uniforms = shaderUniforms.current;
|
|
805
|
+
const glitchDuration = sanitizedRef.current.duration;
|
|
806
|
+
const desiredShowTotal = glitchDuration * (SHOW_BASE_DURATION / SHOW_PRIMARY_DURATION);
|
|
807
|
+
const desiredHideTotal = glitchDuration * (HIDE_BASE_DURATION / SHOW_PRIMARY_DURATION);
|
|
808
|
+
const showScale = desiredShowTotal / SHOW_BASE_DURATION;
|
|
809
|
+
const hideScale = desiredHideTotal / HIDE_BASE_DURATION;
|
|
810
|
+
const showAt = (time) => time / SHOW_BASE_DURATION * desiredShowTotal;
|
|
811
|
+
const hideAt = (time) => time / HIDE_BASE_DURATION * desiredHideTotal;
|
|
812
|
+
showTimeline.current?.kill();
|
|
813
|
+
hideTimeline.current?.kill();
|
|
814
|
+
transitionTimeline.current?.kill();
|
|
815
|
+
const showTl = gsap.timeline({ paused: true });
|
|
816
|
+
showTl.add(() => {
|
|
817
|
+
animationVisibleRef.current = true;
|
|
818
|
+
updateVisibility();
|
|
819
|
+
}, 0);
|
|
820
|
+
showTl.fromTo(
|
|
821
|
+
uniforms.uTileProgressHorizontal,
|
|
822
|
+
{ value: 1 + timelineParams.tileAmplitude * 0.5 },
|
|
823
|
+
{
|
|
824
|
+
value: -timelineParams.tileAmplitude * 0.5,
|
|
825
|
+
duration: glitchDuration,
|
|
826
|
+
ease: "sine.inOut"
|
|
827
|
+
},
|
|
828
|
+
0
|
|
829
|
+
);
|
|
830
|
+
showTl.fromTo(
|
|
831
|
+
uniforms.uGradientProgress,
|
|
832
|
+
{ value: 1 + timelineParams.gradientOffset },
|
|
833
|
+
{
|
|
834
|
+
value: -timelineParams.gradientOffset * 0.5 - timelineParams.gradientAmplitude,
|
|
835
|
+
duration: 0.6 * showScale,
|
|
836
|
+
ease: "sine.inOut"
|
|
837
|
+
},
|
|
838
|
+
showAt(0.1)
|
|
839
|
+
);
|
|
840
|
+
showTl.fromTo(
|
|
841
|
+
uniforms.uBlueProgress,
|
|
842
|
+
{ value: 1 + timelineParams.tileOffsetX },
|
|
843
|
+
{
|
|
844
|
+
value: -timelineParams.tileOffsetX * 0.5 - timelineParams.gradientAmplitude,
|
|
845
|
+
duration: 0.6 * showScale,
|
|
846
|
+
ease: "sine.inOut"
|
|
847
|
+
},
|
|
848
|
+
showAt(0.125)
|
|
849
|
+
);
|
|
850
|
+
showTl.fromTo(
|
|
851
|
+
uniforms.uSaturation,
|
|
852
|
+
{ value: 1 },
|
|
853
|
+
{ value: 1.01, duration: 0.52 * showScale, ease: "sine.inOut" },
|
|
854
|
+
0
|
|
855
|
+
);
|
|
856
|
+
showTl.fromTo(
|
|
857
|
+
uniforms.uSaturation,
|
|
858
|
+
{ value: 1 },
|
|
859
|
+
{ value: 2.5, duration: 0.1 * showScale, ease: "sine.inOut" },
|
|
860
|
+
showAt(0.32)
|
|
861
|
+
);
|
|
862
|
+
showTl.fromTo(
|
|
863
|
+
uniforms.uSaturation,
|
|
864
|
+
{ value: 2.5 },
|
|
865
|
+
{ value: 1, duration: 1.8 * showScale, ease: "sine.out" },
|
|
866
|
+
showAt(0.92)
|
|
867
|
+
);
|
|
868
|
+
showTl.fromTo(
|
|
869
|
+
uniforms.uWhiteTileStrength,
|
|
870
|
+
{ value: 0 },
|
|
871
|
+
{ value: 0.1, duration: 1 * showScale, ease: "sine.inOut" },
|
|
872
|
+
showAt(0.3)
|
|
873
|
+
);
|
|
874
|
+
const hideTl = gsap.timeline({ paused: true });
|
|
875
|
+
hideTl.fromTo(
|
|
876
|
+
uniforms.uWhiteTileStrength,
|
|
877
|
+
{ value: 0.1 },
|
|
878
|
+
{ value: 0, duration: 1 * hideScale, ease: "sine.inOut" },
|
|
879
|
+
0
|
|
880
|
+
);
|
|
881
|
+
hideTl.fromTo(
|
|
882
|
+
uniforms.uSaturation,
|
|
883
|
+
{ value: 1 },
|
|
884
|
+
{ value: 1.5, duration: 0.4 * hideScale, ease: "sine.inOut" },
|
|
885
|
+
hideAt(0.4)
|
|
886
|
+
);
|
|
887
|
+
hideTl.fromTo(
|
|
888
|
+
uniforms.uSaturation,
|
|
889
|
+
{ value: 1.5 },
|
|
890
|
+
{ value: 1, duration: 1 * hideScale, ease: "sine.inOut" },
|
|
891
|
+
hideAt(0.8)
|
|
892
|
+
);
|
|
893
|
+
hideTl.fromTo(
|
|
894
|
+
uniforms.uBlueProgress,
|
|
895
|
+
{
|
|
896
|
+
value: -timelineParams.tileOffsetX * 0.5 - timelineParams.gradientAmplitude
|
|
897
|
+
},
|
|
898
|
+
{
|
|
899
|
+
value: 1 + timelineParams.tileOffsetX,
|
|
900
|
+
duration: 0.6 * hideScale,
|
|
901
|
+
ease: "sine.inOut"
|
|
902
|
+
},
|
|
903
|
+
hideAt(0.2)
|
|
904
|
+
);
|
|
905
|
+
hideTl.fromTo(
|
|
906
|
+
uniforms.uTileProgressHorizontal,
|
|
907
|
+
{ value: -timelineParams.tileAmplitude * 0.5 },
|
|
908
|
+
{
|
|
909
|
+
value: 1 + timelineParams.tileAmplitude * 0.5,
|
|
910
|
+
duration: 0.9 * hideScale,
|
|
911
|
+
ease: "sine.inOut"
|
|
912
|
+
},
|
|
913
|
+
hideAt(0.2)
|
|
914
|
+
);
|
|
915
|
+
hideTl.fromTo(
|
|
916
|
+
uniforms.uGradientProgress,
|
|
917
|
+
{
|
|
918
|
+
value: -timelineParams.gradientOffset * 0.5 - timelineParams.gradientAmplitude
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
value: 1 + timelineParams.gradientOffset,
|
|
922
|
+
duration: 0.6 * hideScale,
|
|
923
|
+
ease: "sine.inOut"
|
|
924
|
+
},
|
|
925
|
+
hideAt(0.225)
|
|
926
|
+
);
|
|
927
|
+
hideTl.add(() => {
|
|
928
|
+
animationVisibleRef.current = false;
|
|
929
|
+
updateVisibility();
|
|
930
|
+
onHideDone?.();
|
|
931
|
+
}, hideAt(HIDE_BASE_DURATION));
|
|
932
|
+
showTl.call(
|
|
933
|
+
() => {
|
|
934
|
+
onShowDone?.();
|
|
935
|
+
},
|
|
936
|
+
void 0,
|
|
937
|
+
showAt(0.65)
|
|
938
|
+
);
|
|
939
|
+
showTimeline.current = showTl;
|
|
940
|
+
hideTimeline.current = hideTl;
|
|
941
|
+
}, [onHideDone, onShowDone, timelineParams, updateVisibility]);
|
|
942
|
+
useEffect5(() => {
|
|
943
|
+
const uniforms = shaderUniforms.current;
|
|
944
|
+
uniforms.tDiffuse.value = diffuseTexture;
|
|
945
|
+
if (gradientTextureRef.current) {
|
|
946
|
+
uniforms.tGradient.value = gradientTextureRef.current;
|
|
947
|
+
}
|
|
948
|
+
uniforms.uTileAmplitude.value = sanitizedValues.tileAmplitude;
|
|
949
|
+
uniforms.uTileOffset.value.set(
|
|
950
|
+
sanitizedValues.tileOffsetX,
|
|
951
|
+
sanitizedValues.tileOffsetY
|
|
952
|
+
);
|
|
953
|
+
uniforms.uTileFrequency.value.set(
|
|
954
|
+
sanitizedValues.tileFrequencyX,
|
|
955
|
+
sanitizedValues.tileFrequencyY
|
|
956
|
+
);
|
|
957
|
+
uniforms.uWaveAmplitude.value = sanitizedValues.waveAmplitude;
|
|
958
|
+
uniforms.uWaveProgress.value = sanitizedValues.waveProgress;
|
|
959
|
+
uniforms.uWaveStrength.value.set(
|
|
960
|
+
sanitizedValues.waveStrengthX,
|
|
961
|
+
sanitizedValues.waveStrengthY
|
|
962
|
+
);
|
|
963
|
+
uniforms.uGradientProgress.value = sanitizedValues.gradientProgress;
|
|
964
|
+
uniforms.uGradientOffset.value = sanitizedValues.gradientOffset;
|
|
965
|
+
uniforms.uGradientAmplitude.value = sanitizedValues.gradientAmplitude;
|
|
966
|
+
uniforms.uBlueProgress.value = sanitizedValues.blueProgress;
|
|
967
|
+
uniforms.uBlueAmplitude.value = sanitizedValues.blueAmplitude;
|
|
968
|
+
uniforms.uWhiteTileChances.value = sanitizedValues.whiteTileChances;
|
|
969
|
+
uniforms.uWhiteTileFrequency.value = sanitizedValues.whiteTileFrequency;
|
|
970
|
+
uniforms.uWhiteTileStrength.value = sanitizedValues.whiteTileStrength;
|
|
971
|
+
uniforms.uSaturation.value = sanitizedValues.saturation;
|
|
972
|
+
uniforms.uTileProgressVertical.value = BASE_TRANSITION_PROGRESS;
|
|
973
|
+
updateMeshScale();
|
|
974
|
+
updateVisibility();
|
|
975
|
+
}, [diffuseTexture, sanitizedValues, updateMeshScale, updateVisibility]);
|
|
976
|
+
useEffect5(() => {
|
|
977
|
+
buildTimelines();
|
|
978
|
+
return () => {
|
|
979
|
+
showTimeline.current?.kill();
|
|
980
|
+
hideTimeline.current?.kill();
|
|
981
|
+
transitionTimeline.current?.kill();
|
|
982
|
+
};
|
|
983
|
+
}, [buildTimelines]);
|
|
984
|
+
useEffect5(() => {
|
|
985
|
+
const mesh = assetsRef.current?.mesh;
|
|
986
|
+
if (mesh) {
|
|
987
|
+
mesh.visible = sanitizedValues.debug || animationVisibleRef.current;
|
|
988
|
+
}
|
|
989
|
+
}, [sanitizedValues.debug]);
|
|
990
|
+
const lastShowSignal = useRef5(settings.showSignal);
|
|
991
|
+
useEffect5(() => {
|
|
992
|
+
if (settings.showSignal === lastShowSignal.current) {
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
lastShowSignal.current = settings.showSignal;
|
|
996
|
+
hideTimeline.current?.pause(0);
|
|
997
|
+
primeShowAnimation();
|
|
998
|
+
showTimeline.current?.seek(0).play();
|
|
999
|
+
}, [primeShowAnimation, settings.showSignal]);
|
|
1000
|
+
const lastHideSignal = useRef5(settings.hideSignal);
|
|
1001
|
+
useEffect5(() => {
|
|
1002
|
+
if (settings.hideSignal === lastHideSignal.current) {
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
lastHideSignal.current = settings.hideSignal;
|
|
1006
|
+
showTimeline.current?.pause(0);
|
|
1007
|
+
hideTimeline.current?.seek(0).play();
|
|
1008
|
+
}, [settings.hideSignal]);
|
|
1009
|
+
return /* @__PURE__ */ jsx4(
|
|
1010
|
+
"div",
|
|
1011
|
+
{
|
|
1012
|
+
ref: containerRef,
|
|
1013
|
+
className,
|
|
1014
|
+
style: {
|
|
1015
|
+
width: width ?? "100%",
|
|
1016
|
+
height: height ?? "100%",
|
|
1017
|
+
...style
|
|
1018
|
+
},
|
|
1019
|
+
...divProps
|
|
1020
|
+
}
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
function createDiffuseTexture() {
|
|
1024
|
+
const size = 256;
|
|
1025
|
+
const data = new Uint8Array(size * size * 4);
|
|
1026
|
+
for (let y = 0; y < size; y += 1) {
|
|
1027
|
+
for (let x = 0; x < size; x += 1) {
|
|
1028
|
+
const i = (y * size + x) * 4;
|
|
1029
|
+
const stripe = Math.sin(y / size * Math.PI * 8) * 0.5 + 0.5;
|
|
1030
|
+
const tint = 0.25 + Math.sin(x / size * Math.PI * 2) * 0.15;
|
|
1031
|
+
const base = THREE5.MathUtils.clamp(stripe * 0.7 + tint, 0, 1);
|
|
1032
|
+
data[i] = base * 255;
|
|
1033
|
+
data[i + 1] = base * 200;
|
|
1034
|
+
data[i + 2] = base * 150;
|
|
1035
|
+
data[i + 3] = 255;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
const texture = new THREE5.DataTexture(data, size, size, THREE5.RGBAFormat);
|
|
1039
|
+
texture.needsUpdate = true;
|
|
1040
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
1041
|
+
texture.wrapS = THREE5.RepeatWrapping;
|
|
1042
|
+
texture.wrapT = THREE5.RepeatWrapping;
|
|
1043
|
+
texture.magFilter = THREE5.LinearFilter;
|
|
1044
|
+
texture.minFilter = THREE5.LinearMipmapLinearFilter;
|
|
1045
|
+
texture.generateMipmaps = true;
|
|
1046
|
+
return texture;
|
|
1047
|
+
}
|
|
528
1048
|
export {
|
|
529
1049
|
FractalFlower,
|
|
1050
|
+
MenuGlitch,
|
|
530
1051
|
OranoParticles,
|
|
531
1052
|
ShaderArt
|
|
532
1053
|
};
|