@toriistudio/shader-ui 0.0.5 → 0.0.6
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 +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +287 -3
- package/dist/index.mjs +286 -3
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -224,4 +224,14 @@ declare const WANDY_HAND_DEFAULTS: {
|
|
|
224
224
|
};
|
|
225
225
|
declare function WandyHand({ text, fontUrl, fontSize, durationMs, strokeWidth, penOpacity, strokeColor, lineCap, lineJoin, samplesPerCurve, strokeMode, canvasPadding, backgroundColor, imperfectionsEnabled, size, animate, onDrawn, }: WandyHandProps): react_jsx_runtime.JSX.Element;
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
type RippleWaveProps = {
|
|
228
|
+
width?: string | number;
|
|
229
|
+
height?: string | number;
|
|
230
|
+
intensity?: number;
|
|
231
|
+
zoom?: number;
|
|
232
|
+
speed?: number;
|
|
233
|
+
hexColors?: string[];
|
|
234
|
+
};
|
|
235
|
+
declare function RippleWave({ width, height, intensity, zoom, speed, hexColors, }: RippleWaveProps): react_jsx_runtime.JSX.Element;
|
|
236
|
+
|
|
237
|
+
export { AnimatedDrawingSVG, EFECTO_ASCII_COMPONENT_DEFAULTS, EFECTO_ASCII_POST_PROCESSING_DEFAULTS, Efecto, type EfectoAsciiColorPalette, type EfectoAsciiStyle, type PublicPostProcessingSettings as EfectoPublicAsciiPostProcessingSettings, FractalFlower, MenuGlitch, type MenuGlitchUniforms, OranoParticles, type OranoParticlesUniforms, RippleWave, ShaderArt, type ShaderArtUniforms, Snow, WANDY_HAND_DEFAULTS, WandyHand };
|
package/dist/index.d.ts
CHANGED
|
@@ -224,4 +224,14 @@ declare const WANDY_HAND_DEFAULTS: {
|
|
|
224
224
|
};
|
|
225
225
|
declare function WandyHand({ text, fontUrl, fontSize, durationMs, strokeWidth, penOpacity, strokeColor, lineCap, lineJoin, samplesPerCurve, strokeMode, canvasPadding, backgroundColor, imperfectionsEnabled, size, animate, onDrawn, }: WandyHandProps): react_jsx_runtime.JSX.Element;
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
type RippleWaveProps = {
|
|
228
|
+
width?: string | number;
|
|
229
|
+
height?: string | number;
|
|
230
|
+
intensity?: number;
|
|
231
|
+
zoom?: number;
|
|
232
|
+
speed?: number;
|
|
233
|
+
hexColors?: string[];
|
|
234
|
+
};
|
|
235
|
+
declare function RippleWave({ width, height, intensity, zoom, speed, hexColors, }: RippleWaveProps): react_jsx_runtime.JSX.Element;
|
|
236
|
+
|
|
237
|
+
export { AnimatedDrawingSVG, EFECTO_ASCII_COMPONENT_DEFAULTS, EFECTO_ASCII_POST_PROCESSING_DEFAULTS, Efecto, type EfectoAsciiColorPalette, type EfectoAsciiStyle, type PublicPostProcessingSettings as EfectoPublicAsciiPostProcessingSettings, FractalFlower, MenuGlitch, type MenuGlitchUniforms, OranoParticles, type OranoParticlesUniforms, RippleWave, ShaderArt, type ShaderArtUniforms, Snow, WANDY_HAND_DEFAULTS, WandyHand };
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ __export(src_exports, {
|
|
|
37
37
|
FractalFlower: () => FractalFlower,
|
|
38
38
|
MenuGlitch: () => MenuGlitch,
|
|
39
39
|
OranoParticles: () => OranoParticles,
|
|
40
|
+
RippleWave: () => RippleWave,
|
|
40
41
|
ShaderArt: () => ShaderArt,
|
|
41
42
|
Snow: () => Snow,
|
|
42
43
|
WANDY_HAND_DEFAULTS: () => WANDY_HAND_DEFAULTS,
|
|
@@ -3138,7 +3139,7 @@ var WANDY_HAND_DEFAULTS = {
|
|
|
3138
3139
|
animate: true
|
|
3139
3140
|
};
|
|
3140
3141
|
function WandyHand({
|
|
3141
|
-
text,
|
|
3142
|
+
text = "",
|
|
3142
3143
|
fontUrl,
|
|
3143
3144
|
fontSize,
|
|
3144
3145
|
durationMs = WANDY_HAND_DEFAULTS.durationMs,
|
|
@@ -3236,7 +3237,8 @@ function WandyHand({
|
|
|
3236
3237
|
}, [resolvedFontUrl]);
|
|
3237
3238
|
const prepared = (0, import_react9.useMemo)(() => {
|
|
3238
3239
|
if (!font) return null;
|
|
3239
|
-
const
|
|
3240
|
+
const safeText = typeof text === "string" ? text : "";
|
|
3241
|
+
const safe = safeText.trim().length ? safeText : " ";
|
|
3240
3242
|
return prepareText(font, safe, resolvedFontSize, resolvedSamplesPerCurve);
|
|
3241
3243
|
}, [font, text, resolvedFontSize, resolvedSamplesPerCurve]);
|
|
3242
3244
|
const aspectRatio = (0, import_react9.useMemo)(() => {
|
|
@@ -3247,7 +3249,8 @@ function WandyHand({
|
|
|
3247
3249
|
}, [prepared]);
|
|
3248
3250
|
const strokePlan = (0, import_react9.useMemo)(() => {
|
|
3249
3251
|
if (!prepared) return null;
|
|
3250
|
-
const
|
|
3252
|
+
const safeText = typeof text === "string" ? text : "";
|
|
3253
|
+
const safe = safeText.trim().length ? safeText : " ";
|
|
3251
3254
|
return createStrokePlan(
|
|
3252
3255
|
prepared.contours,
|
|
3253
3256
|
prepared.totalLen,
|
|
@@ -3469,6 +3472,286 @@ function WandyHand({
|
|
|
3469
3472
|
}
|
|
3470
3473
|
);
|
|
3471
3474
|
}
|
|
3475
|
+
|
|
3476
|
+
// src/components/RippleWave.tsx
|
|
3477
|
+
var import_react11 = require("react");
|
|
3478
|
+
var THREE9 = __toESM(require("three"));
|
|
3479
|
+
|
|
3480
|
+
// src/components/ShaderPass.tsx
|
|
3481
|
+
var import_react10 = require("react");
|
|
3482
|
+
var THREE8 = __toESM(require("three"));
|
|
3483
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
3484
|
+
var buildQuadGeometry = () => {
|
|
3485
|
+
const geom = new THREE8.BufferGeometry();
|
|
3486
|
+
const positions = new Float32Array([
|
|
3487
|
+
-1,
|
|
3488
|
+
-1,
|
|
3489
|
+
0,
|
|
3490
|
+
1,
|
|
3491
|
+
-1,
|
|
3492
|
+
0,
|
|
3493
|
+
1,
|
|
3494
|
+
1,
|
|
3495
|
+
0,
|
|
3496
|
+
-1,
|
|
3497
|
+
-1,
|
|
3498
|
+
0,
|
|
3499
|
+
1,
|
|
3500
|
+
1,
|
|
3501
|
+
0,
|
|
3502
|
+
-1,
|
|
3503
|
+
1,
|
|
3504
|
+
0
|
|
3505
|
+
]);
|
|
3506
|
+
const uvs = new Float32Array([
|
|
3507
|
+
0,
|
|
3508
|
+
0,
|
|
3509
|
+
1,
|
|
3510
|
+
0,
|
|
3511
|
+
1,
|
|
3512
|
+
1,
|
|
3513
|
+
0,
|
|
3514
|
+
0,
|
|
3515
|
+
1,
|
|
3516
|
+
1,
|
|
3517
|
+
0,
|
|
3518
|
+
1
|
|
3519
|
+
]);
|
|
3520
|
+
geom.setAttribute("position", new THREE8.BufferAttribute(positions, 3));
|
|
3521
|
+
geom.setAttribute("uv", new THREE8.BufferAttribute(uvs, 2));
|
|
3522
|
+
return geom;
|
|
3523
|
+
};
|
|
3524
|
+
function ShaderPass({
|
|
3525
|
+
vertexShader,
|
|
3526
|
+
fragmentShader,
|
|
3527
|
+
uniforms,
|
|
3528
|
+
inputUniform = "uTexture",
|
|
3529
|
+
inputTexture = null,
|
|
3530
|
+
target = null,
|
|
3531
|
+
clear = true,
|
|
3532
|
+
clearColor = 0,
|
|
3533
|
+
blending = THREE8.NoBlending,
|
|
3534
|
+
transparent = false,
|
|
3535
|
+
enabled = true,
|
|
3536
|
+
timeUniform,
|
|
3537
|
+
resolutionUniform,
|
|
3538
|
+
hexColors,
|
|
3539
|
+
priority: _priority,
|
|
3540
|
+
className,
|
|
3541
|
+
style,
|
|
3542
|
+
width,
|
|
3543
|
+
height,
|
|
3544
|
+
...divProps
|
|
3545
|
+
}) {
|
|
3546
|
+
const assetsRef = (0, import_react10.useRef)(null);
|
|
3547
|
+
void _priority;
|
|
3548
|
+
const mixedPaletteColor = (0, import_react10.useMemo)(() => {
|
|
3549
|
+
if (!hexColors?.length) return null;
|
|
3550
|
+
const mixed = new THREE8.Color(0, 0, 0);
|
|
3551
|
+
hexColors.forEach((hex) => {
|
|
3552
|
+
const c = new THREE8.Color(hex);
|
|
3553
|
+
mixed.r += c.r;
|
|
3554
|
+
mixed.g += c.g;
|
|
3555
|
+
mixed.b += c.b;
|
|
3556
|
+
});
|
|
3557
|
+
mixed.r /= hexColors.length;
|
|
3558
|
+
mixed.g /= hexColors.length;
|
|
3559
|
+
mixed.b /= hexColors.length;
|
|
3560
|
+
return mixed;
|
|
3561
|
+
}, [hexColors]);
|
|
3562
|
+
(0, import_react10.useEffect)(() => {
|
|
3563
|
+
if (!uniforms.uPaletteColor) {
|
|
3564
|
+
uniforms.uPaletteColor = {
|
|
3565
|
+
value: mixedPaletteColor ?? new THREE8.Color(0, 0, 0)
|
|
3566
|
+
};
|
|
3567
|
+
} else {
|
|
3568
|
+
uniforms.uPaletteColor.value.copy(
|
|
3569
|
+
mixedPaletteColor ?? new THREE8.Color(0, 0, 0)
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
if (!uniforms.uHasPalette) {
|
|
3573
|
+
uniforms.uHasPalette = { value: mixedPaletteColor ? 1 : 0 };
|
|
3574
|
+
} else {
|
|
3575
|
+
uniforms.uHasPalette.value = mixedPaletteColor ? 1 : 0;
|
|
3576
|
+
}
|
|
3577
|
+
if (assetsRef.current) {
|
|
3578
|
+
assetsRef.current.material.uniformsNeedUpdate = true;
|
|
3579
|
+
}
|
|
3580
|
+
}, [mixedPaletteColor, uniforms]);
|
|
3581
|
+
const handleCreate = (0, import_react10.useCallback)(() => {
|
|
3582
|
+
const scene = new THREE8.Scene();
|
|
3583
|
+
const camera = new THREE8.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
3584
|
+
const geometry = buildQuadGeometry();
|
|
3585
|
+
const material = new THREE8.ShaderMaterial({
|
|
3586
|
+
glslVersion: THREE8.GLSL3,
|
|
3587
|
+
vertexShader,
|
|
3588
|
+
fragmentShader,
|
|
3589
|
+
uniforms,
|
|
3590
|
+
blending,
|
|
3591
|
+
transparent,
|
|
3592
|
+
depthTest: false,
|
|
3593
|
+
depthWrite: false
|
|
3594
|
+
});
|
|
3595
|
+
const mesh = new THREE8.Mesh(geometry, material);
|
|
3596
|
+
mesh.frustumCulled = false;
|
|
3597
|
+
scene.add(mesh);
|
|
3598
|
+
assetsRef.current = { scene, camera, mesh, geometry, material };
|
|
3599
|
+
return () => {
|
|
3600
|
+
scene.remove(mesh);
|
|
3601
|
+
geometry.dispose();
|
|
3602
|
+
material.dispose();
|
|
3603
|
+
assetsRef.current = null;
|
|
3604
|
+
};
|
|
3605
|
+
}, [blending, fragmentShader, transparent, uniforms, vertexShader]);
|
|
3606
|
+
const handleRender = (0, import_react10.useCallback)(
|
|
3607
|
+
(context, delta) => {
|
|
3608
|
+
if (!enabled) return;
|
|
3609
|
+
const assets = assetsRef.current;
|
|
3610
|
+
if (!assets) return;
|
|
3611
|
+
if (timeUniform && uniforms[timeUniform]) {
|
|
3612
|
+
uniforms[timeUniform].value = (uniforms[timeUniform].value ?? 0) + delta;
|
|
3613
|
+
}
|
|
3614
|
+
if (resolutionUniform && uniforms[resolutionUniform]) {
|
|
3615
|
+
const v = uniforms[resolutionUniform].value;
|
|
3616
|
+
if (v?.set) v.set(context.size.width, context.size.height);
|
|
3617
|
+
}
|
|
3618
|
+
const prevTarget = context.renderer.getRenderTarget();
|
|
3619
|
+
const prevAutoClear = context.renderer.autoClear;
|
|
3620
|
+
context.renderer.autoClear = false;
|
|
3621
|
+
if (target) context.renderer.setRenderTarget(target);
|
|
3622
|
+
else context.renderer.setRenderTarget(null);
|
|
3623
|
+
if (clear) {
|
|
3624
|
+
const prevClear = context.renderer.getClearColor(new THREE8.Color());
|
|
3625
|
+
const prevAlpha = context.renderer.getClearAlpha();
|
|
3626
|
+
context.renderer.setClearColor(new THREE8.Color(clearColor), 1);
|
|
3627
|
+
context.renderer.clear(true, true, true);
|
|
3628
|
+
context.renderer.setClearColor(prevClear, prevAlpha);
|
|
3629
|
+
}
|
|
3630
|
+
context.renderer.render(assets.scene, assets.camera);
|
|
3631
|
+
context.renderer.setRenderTarget(prevTarget);
|
|
3632
|
+
context.renderer.autoClear = prevAutoClear;
|
|
3633
|
+
},
|
|
3634
|
+
[clear, clearColor, enabled, resolutionUniform, target, timeUniform, uniforms]
|
|
3635
|
+
);
|
|
3636
|
+
const { containerRef } = useScene({
|
|
3637
|
+
onCreate: handleCreate,
|
|
3638
|
+
onRender: handleRender,
|
|
3639
|
+
manualRender: true
|
|
3640
|
+
});
|
|
3641
|
+
(0, import_react10.useEffect)(() => {
|
|
3642
|
+
if (!inputTexture) return;
|
|
3643
|
+
const u = uniforms?.[inputUniform];
|
|
3644
|
+
if (u) u.value = inputTexture;
|
|
3645
|
+
}, [inputTexture, inputUniform, uniforms]);
|
|
3646
|
+
(0, import_react10.useEffect)(() => {
|
|
3647
|
+
const assets = assetsRef.current;
|
|
3648
|
+
if (!assets) return;
|
|
3649
|
+
assets.material.vertexShader = vertexShader;
|
|
3650
|
+
assets.material.fragmentShader = fragmentShader;
|
|
3651
|
+
assets.material.uniforms = uniforms;
|
|
3652
|
+
assets.material.needsUpdate = true;
|
|
3653
|
+
}, [fragmentShader, uniforms, vertexShader]);
|
|
3654
|
+
(0, import_react10.useEffect)(() => {
|
|
3655
|
+
const assets = assetsRef.current;
|
|
3656
|
+
if (!assets) return;
|
|
3657
|
+
assets.material.blending = blending;
|
|
3658
|
+
assets.material.transparent = transparent;
|
|
3659
|
+
assets.material.needsUpdate = true;
|
|
3660
|
+
}, [blending, transparent]);
|
|
3661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
3662
|
+
"div",
|
|
3663
|
+
{
|
|
3664
|
+
ref: containerRef,
|
|
3665
|
+
className,
|
|
3666
|
+
style: {
|
|
3667
|
+
width: width ?? "100%",
|
|
3668
|
+
height: height ?? "100%",
|
|
3669
|
+
...style
|
|
3670
|
+
},
|
|
3671
|
+
...divProps
|
|
3672
|
+
}
|
|
3673
|
+
);
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
// src/shaders/ripple-wave/fragment.glsl
|
|
3677
|
+
var fragment_default8 = "precision highp float;\n\nin vec2 vUv;\nout vec4 FragColor;\n\nuniform float uTime;\nuniform vec2 uResolution;\nuniform float uIntensity;\nuniform float uZoom;\nuniform float uSpeed;\nuniform vec3 uPaletteA;\nuniform vec3 uPaletteB;\nuniform int uHasPalette;\n\nvoid main() {\n vec2 uv = vUv - 0.5;\n uv.x *= uResolution.x / max(uResolution.y, 1.0);\n uv *= uZoom;\n\n float t = uTime * uSpeed;\n float rings = sin(length(uv) * 8.0 - t * 1.5);\n float waves = sin((uv.x + uv.y) * 6.0 + t * 0.9);\n float glow = smoothstep(0.0, 1.0, rings * 0.5 + 0.5);\n\n vec3 base = mix(vec3(0.05, 0.1, 0.2), vec3(0.35, 0.8, 0.9), glow);\n if (uHasPalette == 1) {\n base = mix(uPaletteA, uPaletteB, glow);\n }\n vec3 color = base + waves * 0.12;\n color *= uIntensity;\n\n FragColor = vec4(color, 1.0);\n}\n";
|
|
3678
|
+
|
|
3679
|
+
// src/shaders/ripple-wave/vertex.glsl
|
|
3680
|
+
var vertex_default7 = "out vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position, 1.0);\n}\n";
|
|
3681
|
+
|
|
3682
|
+
// src/components/RippleWave.tsx
|
|
3683
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
3684
|
+
function RippleWave({
|
|
3685
|
+
width,
|
|
3686
|
+
height,
|
|
3687
|
+
intensity = 0.85,
|
|
3688
|
+
zoom = 1.2,
|
|
3689
|
+
speed = 0.9,
|
|
3690
|
+
hexColors
|
|
3691
|
+
}) {
|
|
3692
|
+
const uniforms = (0, import_react11.useMemo)(
|
|
3693
|
+
() => ({
|
|
3694
|
+
uTime: { value: 0 },
|
|
3695
|
+
uResolution: { value: new THREE9.Vector2() },
|
|
3696
|
+
uIntensity: { value: intensity },
|
|
3697
|
+
uZoom: { value: zoom },
|
|
3698
|
+
uSpeed: { value: speed },
|
|
3699
|
+
uPaletteA: { value: new THREE9.Color(0, 0, 0) },
|
|
3700
|
+
uPaletteB: { value: new THREE9.Color(0, 0, 0) },
|
|
3701
|
+
uHasPalette: { value: 0 }
|
|
3702
|
+
}),
|
|
3703
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3704
|
+
[]
|
|
3705
|
+
);
|
|
3706
|
+
uniforms.uIntensity.value = intensity;
|
|
3707
|
+
uniforms.uZoom.value = zoom;
|
|
3708
|
+
uniforms.uSpeed.value = speed;
|
|
3709
|
+
const mixedPalette = (0, import_react11.useMemo)(() => {
|
|
3710
|
+
if (!hexColors?.length) return null;
|
|
3711
|
+
const midpoint = Math.ceil(hexColors.length / 2);
|
|
3712
|
+
const firstHalf = hexColors.slice(0, midpoint);
|
|
3713
|
+
const secondHalf = hexColors.slice(midpoint);
|
|
3714
|
+
const average = (colors) => {
|
|
3715
|
+
if (!colors.length) return new THREE9.Color(0, 0, 0);
|
|
3716
|
+
const mixed = new THREE9.Color(0, 0, 0);
|
|
3717
|
+
colors.forEach((hex) => {
|
|
3718
|
+
const c = new THREE9.Color(hex);
|
|
3719
|
+
mixed.r += c.r;
|
|
3720
|
+
mixed.g += c.g;
|
|
3721
|
+
mixed.b += c.b;
|
|
3722
|
+
});
|
|
3723
|
+
mixed.r /= colors.length;
|
|
3724
|
+
mixed.g /= colors.length;
|
|
3725
|
+
mixed.b /= colors.length;
|
|
3726
|
+
return mixed;
|
|
3727
|
+
};
|
|
3728
|
+
return {
|
|
3729
|
+
a: average(firstHalf),
|
|
3730
|
+
b: average(secondHalf.length ? secondHalf : firstHalf)
|
|
3731
|
+
};
|
|
3732
|
+
}, [hexColors]);
|
|
3733
|
+
if (mixedPalette) {
|
|
3734
|
+
uniforms.uPaletteA.value.copy(mixedPalette.a);
|
|
3735
|
+
uniforms.uPaletteB.value.copy(mixedPalette.b);
|
|
3736
|
+
uniforms.uHasPalette.value = 1;
|
|
3737
|
+
} else {
|
|
3738
|
+
uniforms.uHasPalette.value = 0;
|
|
3739
|
+
}
|
|
3740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
3741
|
+
ShaderPass,
|
|
3742
|
+
{
|
|
3743
|
+
vertexShader: vertex_default7,
|
|
3744
|
+
fragmentShader: fragment_default8,
|
|
3745
|
+
uniforms,
|
|
3746
|
+
clearColor: 396052,
|
|
3747
|
+
timeUniform: "uTime",
|
|
3748
|
+
resolutionUniform: "uResolution",
|
|
3749
|
+
priority: 1,
|
|
3750
|
+
width,
|
|
3751
|
+
height
|
|
3752
|
+
}
|
|
3753
|
+
);
|
|
3754
|
+
}
|
|
3472
3755
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3473
3756
|
0 && (module.exports = {
|
|
3474
3757
|
AnimatedDrawingSVG,
|
|
@@ -3478,6 +3761,7 @@ function WandyHand({
|
|
|
3478
3761
|
FractalFlower,
|
|
3479
3762
|
MenuGlitch,
|
|
3480
3763
|
OranoParticles,
|
|
3764
|
+
RippleWave,
|
|
3481
3765
|
ShaderArt,
|
|
3482
3766
|
Snow,
|
|
3483
3767
|
WANDY_HAND_DEFAULTS,
|
package/dist/index.mjs
CHANGED
|
@@ -3113,7 +3113,7 @@ var WANDY_HAND_DEFAULTS = {
|
|
|
3113
3113
|
animate: true
|
|
3114
3114
|
};
|
|
3115
3115
|
function WandyHand({
|
|
3116
|
-
text,
|
|
3116
|
+
text = "",
|
|
3117
3117
|
fontUrl,
|
|
3118
3118
|
fontSize,
|
|
3119
3119
|
durationMs = WANDY_HAND_DEFAULTS.durationMs,
|
|
@@ -3211,7 +3211,8 @@ function WandyHand({
|
|
|
3211
3211
|
}, [resolvedFontUrl]);
|
|
3212
3212
|
const prepared = useMemo4(() => {
|
|
3213
3213
|
if (!font) return null;
|
|
3214
|
-
const
|
|
3214
|
+
const safeText = typeof text === "string" ? text : "";
|
|
3215
|
+
const safe = safeText.trim().length ? safeText : " ";
|
|
3215
3216
|
return prepareText(font, safe, resolvedFontSize, resolvedSamplesPerCurve);
|
|
3216
3217
|
}, [font, text, resolvedFontSize, resolvedSamplesPerCurve]);
|
|
3217
3218
|
const aspectRatio = useMemo4(() => {
|
|
@@ -3222,7 +3223,8 @@ function WandyHand({
|
|
|
3222
3223
|
}, [prepared]);
|
|
3223
3224
|
const strokePlan = useMemo4(() => {
|
|
3224
3225
|
if (!prepared) return null;
|
|
3225
|
-
const
|
|
3226
|
+
const safeText = typeof text === "string" ? text : "";
|
|
3227
|
+
const safe = safeText.trim().length ? safeText : " ";
|
|
3226
3228
|
return createStrokePlan(
|
|
3227
3229
|
prepared.contours,
|
|
3228
3230
|
prepared.totalLen,
|
|
@@ -3444,6 +3446,286 @@ function WandyHand({
|
|
|
3444
3446
|
}
|
|
3445
3447
|
);
|
|
3446
3448
|
}
|
|
3449
|
+
|
|
3450
|
+
// src/components/RippleWave.tsx
|
|
3451
|
+
import { useMemo as useMemo6 } from "react";
|
|
3452
|
+
import * as THREE9 from "three";
|
|
3453
|
+
|
|
3454
|
+
// src/components/ShaderPass.tsx
|
|
3455
|
+
import { useCallback as useCallback7, useEffect as useEffect10, useMemo as useMemo5, useRef as useRef10 } from "react";
|
|
3456
|
+
import * as THREE8 from "three";
|
|
3457
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
3458
|
+
var buildQuadGeometry = () => {
|
|
3459
|
+
const geom = new THREE8.BufferGeometry();
|
|
3460
|
+
const positions = new Float32Array([
|
|
3461
|
+
-1,
|
|
3462
|
+
-1,
|
|
3463
|
+
0,
|
|
3464
|
+
1,
|
|
3465
|
+
-1,
|
|
3466
|
+
0,
|
|
3467
|
+
1,
|
|
3468
|
+
1,
|
|
3469
|
+
0,
|
|
3470
|
+
-1,
|
|
3471
|
+
-1,
|
|
3472
|
+
0,
|
|
3473
|
+
1,
|
|
3474
|
+
1,
|
|
3475
|
+
0,
|
|
3476
|
+
-1,
|
|
3477
|
+
1,
|
|
3478
|
+
0
|
|
3479
|
+
]);
|
|
3480
|
+
const uvs = new Float32Array([
|
|
3481
|
+
0,
|
|
3482
|
+
0,
|
|
3483
|
+
1,
|
|
3484
|
+
0,
|
|
3485
|
+
1,
|
|
3486
|
+
1,
|
|
3487
|
+
0,
|
|
3488
|
+
0,
|
|
3489
|
+
1,
|
|
3490
|
+
1,
|
|
3491
|
+
0,
|
|
3492
|
+
1
|
|
3493
|
+
]);
|
|
3494
|
+
geom.setAttribute("position", new THREE8.BufferAttribute(positions, 3));
|
|
3495
|
+
geom.setAttribute("uv", new THREE8.BufferAttribute(uvs, 2));
|
|
3496
|
+
return geom;
|
|
3497
|
+
};
|
|
3498
|
+
function ShaderPass({
|
|
3499
|
+
vertexShader,
|
|
3500
|
+
fragmentShader,
|
|
3501
|
+
uniforms,
|
|
3502
|
+
inputUniform = "uTexture",
|
|
3503
|
+
inputTexture = null,
|
|
3504
|
+
target = null,
|
|
3505
|
+
clear = true,
|
|
3506
|
+
clearColor = 0,
|
|
3507
|
+
blending = THREE8.NoBlending,
|
|
3508
|
+
transparent = false,
|
|
3509
|
+
enabled = true,
|
|
3510
|
+
timeUniform,
|
|
3511
|
+
resolutionUniform,
|
|
3512
|
+
hexColors,
|
|
3513
|
+
priority: _priority,
|
|
3514
|
+
className,
|
|
3515
|
+
style,
|
|
3516
|
+
width,
|
|
3517
|
+
height,
|
|
3518
|
+
...divProps
|
|
3519
|
+
}) {
|
|
3520
|
+
const assetsRef = useRef10(null);
|
|
3521
|
+
void _priority;
|
|
3522
|
+
const mixedPaletteColor = useMemo5(() => {
|
|
3523
|
+
if (!hexColors?.length) return null;
|
|
3524
|
+
const mixed = new THREE8.Color(0, 0, 0);
|
|
3525
|
+
hexColors.forEach((hex) => {
|
|
3526
|
+
const c = new THREE8.Color(hex);
|
|
3527
|
+
mixed.r += c.r;
|
|
3528
|
+
mixed.g += c.g;
|
|
3529
|
+
mixed.b += c.b;
|
|
3530
|
+
});
|
|
3531
|
+
mixed.r /= hexColors.length;
|
|
3532
|
+
mixed.g /= hexColors.length;
|
|
3533
|
+
mixed.b /= hexColors.length;
|
|
3534
|
+
return mixed;
|
|
3535
|
+
}, [hexColors]);
|
|
3536
|
+
useEffect10(() => {
|
|
3537
|
+
if (!uniforms.uPaletteColor) {
|
|
3538
|
+
uniforms.uPaletteColor = {
|
|
3539
|
+
value: mixedPaletteColor ?? new THREE8.Color(0, 0, 0)
|
|
3540
|
+
};
|
|
3541
|
+
} else {
|
|
3542
|
+
uniforms.uPaletteColor.value.copy(
|
|
3543
|
+
mixedPaletteColor ?? new THREE8.Color(0, 0, 0)
|
|
3544
|
+
);
|
|
3545
|
+
}
|
|
3546
|
+
if (!uniforms.uHasPalette) {
|
|
3547
|
+
uniforms.uHasPalette = { value: mixedPaletteColor ? 1 : 0 };
|
|
3548
|
+
} else {
|
|
3549
|
+
uniforms.uHasPalette.value = mixedPaletteColor ? 1 : 0;
|
|
3550
|
+
}
|
|
3551
|
+
if (assetsRef.current) {
|
|
3552
|
+
assetsRef.current.material.uniformsNeedUpdate = true;
|
|
3553
|
+
}
|
|
3554
|
+
}, [mixedPaletteColor, uniforms]);
|
|
3555
|
+
const handleCreate = useCallback7(() => {
|
|
3556
|
+
const scene = new THREE8.Scene();
|
|
3557
|
+
const camera = new THREE8.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
3558
|
+
const geometry = buildQuadGeometry();
|
|
3559
|
+
const material = new THREE8.ShaderMaterial({
|
|
3560
|
+
glslVersion: THREE8.GLSL3,
|
|
3561
|
+
vertexShader,
|
|
3562
|
+
fragmentShader,
|
|
3563
|
+
uniforms,
|
|
3564
|
+
blending,
|
|
3565
|
+
transparent,
|
|
3566
|
+
depthTest: false,
|
|
3567
|
+
depthWrite: false
|
|
3568
|
+
});
|
|
3569
|
+
const mesh = new THREE8.Mesh(geometry, material);
|
|
3570
|
+
mesh.frustumCulled = false;
|
|
3571
|
+
scene.add(mesh);
|
|
3572
|
+
assetsRef.current = { scene, camera, mesh, geometry, material };
|
|
3573
|
+
return () => {
|
|
3574
|
+
scene.remove(mesh);
|
|
3575
|
+
geometry.dispose();
|
|
3576
|
+
material.dispose();
|
|
3577
|
+
assetsRef.current = null;
|
|
3578
|
+
};
|
|
3579
|
+
}, [blending, fragmentShader, transparent, uniforms, vertexShader]);
|
|
3580
|
+
const handleRender = useCallback7(
|
|
3581
|
+
(context, delta) => {
|
|
3582
|
+
if (!enabled) return;
|
|
3583
|
+
const assets = assetsRef.current;
|
|
3584
|
+
if (!assets) return;
|
|
3585
|
+
if (timeUniform && uniforms[timeUniform]) {
|
|
3586
|
+
uniforms[timeUniform].value = (uniforms[timeUniform].value ?? 0) + delta;
|
|
3587
|
+
}
|
|
3588
|
+
if (resolutionUniform && uniforms[resolutionUniform]) {
|
|
3589
|
+
const v = uniforms[resolutionUniform].value;
|
|
3590
|
+
if (v?.set) v.set(context.size.width, context.size.height);
|
|
3591
|
+
}
|
|
3592
|
+
const prevTarget = context.renderer.getRenderTarget();
|
|
3593
|
+
const prevAutoClear = context.renderer.autoClear;
|
|
3594
|
+
context.renderer.autoClear = false;
|
|
3595
|
+
if (target) context.renderer.setRenderTarget(target);
|
|
3596
|
+
else context.renderer.setRenderTarget(null);
|
|
3597
|
+
if (clear) {
|
|
3598
|
+
const prevClear = context.renderer.getClearColor(new THREE8.Color());
|
|
3599
|
+
const prevAlpha = context.renderer.getClearAlpha();
|
|
3600
|
+
context.renderer.setClearColor(new THREE8.Color(clearColor), 1);
|
|
3601
|
+
context.renderer.clear(true, true, true);
|
|
3602
|
+
context.renderer.setClearColor(prevClear, prevAlpha);
|
|
3603
|
+
}
|
|
3604
|
+
context.renderer.render(assets.scene, assets.camera);
|
|
3605
|
+
context.renderer.setRenderTarget(prevTarget);
|
|
3606
|
+
context.renderer.autoClear = prevAutoClear;
|
|
3607
|
+
},
|
|
3608
|
+
[clear, clearColor, enabled, resolutionUniform, target, timeUniform, uniforms]
|
|
3609
|
+
);
|
|
3610
|
+
const { containerRef } = useScene({
|
|
3611
|
+
onCreate: handleCreate,
|
|
3612
|
+
onRender: handleRender,
|
|
3613
|
+
manualRender: true
|
|
3614
|
+
});
|
|
3615
|
+
useEffect10(() => {
|
|
3616
|
+
if (!inputTexture) return;
|
|
3617
|
+
const u = uniforms?.[inputUniform];
|
|
3618
|
+
if (u) u.value = inputTexture;
|
|
3619
|
+
}, [inputTexture, inputUniform, uniforms]);
|
|
3620
|
+
useEffect10(() => {
|
|
3621
|
+
const assets = assetsRef.current;
|
|
3622
|
+
if (!assets) return;
|
|
3623
|
+
assets.material.vertexShader = vertexShader;
|
|
3624
|
+
assets.material.fragmentShader = fragmentShader;
|
|
3625
|
+
assets.material.uniforms = uniforms;
|
|
3626
|
+
assets.material.needsUpdate = true;
|
|
3627
|
+
}, [fragmentShader, uniforms, vertexShader]);
|
|
3628
|
+
useEffect10(() => {
|
|
3629
|
+
const assets = assetsRef.current;
|
|
3630
|
+
if (!assets) return;
|
|
3631
|
+
assets.material.blending = blending;
|
|
3632
|
+
assets.material.transparent = transparent;
|
|
3633
|
+
assets.material.needsUpdate = true;
|
|
3634
|
+
}, [blending, transparent]);
|
|
3635
|
+
return /* @__PURE__ */ jsx11(
|
|
3636
|
+
"div",
|
|
3637
|
+
{
|
|
3638
|
+
ref: containerRef,
|
|
3639
|
+
className,
|
|
3640
|
+
style: {
|
|
3641
|
+
width: width ?? "100%",
|
|
3642
|
+
height: height ?? "100%",
|
|
3643
|
+
...style
|
|
3644
|
+
},
|
|
3645
|
+
...divProps
|
|
3646
|
+
}
|
|
3647
|
+
);
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3650
|
+
// src/shaders/ripple-wave/fragment.glsl
|
|
3651
|
+
var fragment_default8 = "precision highp float;\n\nin vec2 vUv;\nout vec4 FragColor;\n\nuniform float uTime;\nuniform vec2 uResolution;\nuniform float uIntensity;\nuniform float uZoom;\nuniform float uSpeed;\nuniform vec3 uPaletteA;\nuniform vec3 uPaletteB;\nuniform int uHasPalette;\n\nvoid main() {\n vec2 uv = vUv - 0.5;\n uv.x *= uResolution.x / max(uResolution.y, 1.0);\n uv *= uZoom;\n\n float t = uTime * uSpeed;\n float rings = sin(length(uv) * 8.0 - t * 1.5);\n float waves = sin((uv.x + uv.y) * 6.0 + t * 0.9);\n float glow = smoothstep(0.0, 1.0, rings * 0.5 + 0.5);\n\n vec3 base = mix(vec3(0.05, 0.1, 0.2), vec3(0.35, 0.8, 0.9), glow);\n if (uHasPalette == 1) {\n base = mix(uPaletteA, uPaletteB, glow);\n }\n vec3 color = base + waves * 0.12;\n color *= uIntensity;\n\n FragColor = vec4(color, 1.0);\n}\n";
|
|
3652
|
+
|
|
3653
|
+
// src/shaders/ripple-wave/vertex.glsl
|
|
3654
|
+
var vertex_default7 = "out vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position, 1.0);\n}\n";
|
|
3655
|
+
|
|
3656
|
+
// src/components/RippleWave.tsx
|
|
3657
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
3658
|
+
function RippleWave({
|
|
3659
|
+
width,
|
|
3660
|
+
height,
|
|
3661
|
+
intensity = 0.85,
|
|
3662
|
+
zoom = 1.2,
|
|
3663
|
+
speed = 0.9,
|
|
3664
|
+
hexColors
|
|
3665
|
+
}) {
|
|
3666
|
+
const uniforms = useMemo6(
|
|
3667
|
+
() => ({
|
|
3668
|
+
uTime: { value: 0 },
|
|
3669
|
+
uResolution: { value: new THREE9.Vector2() },
|
|
3670
|
+
uIntensity: { value: intensity },
|
|
3671
|
+
uZoom: { value: zoom },
|
|
3672
|
+
uSpeed: { value: speed },
|
|
3673
|
+
uPaletteA: { value: new THREE9.Color(0, 0, 0) },
|
|
3674
|
+
uPaletteB: { value: new THREE9.Color(0, 0, 0) },
|
|
3675
|
+
uHasPalette: { value: 0 }
|
|
3676
|
+
}),
|
|
3677
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3678
|
+
[]
|
|
3679
|
+
);
|
|
3680
|
+
uniforms.uIntensity.value = intensity;
|
|
3681
|
+
uniforms.uZoom.value = zoom;
|
|
3682
|
+
uniforms.uSpeed.value = speed;
|
|
3683
|
+
const mixedPalette = useMemo6(() => {
|
|
3684
|
+
if (!hexColors?.length) return null;
|
|
3685
|
+
const midpoint = Math.ceil(hexColors.length / 2);
|
|
3686
|
+
const firstHalf = hexColors.slice(0, midpoint);
|
|
3687
|
+
const secondHalf = hexColors.slice(midpoint);
|
|
3688
|
+
const average = (colors) => {
|
|
3689
|
+
if (!colors.length) return new THREE9.Color(0, 0, 0);
|
|
3690
|
+
const mixed = new THREE9.Color(0, 0, 0);
|
|
3691
|
+
colors.forEach((hex) => {
|
|
3692
|
+
const c = new THREE9.Color(hex);
|
|
3693
|
+
mixed.r += c.r;
|
|
3694
|
+
mixed.g += c.g;
|
|
3695
|
+
mixed.b += c.b;
|
|
3696
|
+
});
|
|
3697
|
+
mixed.r /= colors.length;
|
|
3698
|
+
mixed.g /= colors.length;
|
|
3699
|
+
mixed.b /= colors.length;
|
|
3700
|
+
return mixed;
|
|
3701
|
+
};
|
|
3702
|
+
return {
|
|
3703
|
+
a: average(firstHalf),
|
|
3704
|
+
b: average(secondHalf.length ? secondHalf : firstHalf)
|
|
3705
|
+
};
|
|
3706
|
+
}, [hexColors]);
|
|
3707
|
+
if (mixedPalette) {
|
|
3708
|
+
uniforms.uPaletteA.value.copy(mixedPalette.a);
|
|
3709
|
+
uniforms.uPaletteB.value.copy(mixedPalette.b);
|
|
3710
|
+
uniforms.uHasPalette.value = 1;
|
|
3711
|
+
} else {
|
|
3712
|
+
uniforms.uHasPalette.value = 0;
|
|
3713
|
+
}
|
|
3714
|
+
return /* @__PURE__ */ jsx12(
|
|
3715
|
+
ShaderPass,
|
|
3716
|
+
{
|
|
3717
|
+
vertexShader: vertex_default7,
|
|
3718
|
+
fragmentShader: fragment_default8,
|
|
3719
|
+
uniforms,
|
|
3720
|
+
clearColor: 396052,
|
|
3721
|
+
timeUniform: "uTime",
|
|
3722
|
+
resolutionUniform: "uResolution",
|
|
3723
|
+
priority: 1,
|
|
3724
|
+
width,
|
|
3725
|
+
height
|
|
3726
|
+
}
|
|
3727
|
+
);
|
|
3728
|
+
}
|
|
3447
3729
|
export {
|
|
3448
3730
|
AnimatedDrawingSVG,
|
|
3449
3731
|
EFECTO_ASCII_COMPONENT_DEFAULTS,
|
|
@@ -3452,6 +3734,7 @@ export {
|
|
|
3452
3734
|
FractalFlower,
|
|
3453
3735
|
MenuGlitch,
|
|
3454
3736
|
OranoParticles,
|
|
3737
|
+
RippleWave,
|
|
3455
3738
|
ShaderArt,
|
|
3456
3739
|
Snow,
|
|
3457
3740
|
WANDY_HAND_DEFAULTS,
|