@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.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
FractalFlower: () => FractalFlower,
|
|
34
|
+
MenuGlitch: () => MenuGlitch,
|
|
34
35
|
OranoParticles: () => OranoParticles,
|
|
35
36
|
ShaderArt: () => ShaderArt
|
|
36
37
|
});
|
|
@@ -58,6 +59,7 @@ function useScene({
|
|
|
58
59
|
const onCreateRef = (0, import_react.useRef)(onCreate);
|
|
59
60
|
const onRenderRef = (0, import_react.useRef)(onRender);
|
|
60
61
|
const onResizeRef = (0, import_react.useRef)(onResize);
|
|
62
|
+
const sizeRef = (0, import_react.useRef)({ width: 0, height: 0 });
|
|
61
63
|
(0, import_react.useEffect)(() => {
|
|
62
64
|
onCreateRef.current = onCreate;
|
|
63
65
|
}, [onCreate]);
|
|
@@ -72,43 +74,83 @@ function useScene({
|
|
|
72
74
|
const container = containerRef.current;
|
|
73
75
|
if (!container) return;
|
|
74
76
|
const resolvedPixelRatio = pixelRatio ?? (typeof window !== "undefined" ? Math.min(window.devicePixelRatio, 2) : 1);
|
|
77
|
+
const initialWidth = container.clientWidth || 1;
|
|
78
|
+
const initialHeight = container.clientHeight || 1;
|
|
79
|
+
sizeRef.current = { width: initialWidth, height: initialHeight };
|
|
75
80
|
const renderer = new THREE.WebGLRenderer({
|
|
76
81
|
alpha: true,
|
|
77
82
|
antialias: true,
|
|
78
83
|
...rendererOptions
|
|
79
84
|
});
|
|
80
85
|
renderer.setPixelRatio(resolvedPixelRatio);
|
|
81
|
-
renderer.setSize(
|
|
86
|
+
renderer.setSize(initialWidth, initialHeight, false);
|
|
82
87
|
renderer.setClearColor(0, 0);
|
|
83
88
|
renderer.domElement.style.width = "100%";
|
|
84
89
|
renderer.domElement.style.height = "100%";
|
|
85
90
|
container.appendChild(renderer.domElement);
|
|
86
91
|
const scene = new THREE.Scene();
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
let camera;
|
|
93
|
+
if (cameraOptions?.type === "orthographic") {
|
|
94
|
+
const halfWidth = initialWidth / 2;
|
|
95
|
+
const halfHeight = initialHeight / 2;
|
|
96
|
+
const orthoCamera = new THREE.OrthographicCamera(
|
|
97
|
+
-halfWidth,
|
|
98
|
+
halfWidth,
|
|
99
|
+
halfHeight,
|
|
100
|
+
-halfHeight,
|
|
101
|
+
cameraOptions?.near ?? 0.1,
|
|
102
|
+
cameraOptions?.far ?? 1e3
|
|
103
|
+
);
|
|
104
|
+
const [, , z = 10] = cameraOptions?.position ?? [];
|
|
105
|
+
orthoCamera.position.set(0, 0, z);
|
|
106
|
+
camera = orthoCamera;
|
|
107
|
+
} else {
|
|
108
|
+
const perspectiveCamera = new THREE.PerspectiveCamera(
|
|
109
|
+
cameraOptions?.fov ?? 55,
|
|
110
|
+
initialWidth / Math.max(1, initialHeight),
|
|
111
|
+
cameraOptions?.near ?? 0.1,
|
|
112
|
+
cameraOptions?.far ?? 500
|
|
113
|
+
);
|
|
114
|
+
const [x = 0, y = 0, z = 15] = cameraOptions?.position ?? [];
|
|
115
|
+
perspectiveCamera.position.set(x, y, z);
|
|
116
|
+
camera = perspectiveCamera;
|
|
117
|
+
}
|
|
95
118
|
const clock = new THREE.Clock();
|
|
96
|
-
const context = {
|
|
119
|
+
const context = {
|
|
120
|
+
renderer,
|
|
121
|
+
scene,
|
|
122
|
+
camera,
|
|
123
|
+
clock,
|
|
124
|
+
size: { ...sizeRef.current }
|
|
125
|
+
};
|
|
97
126
|
contextRef.current = context;
|
|
98
127
|
const teardownCreate = onCreateRef.current?.(context);
|
|
128
|
+
let elapsedTime = 0;
|
|
99
129
|
let animationFrameId = 0;
|
|
100
130
|
const renderLoop = () => {
|
|
101
|
-
|
|
131
|
+
const delta = clock.getDelta();
|
|
132
|
+
elapsedTime += delta;
|
|
133
|
+
context.size = { ...sizeRef.current };
|
|
134
|
+
onRenderRef.current?.(context, delta, elapsedTime);
|
|
102
135
|
renderer.render(scene, camera);
|
|
103
136
|
animationFrameId = requestAnimationFrame(renderLoop);
|
|
104
137
|
};
|
|
105
138
|
animationFrameId = requestAnimationFrame(renderLoop);
|
|
106
139
|
const resizeObserver = new ResizeObserver(() => {
|
|
107
|
-
const width = container.clientWidth;
|
|
108
|
-
const height = container.clientHeight;
|
|
140
|
+
const width = container.clientWidth || 1;
|
|
141
|
+
const height = container.clientHeight || 1;
|
|
109
142
|
renderer.setSize(width, height, false);
|
|
110
|
-
|
|
143
|
+
sizeRef.current = { width, height };
|
|
144
|
+
if (camera instanceof THREE.PerspectiveCamera) {
|
|
145
|
+
camera.aspect = width / Math.max(1, height);
|
|
146
|
+
} else if (camera instanceof THREE.OrthographicCamera) {
|
|
147
|
+
camera.left = -width / 2;
|
|
148
|
+
camera.right = width / 2;
|
|
149
|
+
camera.top = height / 2;
|
|
150
|
+
camera.bottom = -height / 2;
|
|
151
|
+
}
|
|
111
152
|
camera.updateProjectionMatrix();
|
|
153
|
+
context.size = { ...sizeRef.current };
|
|
112
154
|
onResizeRef.current?.(context, { width, height });
|
|
113
155
|
});
|
|
114
156
|
resizeObserver.observe(container);
|
|
@@ -168,15 +210,14 @@ function ShaderArt({
|
|
|
168
210
|
assetsRef.current = null;
|
|
169
211
|
};
|
|
170
212
|
}, []);
|
|
171
|
-
const handleRender = (0, import_react2.useCallback)(
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}, []);
|
|
213
|
+
const handleRender = (0, import_react2.useCallback)(
|
|
214
|
+
(context, _delta, elapsedTime) => {
|
|
215
|
+
shaderUniformsRef.current.iTime.value = elapsedTime;
|
|
216
|
+
const { width: width2, height: height2 } = context.size;
|
|
217
|
+
shaderUniformsRef.current.iResolution.value.set(width2, height2, 1);
|
|
218
|
+
},
|
|
219
|
+
[]
|
|
220
|
+
);
|
|
180
221
|
const { containerRef } = useScene({
|
|
181
222
|
onCreate: handleCreate,
|
|
182
223
|
onRender: handleRender
|
|
@@ -318,7 +359,12 @@ function FractalFlower({
|
|
|
318
359
|
const points = new THREE3.Points(geometry, material);
|
|
319
360
|
points.frustumCulled = false;
|
|
320
361
|
scene.add(points);
|
|
321
|
-
assetsRef.current = {
|
|
362
|
+
assetsRef.current = {
|
|
363
|
+
points,
|
|
364
|
+
geometry,
|
|
365
|
+
material,
|
|
366
|
+
uniforms: uniformValues
|
|
367
|
+
};
|
|
322
368
|
return () => {
|
|
323
369
|
scene.remove(points);
|
|
324
370
|
geometry.dispose();
|
|
@@ -326,25 +372,29 @@ function FractalFlower({
|
|
|
326
372
|
assetsRef.current = null;
|
|
327
373
|
};
|
|
328
374
|
},
|
|
329
|
-
[
|
|
375
|
+
[
|
|
376
|
+
attributes.eValues,
|
|
377
|
+
attributes.kValues,
|
|
378
|
+
attributes.positions,
|
|
379
|
+
attributes.rotations
|
|
380
|
+
]
|
|
330
381
|
);
|
|
331
382
|
const handleRender = (0, import_react3.useCallback)(
|
|
332
|
-
(context) => {
|
|
383
|
+
(context, delta, elapsedTime) => {
|
|
333
384
|
const assets = assetsRef.current;
|
|
334
385
|
if (!assets) return;
|
|
335
386
|
const uniforms = assets.uniforms;
|
|
336
|
-
uniforms.uTime.value =
|
|
337
|
-
const
|
|
338
|
-
uniforms.uResolution.value.set(
|
|
387
|
+
uniforms.uTime.value = elapsedTime;
|
|
388
|
+
const { width: width2, height: height2 } = context.size;
|
|
389
|
+
uniforms.uResolution.value.set(width2, height2);
|
|
339
390
|
const basePointSize = Math.max(
|
|
340
391
|
2,
|
|
341
|
-
|
|
392
|
+
height2 / 400 * (uniforms.uPetalRadius.value * 32)
|
|
342
393
|
);
|
|
343
394
|
const pointSize = Math.min(basePointSize, 6);
|
|
344
395
|
uniforms.uPointSize.value = pointSize;
|
|
345
396
|
const morph = morphRef.current;
|
|
346
397
|
if (Math.abs(morph.target - morph.progress) > 1e-3) {
|
|
347
|
-
const delta = context.clock.getDelta();
|
|
348
398
|
const direction = Math.sign(morph.target - morph.progress);
|
|
349
399
|
morph.progress = clamp(
|
|
350
400
|
morph.progress + direction * delta * MORPH_SPEED,
|
|
@@ -495,11 +545,14 @@ function OranoParticles({
|
|
|
495
545
|
particlesRef.current = null;
|
|
496
546
|
};
|
|
497
547
|
}, []);
|
|
498
|
-
const handleRender = (0, import_react4.useCallback)(
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
548
|
+
const handleRender = (0, import_react4.useCallback)(
|
|
549
|
+
(_context, _delta, elapsedTime) => {
|
|
550
|
+
const assets = particlesRef.current;
|
|
551
|
+
if (!assets) return;
|
|
552
|
+
assets.uniforms.uTime.value = elapsedTime;
|
|
553
|
+
},
|
|
554
|
+
[]
|
|
555
|
+
);
|
|
503
556
|
const { containerRef } = useScene({
|
|
504
557
|
onCreate: handleCreate,
|
|
505
558
|
onRender: handleRender
|
|
@@ -558,9 +611,473 @@ function OranoParticles({
|
|
|
558
611
|
}
|
|
559
612
|
);
|
|
560
613
|
}
|
|
614
|
+
|
|
615
|
+
// src/components/MenuGlitch.tsx
|
|
616
|
+
var import_gsap = require("gsap");
|
|
617
|
+
var import_react5 = require("react");
|
|
618
|
+
var THREE5 = __toESM(require("three"));
|
|
619
|
+
|
|
620
|
+
// src/shaders/menu-glitch/fragment.glsl
|
|
621
|
+
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";
|
|
622
|
+
|
|
623
|
+
// src/shaders/menu-glitch/vertex.glsl
|
|
624
|
+
var vertex_default4 = "varying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n";
|
|
625
|
+
|
|
626
|
+
// src/components/MenuGlitch.tsx
|
|
627
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
628
|
+
var GRADIENT_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTVBRkY1OTJDREMyMTFFODhGRjFFRjgxRjM2QjM2MDMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTVBRkY1OTNDREMyMTFFODhGRjFFRjgxRjM2QjM2MDMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFNUFGRjU5MENEQzIxMUU4OEZGMUVGODFGMzZCMzYwMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFNUFGRjU5MUNEQzIxMUU4OEZGMUVGODFGMzZCMzYwMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pksi3ywAAADMSURBVHjarFDLDoMwDDMtUDjtME3TtMcn7f9/hngBCoTSTjsMydixnVZqxTcAX51Quwsad1M80PonWvdCUA7+rrii82eEulcG+hoTdwsrQtRB0UZu3KxrN8OPqIBKgRHxI8qaUTD1RuY2p90V+hOjmWix2uSSeGLPKrDdKc5GHzqZLPWY7XEG+F1PLBktpiuzf8ilkMvqcZfLLqf1ltnu7rLh4G88ZPxh4uUOmjMYO3aPqz8Yve0tGiaDduNr/xn8cWbBY8HLzQd8BBgAgOx+ERYDbIEAAAAASUVORK5CYII=";
|
|
629
|
+
var BASE_TRANSITION_PROGRESS = 0.5;
|
|
630
|
+
var SHOW_BASE_DURATION = 2.72;
|
|
631
|
+
var HIDE_BASE_DURATION = 1.8;
|
|
632
|
+
var SHOW_PRIMARY_DURATION = 1.1;
|
|
633
|
+
var MIN_GLITCH_DURATION = 0.25;
|
|
634
|
+
function MenuGlitch({
|
|
635
|
+
settings,
|
|
636
|
+
onShowDone,
|
|
637
|
+
onHideDone,
|
|
638
|
+
className,
|
|
639
|
+
style,
|
|
640
|
+
width,
|
|
641
|
+
height,
|
|
642
|
+
...divProps
|
|
643
|
+
}) {
|
|
644
|
+
const diffuseTexture = (0, import_react5.useMemo)(() => createDiffuseTexture(), []);
|
|
645
|
+
const gradientTextureRef = (0, import_react5.useRef)(new THREE5.Texture());
|
|
646
|
+
const sanitizedValues = (0, import_react5.useMemo)(() => {
|
|
647
|
+
const clamp2 = THREE5.MathUtils.clamp;
|
|
648
|
+
return {
|
|
649
|
+
tileAmplitude: Math.max(0.1, settings.tileAmplitude),
|
|
650
|
+
planeScale: Math.max(0.1, settings.planeScale ?? 1),
|
|
651
|
+
tileOffsetX: settings.tileOffset.x,
|
|
652
|
+
tileOffsetY: settings.tileOffset.y,
|
|
653
|
+
tileFrequencyX: Math.max(0.1, settings.tileFrequency.x),
|
|
654
|
+
tileFrequencyY: Math.max(0.1, settings.tileFrequency.y),
|
|
655
|
+
gradientAmplitude: Math.max(0.05, settings.gradientAmplitude),
|
|
656
|
+
gradientOffset: settings.gradientOffset,
|
|
657
|
+
gradientProgress: settings.gradientProgress ?? 1,
|
|
658
|
+
blueAmplitude: Math.max(0.05, settings.blueAmplitude),
|
|
659
|
+
blueProgress: settings.blueProgress ?? 1,
|
|
660
|
+
waveAmplitude: Math.max(0.05, settings.waveAmplitude),
|
|
661
|
+
waveProgress: settings.waveProgress ?? 0.5,
|
|
662
|
+
waveStrengthX: settings.waveStrength.x,
|
|
663
|
+
waveStrengthY: settings.waveStrength.y,
|
|
664
|
+
whiteTileChances: clamp2(settings.whiteTileChances, 0.05, 1),
|
|
665
|
+
whiteTileFrequency: Math.max(0.01, settings.whiteTileFrequency),
|
|
666
|
+
whiteTileStrength: Math.max(0, settings.whiteTileStrength),
|
|
667
|
+
saturation: Math.max(0, settings.saturation),
|
|
668
|
+
duration: Math.max(
|
|
669
|
+
MIN_GLITCH_DURATION,
|
|
670
|
+
settings.duration ?? SHOW_PRIMARY_DURATION
|
|
671
|
+
),
|
|
672
|
+
debug: settings.debug
|
|
673
|
+
};
|
|
674
|
+
}, [settings]);
|
|
675
|
+
const sanitizedRef = (0, import_react5.useRef)(sanitizedValues);
|
|
676
|
+
sanitizedRef.current = sanitizedValues;
|
|
677
|
+
const sizeRef = (0, import_react5.useRef)({ width: 0, height: 0 });
|
|
678
|
+
const assetsRef = (0, import_react5.useRef)(null);
|
|
679
|
+
const animationVisibleRef = (0, import_react5.useRef)(false);
|
|
680
|
+
const shaderUniforms = (0, import_react5.useRef)({
|
|
681
|
+
tDiffuse: { value: diffuseTexture },
|
|
682
|
+
tGradient: { value: gradientTextureRef.current },
|
|
683
|
+
uTime: { value: 0 },
|
|
684
|
+
uTileProgressVertical: { value: -0.5 },
|
|
685
|
+
uTileProgressHorizontal: { value: -0.5 },
|
|
686
|
+
uTileAmplitude: { value: settings.tileAmplitude },
|
|
687
|
+
uTileOffset: {
|
|
688
|
+
value: new THREE5.Vector2(settings.tileOffset.x, settings.tileOffset.y)
|
|
689
|
+
},
|
|
690
|
+
uTileFrequency: {
|
|
691
|
+
value: new THREE5.Vector2(
|
|
692
|
+
settings.tileFrequency.x,
|
|
693
|
+
settings.tileFrequency.y
|
|
694
|
+
)
|
|
695
|
+
},
|
|
696
|
+
uWaveProgress: { value: settings.waveProgress },
|
|
697
|
+
uWaveAmplitude: { value: settings.waveAmplitude },
|
|
698
|
+
uWaveStrength: {
|
|
699
|
+
value: new THREE5.Vector2(
|
|
700
|
+
settings.waveStrength.x,
|
|
701
|
+
settings.waveStrength.y
|
|
702
|
+
)
|
|
703
|
+
},
|
|
704
|
+
uGradientProgress: { value: settings.gradientProgress },
|
|
705
|
+
uGradientOffset: { value: settings.gradientOffset },
|
|
706
|
+
uGradientAmplitude: { value: settings.gradientAmplitude },
|
|
707
|
+
uBlueProgress: { value: settings.blueProgress },
|
|
708
|
+
uBlueAmplitude: { value: settings.blueAmplitude },
|
|
709
|
+
uWhiteTileChances: { value: settings.whiteTileChances },
|
|
710
|
+
uWhiteTileFrequency: { value: settings.whiteTileFrequency },
|
|
711
|
+
uWhiteTileStrength: { value: settings.whiteTileStrength },
|
|
712
|
+
uSaturation: { value: settings.saturation }
|
|
713
|
+
});
|
|
714
|
+
(0, import_react5.useEffect)(() => {
|
|
715
|
+
let disposed = false;
|
|
716
|
+
const loader = new THREE5.TextureLoader();
|
|
717
|
+
loader.load(
|
|
718
|
+
GRADIENT_DATA_URL,
|
|
719
|
+
(texture) => {
|
|
720
|
+
if (disposed) return;
|
|
721
|
+
texture.wrapS = THREE5.ClampToEdgeWrapping;
|
|
722
|
+
texture.wrapT = THREE5.ClampToEdgeWrapping;
|
|
723
|
+
texture.magFilter = THREE5.LinearFilter;
|
|
724
|
+
texture.minFilter = THREE5.LinearFilter;
|
|
725
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
726
|
+
gradientTextureRef.current = texture;
|
|
727
|
+
shaderUniforms.current.tGradient.value = texture;
|
|
728
|
+
},
|
|
729
|
+
void 0,
|
|
730
|
+
() => {
|
|
731
|
+
if (disposed) return;
|
|
732
|
+
gradientTextureRef.current = new THREE5.Texture();
|
|
733
|
+
shaderUniforms.current.tGradient.value = gradientTextureRef.current;
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
return () => {
|
|
737
|
+
disposed = true;
|
|
738
|
+
};
|
|
739
|
+
}, []);
|
|
740
|
+
const updateMeshScale = (0, import_react5.useCallback)(() => {
|
|
741
|
+
const assets = assetsRef.current;
|
|
742
|
+
if (!assets) return;
|
|
743
|
+
const base = Math.max(
|
|
744
|
+
sizeRef.current.width || 1,
|
|
745
|
+
sizeRef.current.height || 1
|
|
746
|
+
);
|
|
747
|
+
const scale = base * sanitizedRef.current.planeScale;
|
|
748
|
+
assets.mesh.scale.set(scale, scale, 1);
|
|
749
|
+
}, []);
|
|
750
|
+
const updateVisibility = (0, import_react5.useCallback)(() => {
|
|
751
|
+
const mesh = assetsRef.current?.mesh;
|
|
752
|
+
if (!mesh) return;
|
|
753
|
+
mesh.visible = sanitizedRef.current.debug || animationVisibleRef.current;
|
|
754
|
+
}, []);
|
|
755
|
+
const handleCreate = (0, import_react5.useCallback)(
|
|
756
|
+
({ scene, size }) => {
|
|
757
|
+
const geometry = new THREE5.PlaneGeometry(1, 1);
|
|
758
|
+
const material = new THREE5.ShaderMaterial({
|
|
759
|
+
vertexShader: vertex_default4,
|
|
760
|
+
fragmentShader: fragment_default4,
|
|
761
|
+
uniforms: shaderUniforms.current,
|
|
762
|
+
depthWrite: false,
|
|
763
|
+
depthTest: false,
|
|
764
|
+
transparent: true,
|
|
765
|
+
blending: THREE5.AdditiveBlending
|
|
766
|
+
});
|
|
767
|
+
const mesh = new THREE5.Mesh(geometry, material);
|
|
768
|
+
scene.add(mesh);
|
|
769
|
+
assetsRef.current = { mesh, geometry, material };
|
|
770
|
+
sizeRef.current = size;
|
|
771
|
+
updateMeshScale();
|
|
772
|
+
updateVisibility();
|
|
773
|
+
return () => {
|
|
774
|
+
scene.remove(mesh);
|
|
775
|
+
geometry.dispose();
|
|
776
|
+
material.dispose();
|
|
777
|
+
assetsRef.current = null;
|
|
778
|
+
};
|
|
779
|
+
},
|
|
780
|
+
[updateMeshScale, updateVisibility]
|
|
781
|
+
);
|
|
782
|
+
const handleRender = (0, import_react5.useCallback)(
|
|
783
|
+
(_context, _delta, elapsedTime) => {
|
|
784
|
+
shaderUniforms.current.uTime.value = elapsedTime;
|
|
785
|
+
},
|
|
786
|
+
[]
|
|
787
|
+
);
|
|
788
|
+
const handleResize = (0, import_react5.useCallback)(
|
|
789
|
+
(_context, size) => {
|
|
790
|
+
sizeRef.current = size;
|
|
791
|
+
updateMeshScale();
|
|
792
|
+
},
|
|
793
|
+
[updateMeshScale]
|
|
794
|
+
);
|
|
795
|
+
const { containerRef } = useScene({
|
|
796
|
+
camera: { type: "orthographic", position: [0, 0, 10], near: 0.1, far: 100 },
|
|
797
|
+
onCreate: handleCreate,
|
|
798
|
+
onRender: handleRender,
|
|
799
|
+
onResize: handleResize
|
|
800
|
+
});
|
|
801
|
+
const showTimeline = (0, import_react5.useRef)(null);
|
|
802
|
+
const hideTimeline = (0, import_react5.useRef)(null);
|
|
803
|
+
const transitionTimeline = (0, import_react5.useRef)(null);
|
|
804
|
+
const timelineParams = (0, import_react5.useMemo)(
|
|
805
|
+
() => ({
|
|
806
|
+
tileAmplitude: sanitizedValues.tileAmplitude,
|
|
807
|
+
gradientAmplitude: sanitizedValues.gradientAmplitude,
|
|
808
|
+
gradientOffset: sanitizedValues.gradientOffset,
|
|
809
|
+
tileOffsetX: sanitizedValues.tileOffsetX,
|
|
810
|
+
duration: sanitizedValues.duration
|
|
811
|
+
}),
|
|
812
|
+
[
|
|
813
|
+
sanitizedValues.duration,
|
|
814
|
+
sanitizedValues.gradientAmplitude,
|
|
815
|
+
sanitizedValues.gradientOffset,
|
|
816
|
+
sanitizedValues.tileAmplitude,
|
|
817
|
+
sanitizedValues.tileOffsetX
|
|
818
|
+
]
|
|
819
|
+
);
|
|
820
|
+
const primeShowAnimation = (0, import_react5.useCallback)(() => {
|
|
821
|
+
const uniforms = shaderUniforms.current;
|
|
822
|
+
uniforms.uTileProgressHorizontal.value = 1 + timelineParams.tileAmplitude * 0.5;
|
|
823
|
+
uniforms.uGradientProgress.value = 1 + timelineParams.gradientOffset;
|
|
824
|
+
uniforms.uBlueProgress.value = 1 + timelineParams.tileOffsetX;
|
|
825
|
+
uniforms.uSaturation.value = 1;
|
|
826
|
+
uniforms.uWhiteTileStrength.value = 0;
|
|
827
|
+
}, [
|
|
828
|
+
timelineParams.gradientOffset,
|
|
829
|
+
timelineParams.tileAmplitude,
|
|
830
|
+
timelineParams.tileOffsetX
|
|
831
|
+
]);
|
|
832
|
+
const buildTimelines = (0, import_react5.useCallback)(() => {
|
|
833
|
+
const uniforms = shaderUniforms.current;
|
|
834
|
+
const glitchDuration = sanitizedRef.current.duration;
|
|
835
|
+
const desiredShowTotal = glitchDuration * (SHOW_BASE_DURATION / SHOW_PRIMARY_DURATION);
|
|
836
|
+
const desiredHideTotal = glitchDuration * (HIDE_BASE_DURATION / SHOW_PRIMARY_DURATION);
|
|
837
|
+
const showScale = desiredShowTotal / SHOW_BASE_DURATION;
|
|
838
|
+
const hideScale = desiredHideTotal / HIDE_BASE_DURATION;
|
|
839
|
+
const showAt = (time) => time / SHOW_BASE_DURATION * desiredShowTotal;
|
|
840
|
+
const hideAt = (time) => time / HIDE_BASE_DURATION * desiredHideTotal;
|
|
841
|
+
showTimeline.current?.kill();
|
|
842
|
+
hideTimeline.current?.kill();
|
|
843
|
+
transitionTimeline.current?.kill();
|
|
844
|
+
const showTl = import_gsap.gsap.timeline({ paused: true });
|
|
845
|
+
showTl.add(() => {
|
|
846
|
+
animationVisibleRef.current = true;
|
|
847
|
+
updateVisibility();
|
|
848
|
+
}, 0);
|
|
849
|
+
showTl.fromTo(
|
|
850
|
+
uniforms.uTileProgressHorizontal,
|
|
851
|
+
{ value: 1 + timelineParams.tileAmplitude * 0.5 },
|
|
852
|
+
{
|
|
853
|
+
value: -timelineParams.tileAmplitude * 0.5,
|
|
854
|
+
duration: glitchDuration,
|
|
855
|
+
ease: "sine.inOut"
|
|
856
|
+
},
|
|
857
|
+
0
|
|
858
|
+
);
|
|
859
|
+
showTl.fromTo(
|
|
860
|
+
uniforms.uGradientProgress,
|
|
861
|
+
{ value: 1 + timelineParams.gradientOffset },
|
|
862
|
+
{
|
|
863
|
+
value: -timelineParams.gradientOffset * 0.5 - timelineParams.gradientAmplitude,
|
|
864
|
+
duration: 0.6 * showScale,
|
|
865
|
+
ease: "sine.inOut"
|
|
866
|
+
},
|
|
867
|
+
showAt(0.1)
|
|
868
|
+
);
|
|
869
|
+
showTl.fromTo(
|
|
870
|
+
uniforms.uBlueProgress,
|
|
871
|
+
{ value: 1 + timelineParams.tileOffsetX },
|
|
872
|
+
{
|
|
873
|
+
value: -timelineParams.tileOffsetX * 0.5 - timelineParams.gradientAmplitude,
|
|
874
|
+
duration: 0.6 * showScale,
|
|
875
|
+
ease: "sine.inOut"
|
|
876
|
+
},
|
|
877
|
+
showAt(0.125)
|
|
878
|
+
);
|
|
879
|
+
showTl.fromTo(
|
|
880
|
+
uniforms.uSaturation,
|
|
881
|
+
{ value: 1 },
|
|
882
|
+
{ value: 1.01, duration: 0.52 * showScale, ease: "sine.inOut" },
|
|
883
|
+
0
|
|
884
|
+
);
|
|
885
|
+
showTl.fromTo(
|
|
886
|
+
uniforms.uSaturation,
|
|
887
|
+
{ value: 1 },
|
|
888
|
+
{ value: 2.5, duration: 0.1 * showScale, ease: "sine.inOut" },
|
|
889
|
+
showAt(0.32)
|
|
890
|
+
);
|
|
891
|
+
showTl.fromTo(
|
|
892
|
+
uniforms.uSaturation,
|
|
893
|
+
{ value: 2.5 },
|
|
894
|
+
{ value: 1, duration: 1.8 * showScale, ease: "sine.out" },
|
|
895
|
+
showAt(0.92)
|
|
896
|
+
);
|
|
897
|
+
showTl.fromTo(
|
|
898
|
+
uniforms.uWhiteTileStrength,
|
|
899
|
+
{ value: 0 },
|
|
900
|
+
{ value: 0.1, duration: 1 * showScale, ease: "sine.inOut" },
|
|
901
|
+
showAt(0.3)
|
|
902
|
+
);
|
|
903
|
+
const hideTl = import_gsap.gsap.timeline({ paused: true });
|
|
904
|
+
hideTl.fromTo(
|
|
905
|
+
uniforms.uWhiteTileStrength,
|
|
906
|
+
{ value: 0.1 },
|
|
907
|
+
{ value: 0, duration: 1 * hideScale, ease: "sine.inOut" },
|
|
908
|
+
0
|
|
909
|
+
);
|
|
910
|
+
hideTl.fromTo(
|
|
911
|
+
uniforms.uSaturation,
|
|
912
|
+
{ value: 1 },
|
|
913
|
+
{ value: 1.5, duration: 0.4 * hideScale, ease: "sine.inOut" },
|
|
914
|
+
hideAt(0.4)
|
|
915
|
+
);
|
|
916
|
+
hideTl.fromTo(
|
|
917
|
+
uniforms.uSaturation,
|
|
918
|
+
{ value: 1.5 },
|
|
919
|
+
{ value: 1, duration: 1 * hideScale, ease: "sine.inOut" },
|
|
920
|
+
hideAt(0.8)
|
|
921
|
+
);
|
|
922
|
+
hideTl.fromTo(
|
|
923
|
+
uniforms.uBlueProgress,
|
|
924
|
+
{
|
|
925
|
+
value: -timelineParams.tileOffsetX * 0.5 - timelineParams.gradientAmplitude
|
|
926
|
+
},
|
|
927
|
+
{
|
|
928
|
+
value: 1 + timelineParams.tileOffsetX,
|
|
929
|
+
duration: 0.6 * hideScale,
|
|
930
|
+
ease: "sine.inOut"
|
|
931
|
+
},
|
|
932
|
+
hideAt(0.2)
|
|
933
|
+
);
|
|
934
|
+
hideTl.fromTo(
|
|
935
|
+
uniforms.uTileProgressHorizontal,
|
|
936
|
+
{ value: -timelineParams.tileAmplitude * 0.5 },
|
|
937
|
+
{
|
|
938
|
+
value: 1 + timelineParams.tileAmplitude * 0.5,
|
|
939
|
+
duration: 0.9 * hideScale,
|
|
940
|
+
ease: "sine.inOut"
|
|
941
|
+
},
|
|
942
|
+
hideAt(0.2)
|
|
943
|
+
);
|
|
944
|
+
hideTl.fromTo(
|
|
945
|
+
uniforms.uGradientProgress,
|
|
946
|
+
{
|
|
947
|
+
value: -timelineParams.gradientOffset * 0.5 - timelineParams.gradientAmplitude
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
value: 1 + timelineParams.gradientOffset,
|
|
951
|
+
duration: 0.6 * hideScale,
|
|
952
|
+
ease: "sine.inOut"
|
|
953
|
+
},
|
|
954
|
+
hideAt(0.225)
|
|
955
|
+
);
|
|
956
|
+
hideTl.add(() => {
|
|
957
|
+
animationVisibleRef.current = false;
|
|
958
|
+
updateVisibility();
|
|
959
|
+
onHideDone?.();
|
|
960
|
+
}, hideAt(HIDE_BASE_DURATION));
|
|
961
|
+
showTl.call(
|
|
962
|
+
() => {
|
|
963
|
+
onShowDone?.();
|
|
964
|
+
},
|
|
965
|
+
void 0,
|
|
966
|
+
showAt(0.65)
|
|
967
|
+
);
|
|
968
|
+
showTimeline.current = showTl;
|
|
969
|
+
hideTimeline.current = hideTl;
|
|
970
|
+
}, [onHideDone, onShowDone, timelineParams, updateVisibility]);
|
|
971
|
+
(0, import_react5.useEffect)(() => {
|
|
972
|
+
const uniforms = shaderUniforms.current;
|
|
973
|
+
uniforms.tDiffuse.value = diffuseTexture;
|
|
974
|
+
if (gradientTextureRef.current) {
|
|
975
|
+
uniforms.tGradient.value = gradientTextureRef.current;
|
|
976
|
+
}
|
|
977
|
+
uniforms.uTileAmplitude.value = sanitizedValues.tileAmplitude;
|
|
978
|
+
uniforms.uTileOffset.value.set(
|
|
979
|
+
sanitizedValues.tileOffsetX,
|
|
980
|
+
sanitizedValues.tileOffsetY
|
|
981
|
+
);
|
|
982
|
+
uniforms.uTileFrequency.value.set(
|
|
983
|
+
sanitizedValues.tileFrequencyX,
|
|
984
|
+
sanitizedValues.tileFrequencyY
|
|
985
|
+
);
|
|
986
|
+
uniforms.uWaveAmplitude.value = sanitizedValues.waveAmplitude;
|
|
987
|
+
uniforms.uWaveProgress.value = sanitizedValues.waveProgress;
|
|
988
|
+
uniforms.uWaveStrength.value.set(
|
|
989
|
+
sanitizedValues.waveStrengthX,
|
|
990
|
+
sanitizedValues.waveStrengthY
|
|
991
|
+
);
|
|
992
|
+
uniforms.uGradientProgress.value = sanitizedValues.gradientProgress;
|
|
993
|
+
uniforms.uGradientOffset.value = sanitizedValues.gradientOffset;
|
|
994
|
+
uniforms.uGradientAmplitude.value = sanitizedValues.gradientAmplitude;
|
|
995
|
+
uniforms.uBlueProgress.value = sanitizedValues.blueProgress;
|
|
996
|
+
uniforms.uBlueAmplitude.value = sanitizedValues.blueAmplitude;
|
|
997
|
+
uniforms.uWhiteTileChances.value = sanitizedValues.whiteTileChances;
|
|
998
|
+
uniforms.uWhiteTileFrequency.value = sanitizedValues.whiteTileFrequency;
|
|
999
|
+
uniforms.uWhiteTileStrength.value = sanitizedValues.whiteTileStrength;
|
|
1000
|
+
uniforms.uSaturation.value = sanitizedValues.saturation;
|
|
1001
|
+
uniforms.uTileProgressVertical.value = BASE_TRANSITION_PROGRESS;
|
|
1002
|
+
updateMeshScale();
|
|
1003
|
+
updateVisibility();
|
|
1004
|
+
}, [diffuseTexture, sanitizedValues, updateMeshScale, updateVisibility]);
|
|
1005
|
+
(0, import_react5.useEffect)(() => {
|
|
1006
|
+
buildTimelines();
|
|
1007
|
+
return () => {
|
|
1008
|
+
showTimeline.current?.kill();
|
|
1009
|
+
hideTimeline.current?.kill();
|
|
1010
|
+
transitionTimeline.current?.kill();
|
|
1011
|
+
};
|
|
1012
|
+
}, [buildTimelines]);
|
|
1013
|
+
(0, import_react5.useEffect)(() => {
|
|
1014
|
+
const mesh = assetsRef.current?.mesh;
|
|
1015
|
+
if (mesh) {
|
|
1016
|
+
mesh.visible = sanitizedValues.debug || animationVisibleRef.current;
|
|
1017
|
+
}
|
|
1018
|
+
}, [sanitizedValues.debug]);
|
|
1019
|
+
const lastShowSignal = (0, import_react5.useRef)(settings.showSignal);
|
|
1020
|
+
(0, import_react5.useEffect)(() => {
|
|
1021
|
+
if (settings.showSignal === lastShowSignal.current) {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
lastShowSignal.current = settings.showSignal;
|
|
1025
|
+
hideTimeline.current?.pause(0);
|
|
1026
|
+
primeShowAnimation();
|
|
1027
|
+
showTimeline.current?.seek(0).play();
|
|
1028
|
+
}, [primeShowAnimation, settings.showSignal]);
|
|
1029
|
+
const lastHideSignal = (0, import_react5.useRef)(settings.hideSignal);
|
|
1030
|
+
(0, import_react5.useEffect)(() => {
|
|
1031
|
+
if (settings.hideSignal === lastHideSignal.current) {
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
lastHideSignal.current = settings.hideSignal;
|
|
1035
|
+
showTimeline.current?.pause(0);
|
|
1036
|
+
hideTimeline.current?.seek(0).play();
|
|
1037
|
+
}, [settings.hideSignal]);
|
|
1038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1039
|
+
"div",
|
|
1040
|
+
{
|
|
1041
|
+
ref: containerRef,
|
|
1042
|
+
className,
|
|
1043
|
+
style: {
|
|
1044
|
+
width: width ?? "100%",
|
|
1045
|
+
height: height ?? "100%",
|
|
1046
|
+
...style
|
|
1047
|
+
},
|
|
1048
|
+
...divProps
|
|
1049
|
+
}
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
function createDiffuseTexture() {
|
|
1053
|
+
const size = 256;
|
|
1054
|
+
const data = new Uint8Array(size * size * 4);
|
|
1055
|
+
for (let y = 0; y < size; y += 1) {
|
|
1056
|
+
for (let x = 0; x < size; x += 1) {
|
|
1057
|
+
const i = (y * size + x) * 4;
|
|
1058
|
+
const stripe = Math.sin(y / size * Math.PI * 8) * 0.5 + 0.5;
|
|
1059
|
+
const tint = 0.25 + Math.sin(x / size * Math.PI * 2) * 0.15;
|
|
1060
|
+
const base = THREE5.MathUtils.clamp(stripe * 0.7 + tint, 0, 1);
|
|
1061
|
+
data[i] = base * 255;
|
|
1062
|
+
data[i + 1] = base * 200;
|
|
1063
|
+
data[i + 2] = base * 150;
|
|
1064
|
+
data[i + 3] = 255;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
const texture = new THREE5.DataTexture(data, size, size, THREE5.RGBAFormat);
|
|
1068
|
+
texture.needsUpdate = true;
|
|
1069
|
+
texture.colorSpace = THREE5.SRGBColorSpace;
|
|
1070
|
+
texture.wrapS = THREE5.RepeatWrapping;
|
|
1071
|
+
texture.wrapT = THREE5.RepeatWrapping;
|
|
1072
|
+
texture.magFilter = THREE5.LinearFilter;
|
|
1073
|
+
texture.minFilter = THREE5.LinearMipmapLinearFilter;
|
|
1074
|
+
texture.generateMipmaps = true;
|
|
1075
|
+
return texture;
|
|
1076
|
+
}
|
|
561
1077
|
// Annotate the CommonJS export names for ESM import in node:
|
|
562
1078
|
0 && (module.exports = {
|
|
563
1079
|
FractalFlower,
|
|
1080
|
+
MenuGlitch,
|
|
564
1081
|
OranoParticles,
|
|
565
1082
|
ShaderArt
|
|
566
1083
|
});
|