@3driseai/3drise-viewer 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/components/ChladniGrid.d.ts +15 -0
- package/dist/components/ChladniGrid.d.ts.map +1 -0
- package/dist/components/ChladniGrid.js +62 -0
- package/dist/components/CustomPrimitive.d.ts +2 -0
- package/dist/components/CustomPrimitive.d.ts.map +1 -1
- package/dist/components/CustomPrimitive.js +2 -2
- package/dist/components/EffectsGenerator.d.ts.map +1 -1
- package/dist/components/EffectsGenerator.js +26 -2
- package/dist/components/FlowNetGrid.d.ts +15 -0
- package/dist/components/FlowNetGrid.d.ts.map +1 -0
- package/dist/components/FlowNetGrid.js +61 -0
- package/dist/components/Galaxy.d.ts.map +1 -1
- package/dist/components/Galaxy.js +2 -0
- package/dist/components/GirihGrid.d.ts +15 -0
- package/dist/components/GirihGrid.d.ts.map +1 -0
- package/dist/components/GirihGrid.js +62 -0
- package/dist/components/GravWaveGrid.d.ts +15 -0
- package/dist/components/GravWaveGrid.d.ts.map +1 -0
- package/dist/components/GravWaveGrid.js +62 -0
- package/dist/components/GridsGenerator.d.ts +2 -2
- package/dist/components/GridsGenerator.d.ts.map +1 -1
- package/dist/components/GridsGenerator.js +21 -0
- package/dist/components/HyperbolicGrid.d.ts +15 -0
- package/dist/components/HyperbolicGrid.d.ts.map +1 -0
- package/dist/components/HyperbolicGrid.js +61 -0
- package/dist/components/LayoutInstances.d.ts +13 -0
- package/dist/components/LayoutInstances.d.ts.map +1 -0
- package/dist/components/LayoutInstances.js +39 -0
- package/dist/components/ModelPrimitive.d.ts +2 -0
- package/dist/components/ModelPrimitive.d.ts.map +1 -1
- package/dist/components/ModelPrimitive.js +3 -3
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +44 -9
- package/dist/components/ParticlesGenerator.d.ts +10 -0
- package/dist/components/ParticlesGenerator.d.ts.map +1 -0
- package/dist/components/ParticlesGenerator.js +23 -0
- package/dist/components/ReactionDiffusionGrid.d.ts +15 -0
- package/dist/components/ReactionDiffusionGrid.d.ts.map +1 -0
- package/dist/components/ReactionDiffusionGrid.js +376 -0
- package/dist/components/WallpaperGrid.d.ts +15 -0
- package/dist/components/WallpaperGrid.d.ts.map +1 -0
- package/dist/components/WallpaperGrid.js +555 -0
- package/dist/components/cursor/CursorController.d.ts.map +1 -1
- package/dist/components/effects/BlackHoleEffect.d.ts +3 -3
- package/dist/components/effects/BlackHoleEffect.d.ts.map +1 -1
- package/dist/components/effects/BlackHoleEffect.js +293 -163
- package/dist/components/effects/DandelionSeedsEffect.d.ts +13 -0
- package/dist/components/effects/DandelionSeedsEffect.d.ts.map +1 -0
- package/dist/components/effects/DandelionSeedsEffect.js +510 -0
- package/dist/components/effects/FallingLeavesEffect.d.ts +13 -0
- package/dist/components/effects/FallingLeavesEffect.d.ts.map +1 -0
- package/dist/components/effects/FallingLeavesEffect.js +446 -0
- package/dist/components/effects/FieldLinesEffect.d.ts +11 -0
- package/dist/components/effects/FieldLinesEffect.d.ts.map +1 -0
- package/dist/components/effects/FieldLinesEffect.js +260 -0
- package/dist/components/effects/FireflySwarmEffect.d.ts +13 -0
- package/dist/components/effects/FireflySwarmEffect.d.ts.map +1 -0
- package/dist/components/effects/FireflySwarmEffect.js +408 -0
- package/dist/components/effects/GalaxyEffect.d.ts +13 -0
- package/dist/components/effects/GalaxyEffect.d.ts.map +1 -0
- package/dist/components/effects/GalaxyEffect.js +374 -0
- package/dist/components/effects/HarmonicShellEffect.d.ts +11 -0
- package/dist/components/effects/HarmonicShellEffect.d.ts.map +1 -0
- package/dist/components/effects/HarmonicShellEffect.js +209 -0
- package/dist/components/effects/IceCrystalsEffect.d.ts +3 -3
- package/dist/components/effects/IceCrystalsEffect.d.ts.map +1 -1
- package/dist/components/effects/IceCrystalsEffect.js +286 -166
- package/dist/components/effects/IceHaloEffect.d.ts +13 -0
- package/dist/components/effects/IceHaloEffect.d.ts.map +1 -0
- package/dist/components/effects/IceHaloEffect.js +306 -0
- package/dist/components/effects/LichtenbergEffect.d.ts +13 -0
- package/dist/components/effects/LichtenbergEffect.d.ts.map +1 -0
- package/dist/components/effects/LichtenbergEffect.js +517 -0
- package/dist/components/effects/MoleculesEffect.d.ts +3 -3
- package/dist/components/effects/MoleculesEffect.d.ts.map +1 -1
- package/dist/components/effects/MoleculesEffect.js +322 -164
- package/dist/components/effects/MurmurationEffect.d.ts +13 -0
- package/dist/components/effects/MurmurationEffect.d.ts.map +1 -0
- package/dist/components/effects/MurmurationEffect.js +539 -0
- package/dist/components/effects/PlanetaryRingsEffect.d.ts +13 -0
- package/dist/components/effects/PlanetaryRingsEffect.d.ts.map +1 -0
- package/dist/components/effects/PlanetaryRingsEffect.js +458 -0
- package/dist/components/effects/PortalEffect.d.ts +3 -3
- package/dist/components/effects/PortalEffect.d.ts.map +1 -1
- package/dist/components/effects/PortalEffect.js +240 -163
- package/dist/components/effects/ShockwaveEffect.d.ts +5 -3
- package/dist/components/effects/ShockwaveEffect.d.ts.map +1 -1
- package/dist/components/effects/ShockwaveEffect.js +538 -142
- package/dist/components/effects/SmokePlumeEffect.d.ts +3 -3
- package/dist/components/effects/SmokePlumeEffect.d.ts.map +1 -1
- package/dist/components/effects/SmokePlumeEffect.js +180 -116
- package/dist/components/effects/SmokeRingEffect.d.ts +3 -3
- package/dist/components/effects/SmokeRingEffect.d.ts.map +1 -1
- package/dist/components/effects/SmokeRingEffect.js +260 -135
- package/dist/components/effects/StrangeAttractorEffect.d.ts +11 -0
- package/dist/components/effects/StrangeAttractorEffect.d.ts.map +1 -0
- package/dist/components/effects/StrangeAttractorEffect.js +229 -0
- package/dist/components/effects/VolumetricFogEffect.d.ts +5 -3
- package/dist/components/effects/VolumetricFogEffect.d.ts.map +1 -1
- package/dist/components/effects/VolumetricFogEffect.js +211 -93
- package/dist/components/effects/WaterCausticsEffect.d.ts +13 -0
- package/dist/components/effects/WaterCausticsEffect.d.ts.map +1 -0
- package/dist/components/effects/WaterCausticsEffect.js +308 -0
- package/dist/components/effects/index.d.ts +9 -0
- package/dist/components/effects/index.d.ts.map +1 -1
- package/dist/components/effects/index.js +9 -0
- package/dist/components/index.d.ts +19 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +10 -0
- package/dist/components/particles/BioluminescentWakeParticles.d.ts +12 -0
- package/dist/components/particles/BioluminescentWakeParticles.d.ts.map +1 -0
- package/dist/components/particles/BioluminescentWakeParticles.js +1123 -0
- package/dist/components/particles/BrownianDustParticles.d.ts +12 -0
- package/dist/components/particles/BrownianDustParticles.d.ts.map +1 -0
- package/dist/components/particles/BrownianDustParticles.js +757 -0
- package/dist/components/particles/ElectronOrbitalsParticles.d.ts +12 -0
- package/dist/components/particles/ElectronOrbitalsParticles.d.ts.map +1 -0
- package/dist/components/particles/ElectronOrbitalsParticles.js +944 -0
- package/dist/components/particles/GrinderSparksParticles.d.ts +12 -0
- package/dist/components/particles/GrinderSparksParticles.d.ts.map +1 -0
- package/dist/components/particles/GrinderSparksParticles.js +744 -0
- package/dist/components/particles/TidalStreamParticles.d.ts +12 -0
- package/dist/components/particles/TidalStreamParticles.d.ts.map +1 -0
- package/dist/components/particles/TidalStreamParticles.js +788 -0
- package/dist/components/particles/index.d.ts +11 -0
- package/dist/components/particles/index.d.ts.map +1 -0
- package/dist/components/particles/index.js +6 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/hooks/useModelObject.d.ts +6 -1
- package/dist/hooks/useModelObject.d.ts.map +1 -1
- package/dist/hooks/useModelObject.js +19 -6
- package/dist/types/gridConfigs.d.ts +98 -0
- package/dist/types/gridConfigs.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/particleTrails.d.ts +70 -0
- package/dist/utils/particleTrails.d.ts.map +1 -0
- package/dist/utils/particleTrails.js +369 -0
- package/dist/utils/pointerField.d.ts +28 -0
- package/dist/utils/pointerField.d.ts.map +1 -0
- package/dist/utils/pointerField.js +103 -0
- package/package.json +2 -2
|
@@ -1,194 +1,271 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import { useFrame } from '@react-three/fiber';
|
|
2
|
+
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
4
3
|
import * as THREE from 'three';
|
|
4
|
+
import { useFrame } from '@react-three/fiber';
|
|
5
5
|
import { applyGenerativeAnimations } from '../../utils/handleGenerativeEffectsAnimations.js';
|
|
6
6
|
import { useObjectReady } from '../../hooks/useObjectReady.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
/**
|
|
8
|
+
* A wormhole portal lying under the host.
|
|
9
|
+
*
|
|
10
|
+
* The disc is bent into Flamm's paraboloid (depth ~ sqrt(r - r_t)) so it
|
|
11
|
+
* funnels down to a throat. Through the throat you see another universe,
|
|
12
|
+
* lensed into an Einstein ring at its edge. The funnel swirls with Keplerian
|
|
13
|
+
* shear (omega ~ r^-1.5), using a two-phase flow map so the spiral never winds
|
|
14
|
+
* up, and matter falls in along log spirals, heating and blueshifting.
|
|
15
|
+
*/
|
|
16
|
+
const PRE_NORMAL = { transparent: true, depthWrite: false, blending: THREE.NormalBlending, premultipliedAlpha: true };
|
|
17
|
+
const PRE_ADD = { transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, premultipliedAlpha: true };
|
|
18
|
+
function mulberry32(seed) {
|
|
19
|
+
return () => {
|
|
20
|
+
seed |= 0;
|
|
21
|
+
seed = (seed + 0x6d2b79f5) | 0;
|
|
22
|
+
let r = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
|
23
|
+
r = (r + Math.imul(r ^ (r >>> 7), 61 | r)) ^ r;
|
|
24
|
+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function seedTriples(count, seed) {
|
|
28
|
+
const rand = mulberry32(seed);
|
|
29
|
+
const out = new Float32Array(count * 3);
|
|
30
|
+
for (let i = 0; i < out.length; i++)
|
|
31
|
+
out[i] = rand();
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function buildInfall(count) {
|
|
35
|
+
const n = Math.round(Math.min(Math.max(count, 0), 400));
|
|
36
|
+
return { count: n, aSeed: seedTriples(n, 31) };
|
|
37
|
+
}
|
|
38
|
+
const portalVert = /* glsl */ `
|
|
39
|
+
uniform float uThroatSize;
|
|
40
|
+
uniform float uFunnelDepth;
|
|
41
|
+
uniform float uRadius;
|
|
42
|
+
uniform float uBound;
|
|
43
|
+
varying vec2 vP;
|
|
44
|
+
void main(){
|
|
45
|
+
// Normalised disc coordinates; the geometry is a unit disc scaled by uRadius.
|
|
46
|
+
vP = position.xy;
|
|
47
|
+
float r = length(position.xy);
|
|
48
|
+
// Flamm's paraboloid, the embedding of a Schwarzschild throat:
|
|
49
|
+
// depth falls as sqrt(r - r_throat), flat inside the throat.
|
|
50
|
+
float rt = uThroatSize;
|
|
51
|
+
float s = clamp((r - rt) / max(1.0 - rt, 1e-3), 0.0, 1.0);
|
|
52
|
+
float depth = uFunnelDepth * (1.0 - sqrt(s));
|
|
53
|
+
float Rw = uRadius * uBound;
|
|
54
|
+
vec3 pos = vec3(position.xy * Rw, -depth * Rw);
|
|
55
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
|
13
56
|
}
|
|
14
57
|
`;
|
|
15
|
-
const
|
|
16
|
-
uniform float
|
|
17
|
-
uniform float uSpiralTurns;
|
|
58
|
+
const portalFrag = /* glsl */ `
|
|
59
|
+
uniform float uTime;
|
|
18
60
|
uniform float uRotationSpeed;
|
|
19
|
-
uniform
|
|
20
|
-
uniform
|
|
61
|
+
uniform float uSpiralTurns;
|
|
62
|
+
uniform float uThroatSize;
|
|
63
|
+
uniform vec3 uInnerGlowColor;
|
|
64
|
+
uniform vec3 uOuterGlowColor;
|
|
65
|
+
uniform vec3 uOtherSideColor;
|
|
21
66
|
uniform float uOpacity;
|
|
22
67
|
uniform float uIntensity;
|
|
68
|
+
varying vec2 vP;
|
|
23
69
|
|
|
24
|
-
|
|
70
|
+
|
|
71
|
+
float hash13(vec3 p3){
|
|
72
|
+
p3 = fract(p3 * 0.1031);
|
|
73
|
+
p3 += dot(p3, p3.zyx + 31.32);
|
|
74
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
75
|
+
}
|
|
76
|
+
float vnoise(vec3 p){
|
|
77
|
+
vec3 i = floor(p);
|
|
78
|
+
vec3 f = fract(p);
|
|
79
|
+
f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
|
80
|
+
float n000 = hash13(i);
|
|
81
|
+
float n100 = hash13(i + vec3(1.0, 0.0, 0.0));
|
|
82
|
+
float n010 = hash13(i + vec3(0.0, 1.0, 0.0));
|
|
83
|
+
float n110 = hash13(i + vec3(1.0, 1.0, 0.0));
|
|
84
|
+
float n001 = hash13(i + vec3(0.0, 0.0, 1.0));
|
|
85
|
+
float n101 = hash13(i + vec3(1.0, 0.0, 1.0));
|
|
86
|
+
float n011 = hash13(i + vec3(0.0, 1.0, 1.0));
|
|
87
|
+
float n111 = hash13(i + vec3(1.0, 1.0, 1.0));
|
|
88
|
+
return mix(mix(mix(n000, n100, f.x), mix(n010, n110, f.x), f.y),
|
|
89
|
+
mix(mix(n001, n101, f.x), mix(n011, n111, f.x), f.y), f.z);
|
|
90
|
+
}
|
|
91
|
+
// low-frequency fBm; the rotation between octaves hides the lattice
|
|
92
|
+
const mat3 FBM_ROT = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
|
93
|
+
float fbm3(vec3 p, int octaves){
|
|
94
|
+
float a = 0.5, s = 0.0;
|
|
95
|
+
for (int i = 0; i < 5; i++){
|
|
96
|
+
if (i >= octaves) break;
|
|
97
|
+
s += a * vnoise(p);
|
|
98
|
+
p = FBM_ROT * p * 2.02;
|
|
99
|
+
a *= 0.5;
|
|
100
|
+
}
|
|
101
|
+
return s;
|
|
102
|
+
}
|
|
25
103
|
|
|
26
|
-
float hash(vec2 p){ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }
|
|
27
104
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
float
|
|
31
|
-
|
|
105
|
+
vec3 otherSide(vec3 dir, float t){
|
|
106
|
+
// the far universe: a slow nebula and a static star field
|
|
107
|
+
float c = cos(t * 0.02), s = sin(t * 0.02);
|
|
108
|
+
dir.xz = mat2(c, -s, s, c) * dir.xz;
|
|
109
|
+
vec3 w = vec3(fbm3(dir * 1.8, 3), fbm3(dir * 1.8 + 7.1, 3), 0.0);
|
|
110
|
+
float neb = fbm3(dir * 2.6 + w * 1.5, 4);
|
|
111
|
+
vec3 col = uOtherSideColor * smoothstep(0.35, 0.8, neb) * 1.2
|
|
112
|
+
+ uInnerGlowColor * smoothstep(0.55, 0.9, fbm3(dir * 4.0 + 3.0, 3)) * 0.35;
|
|
113
|
+
vec3 sp = dir * 42.0;
|
|
114
|
+
vec3 id = floor(sp);
|
|
115
|
+
vec3 f = fract(sp) - 0.5;
|
|
116
|
+
float hs = hash13(id);
|
|
117
|
+
vec3 o = (vec3(hash13(id + 1.7), hash13(id + 3.1), hash13(id + 5.3)) - 0.5) * 0.5;
|
|
118
|
+
float star = step(0.94, hs) * smoothstep(0.1, 0.0, length(f - o)) * (hs - 0.94) * 16.0;
|
|
119
|
+
return col + vec3(star);
|
|
120
|
+
}
|
|
32
121
|
|
|
33
|
-
|
|
122
|
+
void main(){
|
|
34
123
|
const float TAU = 6.28318530718;
|
|
35
|
-
float
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
float
|
|
39
|
-
float
|
|
40
|
-
float
|
|
41
|
-
|
|
42
|
-
float w3 = pow(1.0 - dist, 2.0);
|
|
43
|
-
float vortex = s1 * 0.45 + s2 * 0.30 * (1.0 - w3) + s3 * 0.60 * w3;
|
|
44
|
-
|
|
45
|
-
// Gravitational lensing rim
|
|
46
|
-
float rimRing = exp(-pow((dist - 0.92) / 0.04, 2.0)) * 3.0;
|
|
47
|
-
float rim = pow(smoothstep(0.85, 1.0, dist), 0.7) * 1.5;
|
|
124
|
+
float r = length(vP);
|
|
125
|
+
if (r > 1.0) discard;
|
|
126
|
+
float theta = atan(vP.y, vP.x);
|
|
127
|
+
float rt = uThroatSize;
|
|
128
|
+
float t = uTime * uRotationSpeed;
|
|
129
|
+
float aa = fwidth(r) * 1.5;
|
|
48
130
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
131
|
+
// ---- throat: the other side, compressed toward the rim like a fisheye.
|
|
132
|
+
// Near the throat edge light is bent hardest, so the view squeezes into
|
|
133
|
+
// a thin bright Einstein ring.
|
|
134
|
+
float s = clamp(r / rt, 0.0, 1.0);
|
|
135
|
+
float psi = pow(s, 0.55) * 1.45;
|
|
136
|
+
vec3 dir = normalize(vec3(vP / max(r, 1e-4) * sin(psi), cos(psi)));
|
|
137
|
+
vec3 inside = otherSide(dir, t) * (0.5 + 0.5 * (1.0 - s * s));
|
|
138
|
+
float throat = 1.0 - smoothstep(rt - aa, rt + aa, r);
|
|
139
|
+
float einstein = exp(-pow((r - rt) / (0.018 + aa), 2.0));
|
|
52
140
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
float
|
|
141
|
+
// ---- funnel: swirling matter on logarithmic spiral arms with Keplerian
|
|
142
|
+
// shear (Omega ~ r^-1.5), crossfaded between two phases so it never winds tight.
|
|
143
|
+
float x = (r - rt) / max(1.0 - rt, 1e-3);
|
|
144
|
+
float omega = pow(max(r, 0.05) / 0.5, -1.5);
|
|
145
|
+
float ph = t / 6.0;
|
|
146
|
+
float f0 = fract(ph), f1 = fract(ph + 0.5);
|
|
147
|
+
float wgt = 1.0 - abs(2.0 * f0 - 1.0);
|
|
148
|
+
float th0 = theta + omega * f0 * 6.0 * 0.8;
|
|
149
|
+
float th1 = theta + omega * f1 * 6.0 * 0.8;
|
|
150
|
+
float n0 = fbm3(vec3(cos(th0) * r * 3.0, sin(th0) * r * 3.0, floor(ph) * 3.1), 4);
|
|
151
|
+
float n1 = fbm3(vec3(cos(th1) * r * 3.0, sin(th1) * r * 3.0, floor(ph + 0.5) * 3.1 + 9.0), 4);
|
|
152
|
+
float n = n0 * wgt + n1 * (1.0 - wgt);
|
|
153
|
+
float arms = 0.5 + 0.5 * sin(uSpiralTurns * log(max(r, 0.02)) * 2.2 - 2.0 * (theta + omega * t * 0.12) + n * 3.0);
|
|
154
|
+
float swirl = (smoothstep(0.25, 1.0, arms) * 0.7 + n * 0.8);
|
|
155
|
+
float bright = pow(1.0 - x, 2.2) * 1.6 + 0.08;
|
|
156
|
+
vec3 grad = mix(uOuterGlowColor, uInnerGlowColor, pow(1.0 - x, 1.8));
|
|
157
|
+
float outer = (1.0 - throat) * (1.0 - smoothstep(0.82, 1.0, r));
|
|
158
|
+
vec3 funnel = grad * swirl * bright * outer;
|
|
56
159
|
|
|
57
|
-
vec3
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
col += uOuterColor * rim * 0.8;
|
|
61
|
-
|
|
62
|
-
float alpha = (vortex * 0.5 + edgeFade * 0.25 + core * 0.5 + rim * 0.4 + singularity * 0.3)
|
|
63
|
-
* uOpacity * uIntensity;
|
|
64
|
-
if (alpha < 0.008) discard;
|
|
65
|
-
gl_FragColor = vec4(col, alpha);
|
|
160
|
+
vec3 col = inside * throat + funnel + mix(uInnerGlowColor, vec3(1.0), 0.6) * einstein * 1.4;
|
|
161
|
+
float alpha = clamp(throat + (swirl * bright * 0.8) * outer + einstein, 0.0, 1.0) * uOpacity;
|
|
162
|
+
gl_FragColor = vec4(col * uIntensity * uOpacity, alpha);
|
|
66
163
|
}
|
|
67
164
|
`;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
attribute float aSpeed; // orbit speed multiplier 0.3..1.7
|
|
75
|
-
attribute float aPhase; // twinkle phase
|
|
76
|
-
|
|
77
|
-
uniform float u_time;
|
|
165
|
+
const infallVert = /* glsl */ `
|
|
166
|
+
attribute vec3 aSeed; // x: start angle, y: phase, z: random
|
|
167
|
+
uniform float uTime;
|
|
168
|
+
uniform float uRotationSpeed;
|
|
169
|
+
uniform float uThroatSize;
|
|
170
|
+
uniform float uFunnelDepth;
|
|
78
171
|
uniform float uRadius;
|
|
79
|
-
uniform float
|
|
80
|
-
uniform float
|
|
81
|
-
|
|
82
|
-
varying float
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
float
|
|
88
|
-
float
|
|
89
|
-
float
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
float
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
vec4 mv
|
|
99
|
-
gl_PointSize =
|
|
100
|
-
gl_Position
|
|
172
|
+
uniform float uBound;
|
|
173
|
+
uniform float uIntensity;
|
|
174
|
+
varying float vHeat;
|
|
175
|
+
varying float vFade;
|
|
176
|
+
void main(){
|
|
177
|
+
// Matter spirals in on r = r0 exp(-k tau) with Keplerian angular speed;
|
|
178
|
+
// the angle is the closed-form integral of Omega = Omega0 r^-1.5.
|
|
179
|
+
float life = fract(aSeed.y + uTime * uRotationSpeed * 0.05 * (0.7 + 0.6 * aSeed.z));
|
|
180
|
+
float r0 = 0.95;
|
|
181
|
+
float rt = uThroatSize;
|
|
182
|
+
float k = log(r0 / rt);
|
|
183
|
+
float r = r0 * exp(-k * life);
|
|
184
|
+
float om0 = 0.35;
|
|
185
|
+
float phi = aSeed.x * 6.2832 + om0 / (1.5 * k) * (pow(r / 0.5, -1.5) - pow(r0 / 0.5, -1.5)) * 3.0;
|
|
186
|
+
float s = clamp((r - rt) / max(1.0 - rt, 1e-3), 0.0, 1.0);
|
|
187
|
+
float depth = uFunnelDepth * (1.0 - sqrt(s));
|
|
188
|
+
vec3 pos = vec3(cos(phi) * r, sin(phi) * r, -depth + 0.01) * (uRadius * uBound);
|
|
189
|
+
vHeat = pow(1.0 - s, 1.5);
|
|
190
|
+
vFade = smoothstep(0.0, 0.1, life) * (1.0 - smoothstep(0.85, 1.0, life));
|
|
191
|
+
vec4 mv = modelViewMatrix * vec4(pos, 1.0);
|
|
192
|
+
gl_PointSize = (1.2 + 3.5 * vHeat) * uIntensity * (4.0 * uRadius * uBound / max(-mv.z, 1e-3));
|
|
193
|
+
gl_Position = projectionMatrix * mv;
|
|
101
194
|
}
|
|
102
195
|
`;
|
|
103
|
-
const
|
|
104
|
-
uniform vec3
|
|
196
|
+
const infallFrag = /* glsl */ `
|
|
197
|
+
uniform vec3 uInnerGlowColor;
|
|
198
|
+
uniform vec3 uOuterGlowColor;
|
|
105
199
|
uniform float uOpacity;
|
|
106
|
-
varying float
|
|
107
|
-
|
|
108
|
-
void main()
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
200
|
+
varying float vHeat;
|
|
201
|
+
varying float vFade;
|
|
202
|
+
void main(){
|
|
203
|
+
float d = length(gl_PointCoord - 0.5);
|
|
204
|
+
if (d > 0.5) discard;
|
|
205
|
+
float core = smoothstep(0.5, 0.0, d);
|
|
206
|
+
// infalling matter heats up and blueshifts toward the throat
|
|
207
|
+
vec3 col = mix(uOuterGlowColor, mix(uInnerGlowColor, vec3(0.85, 0.92, 1.0), vHeat), vHeat);
|
|
208
|
+
float a = core * core * vFade * (0.3 + 0.9 * vHeat) * uOpacity;
|
|
209
|
+
gl_FragColor = vec4(col * a, a);
|
|
114
210
|
}
|
|
115
211
|
`;
|
|
116
212
|
const PortalEffect = ({ boundingRadius, config, animations, onObjectReady, onObjectDispose }) => {
|
|
117
|
-
const { radius, spiralTurns, innerGlowColor, outerGlowColor, rotationSpeed, particleRingEnabled, particleCount,
|
|
118
|
-
const startValuesCacheRef = useRef({});
|
|
213
|
+
const { intensity = 1, speed = 1, opacity = 0.95, radius = 1.5, spiralTurns = 6, innerGlowColor = '#e9e4ff', outerGlowColor = '#8800ff', rotationSpeed = 1.2, particleRingEnabled = true, particleCount = 160, throatSize = 0.38, funnelDepth = 0.6, otherSideColor = '#2a6bff', } = config;
|
|
119
214
|
const rootRef = useRef(null);
|
|
215
|
+
const animCache = useRef({});
|
|
120
216
|
useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
side: THREE.DoubleSide,
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
uRadius: { value: r },
|
|
173
|
-
uPointSize: { value: 5 * intensity },
|
|
174
|
-
u_speed: { value: speed * 0.5 },
|
|
175
|
-
uColor: { value: dustColVec },
|
|
176
|
-
uOpacity: { value: opacity * 0.6 },
|
|
177
|
-
},
|
|
178
|
-
transparent: true,
|
|
179
|
-
depthWrite: false,
|
|
180
|
-
blending: THREE.AdditiveBlending,
|
|
181
|
-
});
|
|
182
|
-
return { dustGeo: geo, dustMat: mat };
|
|
183
|
-
}, [particleCount, r, innerGlowColor, intensity, speed, opacity]);
|
|
184
|
-
useFrame((state) => {
|
|
185
|
-
const t = state.clock.getElapsedTime();
|
|
186
|
-
discMaterial.uniforms.u_time.value = t;
|
|
187
|
-
dustMat.uniforms.u_time.value = t;
|
|
188
|
-
if (animations?.length) {
|
|
189
|
-
applyGenerativeAnimations([discMaterial, dustMat], animations, startValuesCacheRef.current, Date.now(), false);
|
|
190
|
-
}
|
|
217
|
+
// a standalone effect gets boundingRadius 1; guard against an empty host
|
|
218
|
+
const b = boundingRadius > 0 ? boundingRadius : 1;
|
|
219
|
+
const uniforms = useMemo(() => ({
|
|
220
|
+
uTime: { value: 0 },
|
|
221
|
+
uSpeed: { value: 1 },
|
|
222
|
+
uBound: { value: 1 },
|
|
223
|
+
uIntensity: { value: 1 },
|
|
224
|
+
uOpacity: { value: 1 },
|
|
225
|
+
uRadius: { value: 1.5 },
|
|
226
|
+
uSpiralTurns: { value: 6 },
|
|
227
|
+
uRotationSpeed: { value: 1.2 },
|
|
228
|
+
uThroatSize: { value: 0.38 },
|
|
229
|
+
uFunnelDepth: { value: 0.6 },
|
|
230
|
+
uInnerGlowColor: { value: new THREE.Color() },
|
|
231
|
+
uOuterGlowColor: { value: new THREE.Color() },
|
|
232
|
+
uOtherSideColor: { value: new THREE.Color() },
|
|
233
|
+
}), []);
|
|
234
|
+
const materials = useMemo(() => [
|
|
235
|
+
new THREE.ShaderMaterial({ vertexShader: portalVert, fragmentShader: portalFrag, uniforms, ...PRE_NORMAL, side: THREE.DoubleSide }),
|
|
236
|
+
new THREE.ShaderMaterial({ vertexShader: infallVert, fragmentShader: infallFrag, uniforms, ...PRE_ADD }),
|
|
237
|
+
], [uniforms]);
|
|
238
|
+
useEffect(() => () => materials.forEach((m) => m.dispose()), [materials]);
|
|
239
|
+
// a unit disc; the vertex shader scales it and bends it into the funnel
|
|
240
|
+
const discGeometry = useMemo(() => new THREE.RingGeometry(0.0005, 1, 128, 64), []);
|
|
241
|
+
useEffect(() => () => discGeometry.dispose(), [discGeometry]);
|
|
242
|
+
const infallGeometry = useMemo(() => {
|
|
243
|
+
const inf = buildInfall(particleCount);
|
|
244
|
+
const g = new THREE.BufferGeometry();
|
|
245
|
+
g.setAttribute('position', new THREE.BufferAttribute(new Float32Array(inf.count * 3), 3));
|
|
246
|
+
g.setAttribute('aSeed', new THREE.BufferAttribute(inf.aSeed, 3));
|
|
247
|
+
return g;
|
|
248
|
+
}, [particleCount]);
|
|
249
|
+
useEffect(() => () => infallGeometry.dispose(), [infallGeometry]);
|
|
250
|
+
useLayoutEffect(() => {
|
|
251
|
+
uniforms.uSpeed.value = speed;
|
|
252
|
+
uniforms.uBound.value = b;
|
|
253
|
+
uniforms.uIntensity.value = intensity;
|
|
254
|
+
uniforms.uOpacity.value = opacity;
|
|
255
|
+
uniforms.uRadius.value = radius;
|
|
256
|
+
uniforms.uSpiralTurns.value = spiralTurns;
|
|
257
|
+
uniforms.uRotationSpeed.value = rotationSpeed;
|
|
258
|
+
uniforms.uThroatSize.value = throatSize;
|
|
259
|
+
uniforms.uFunnelDepth.value = funnelDepth;
|
|
260
|
+
uniforms.uInnerGlowColor.value.set(innerGlowColor);
|
|
261
|
+
uniforms.uOuterGlowColor.value.set(outerGlowColor);
|
|
262
|
+
uniforms.uOtherSideColor.value.set(otherSideColor);
|
|
263
|
+
}, [uniforms, speed, b, intensity, opacity, radius, spiralTurns, rotationSpeed, throatSize, funnelDepth, innerGlowColor, outerGlowColor, otherSideColor]);
|
|
264
|
+
useFrame((_, delta) => {
|
|
265
|
+
uniforms.uTime.value += delta * uniforms.uSpeed.value;
|
|
266
|
+
if (animations?.length)
|
|
267
|
+
applyGenerativeAnimations(materials, animations, animCache.current, Date.now(), false);
|
|
191
268
|
});
|
|
192
|
-
return (
|
|
269
|
+
return (_jsx("group", { ref: rootRef, children: _jsxs("group", { rotation: [-Math.PI / 2, 0, 0], position: [0, -b * 0.75, 0], children: [_jsx("mesh", { geometry: discGeometry, material: materials[0], frustumCulled: false }), _jsx("points", { geometry: infallGeometry, material: materials[1], visible: particleRingEnabled, frustumCulled: false })] }) }));
|
|
193
270
|
};
|
|
194
271
|
export default PortalEffect;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AnimationOptions, ShockwaveConfig } from '@3driseai/3drise-core';
|
|
3
3
|
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
4
|
-
interface ShockwaveEffectProps extends ObjectReadyProps {
|
|
4
|
+
export interface ShockwaveEffectProps extends ObjectReadyProps {
|
|
5
5
|
boundingRadius: number;
|
|
6
6
|
config: ShockwaveConfig;
|
|
7
7
|
animations?: AnimationOptions[];
|
|
8
|
+
/** True when the effect is attached to an object, so it can react to the host. */
|
|
9
|
+
hasHost?: boolean;
|
|
8
10
|
}
|
|
9
11
|
declare const ShockwaveEffect: React.FC<ShockwaveEffectProps>;
|
|
10
12
|
export default ShockwaveEffect;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShockwaveEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/ShockwaveEffect.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ShockwaveEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/ShockwaveEffect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAG3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC1D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AA4hBD,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+BnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|