@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,195 +1,325 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import {
|
|
3
|
-
import { useFrame } from '@react-three/fiber';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
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
|
-
|
|
7
|
+
/**
|
|
8
|
+
* A ray-traced Schwarzschild black hole.
|
|
9
|
+
*
|
|
10
|
+
* A proxy sphere around the hole is shaded per pixel: each view ray is bent by
|
|
11
|
+
* the photon geodesic a = -1.5 h^2 x / r^5, so the disk behind the hole is
|
|
12
|
+
* lensed over and under it and a thin photon ring forms. The disk follows the
|
|
13
|
+
* Shakura-Sunyaev temperature profile T ~ r^-3/4 (1 - sqrt(r_in/r))^1/4, and
|
|
14
|
+
* its light is Doppler-beamed and gravitationally redshifted. Two jets leave
|
|
15
|
+
* along the spin axis.
|
|
16
|
+
*
|
|
17
|
+
* Distances in the shader are in units of the horizon radius (uRs).
|
|
18
|
+
* Flying the camera into the proxy flips it to back faces so the view keeps working.
|
|
19
|
+
*/
|
|
20
|
+
const PRE_NORMAL = { transparent: true, depthWrite: false, blending: THREE.NormalBlending, premultipliedAlpha: true };
|
|
21
|
+
const ADD = { transparent: true, depthWrite: false, blending: THREE.AdditiveBlending };
|
|
22
|
+
const blackHoleVert = /* glsl */ `
|
|
23
|
+
varying vec3 vLocal;
|
|
24
|
+
varying vec3 vCamLocal;
|
|
25
|
+
void main(){
|
|
26
|
+
vLocal = position;
|
|
27
|
+
vCamLocal = (inverse(modelMatrix) * vec4(cameraPosition, 1.0)).xyz;
|
|
28
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
29
|
+
}
|
|
11
30
|
`;
|
|
12
|
-
const
|
|
13
|
-
uniform float
|
|
14
|
-
uniform float
|
|
15
|
-
uniform
|
|
16
|
-
uniform float
|
|
31
|
+
const blackHoleFrag = /* glsl */ `
|
|
32
|
+
uniform float uTime;
|
|
33
|
+
uniform float uRs; // Schwarzschild radius, local units
|
|
34
|
+
uniform float uOuter; // disk outer edge and proxy radius, in rs
|
|
35
|
+
uniform float uLensing;
|
|
36
|
+
uniform float uBeaming;
|
|
37
|
+
uniform float uRotationSpeed;
|
|
17
38
|
uniform float uIntensity;
|
|
39
|
+
uniform float uOpacity;
|
|
40
|
+
uniform float uInside; // 1 when the camera is inside the proxy sphere
|
|
41
|
+
uniform vec3 uDiskColor;
|
|
42
|
+
uniform vec3 uColor;
|
|
43
|
+
varying vec3 vLocal;
|
|
44
|
+
varying vec3 vCamLocal;
|
|
18
45
|
|
|
19
|
-
|
|
46
|
+
|
|
47
|
+
float hash13(vec3 p3){
|
|
48
|
+
p3 = fract(p3 * 0.1031);
|
|
49
|
+
p3 += dot(p3, p3.zyx + 31.32);
|
|
50
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
51
|
+
}
|
|
52
|
+
float vnoise(vec3 p){
|
|
53
|
+
vec3 i = floor(p);
|
|
54
|
+
vec3 f = fract(p);
|
|
55
|
+
f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
|
56
|
+
float n000 = hash13(i);
|
|
57
|
+
float n100 = hash13(i + vec3(1.0, 0.0, 0.0));
|
|
58
|
+
float n010 = hash13(i + vec3(0.0, 1.0, 0.0));
|
|
59
|
+
float n110 = hash13(i + vec3(1.0, 1.0, 0.0));
|
|
60
|
+
float n001 = hash13(i + vec3(0.0, 0.0, 1.0));
|
|
61
|
+
float n101 = hash13(i + vec3(1.0, 0.0, 1.0));
|
|
62
|
+
float n011 = hash13(i + vec3(0.0, 1.0, 1.0));
|
|
63
|
+
float n111 = hash13(i + vec3(1.0, 1.0, 1.0));
|
|
64
|
+
return mix(mix(mix(n000, n100, f.x), mix(n010, n110, f.x), f.y),
|
|
65
|
+
mix(mix(n001, n101, f.x), mix(n011, n111, f.x), f.y), f.z);
|
|
66
|
+
}
|
|
67
|
+
// low-frequency fBm; the rotation between octaves hides the lattice
|
|
68
|
+
const mat3 FBM_ROT = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
|
69
|
+
float fbm3(vec3 p, int octaves){
|
|
70
|
+
float a = 0.5, s = 0.0;
|
|
71
|
+
for (int i = 0; i < 5; i++){
|
|
72
|
+
if (i >= octaves) break;
|
|
73
|
+
s += a * vnoise(p);
|
|
74
|
+
p = FBM_ROT * p * 2.02;
|
|
75
|
+
a *= 0.5;
|
|
76
|
+
}
|
|
77
|
+
return s;
|
|
78
|
+
}
|
|
20
79
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
vec3
|
|
25
|
-
vec3
|
|
26
|
-
|
|
27
|
-
|
|
80
|
+
|
|
81
|
+
// Observed temperature (1 = the disk's hottest ring at rest) to colour.
|
|
82
|
+
vec3 diskRamp(float T){
|
|
83
|
+
vec3 c0 = uDiskColor * 0.3;
|
|
84
|
+
vec3 c1 = uDiskColor;
|
|
85
|
+
vec3 c2 = vec3(1.0, 0.86, 0.66);
|
|
86
|
+
vec3 c3 = vec3(0.78, 0.87, 1.0) * 1.5;
|
|
87
|
+
if (T < 0.5) return mix(c0, c1, T * 2.0);
|
|
88
|
+
if (T < 1.0) return mix(c1, c2, (T - 0.5) * 2.0);
|
|
89
|
+
return mix(c2, c3, clamp(T - 1.0, 0.0, 1.0));
|
|
28
90
|
}
|
|
29
91
|
|
|
30
|
-
float
|
|
92
|
+
float diskNoise(float x, float ang, float off){
|
|
93
|
+
vec3 q = vec3(cos(ang) * x, sin(ang) * x, off) * 0.85;
|
|
94
|
+
float n = fbm3(q, 4);
|
|
95
|
+
// faint concentric structure, bent by the noise
|
|
96
|
+
return n + 0.18 * sin(log(x) * 22.0 + n * 5.0);
|
|
97
|
+
}
|
|
31
98
|
|
|
32
|
-
void main()
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
99
|
+
void main(){
|
|
100
|
+
const float RIN = 3.0; // innermost stable circular orbit, in rs
|
|
101
|
+
vec3 ro = vCamLocal / uRs;
|
|
102
|
+
vec3 rd = normalize(vLocal - vCamLocal);
|
|
103
|
+
vec3 pos = uInside > 0.5 ? ro : vLocal / uRs;
|
|
104
|
+
vec3 vel = rd;
|
|
37
105
|
|
|
38
|
-
|
|
106
|
+
// h = |x cross v| is conserved along a photon path; the Schwarzschild
|
|
107
|
+
// geodesic in these units bends the ray by a = -1.5 h^2 x / r^5.
|
|
108
|
+
vec3 hv = cross(pos, vel);
|
|
109
|
+
float h2 = dot(hv, hv);
|
|
39
110
|
|
|
40
|
-
|
|
41
|
-
float
|
|
111
|
+
vec3 col = vec3(0.0);
|
|
112
|
+
float trans = 1.0;
|
|
113
|
+
float captured = 0.0;
|
|
114
|
+
float glow = 0.0;
|
|
42
115
|
|
|
43
|
-
|
|
44
|
-
float
|
|
45
|
-
float
|
|
116
|
+
float ph = uTime * uRotationSpeed / 7.0;
|
|
117
|
+
float f0 = fract(ph), f1 = fract(ph + 0.5);
|
|
118
|
+
float w0 = 1.0 - abs(2.0 * f0 - 1.0);
|
|
119
|
+
float off0 = floor(ph) * 7.31, off1 = floor(ph + 0.5) * 7.31 + 3.7;
|
|
46
120
|
|
|
47
|
-
|
|
48
|
-
|
|
121
|
+
for (int i = 0; i < 64; i++){
|
|
122
|
+
float r2 = dot(pos, pos);
|
|
123
|
+
float r = sqrt(r2);
|
|
124
|
+
if (r < 1.0){ captured = 1.0; break; }
|
|
125
|
+
if (r > uOuter * 1.02 && dot(pos, vel) > 0.0) break;
|
|
49
126
|
|
|
50
|
-
|
|
51
|
-
|
|
127
|
+
float dt = clamp(0.16 * (r - 0.8), 0.03, 0.9);
|
|
128
|
+
vec3 acc = -1.5 * h2 * pos / (r2 * r2 * r) * uLensing;
|
|
129
|
+
vec3 prev = pos;
|
|
130
|
+
vel += acc * dt;
|
|
131
|
+
pos += vel * dt;
|
|
52
132
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
133
|
+
// light hugging the photon sphere (r = 1.5) forms the thin photon ring
|
|
134
|
+
glow += exp(-pow((r - 1.5) * 9.0, 2.0)) * dt;
|
|
135
|
+
|
|
136
|
+
// thin disk in the y = 0 plane
|
|
137
|
+
if (prev.y * pos.y < 0.0){
|
|
138
|
+
vec3 hit = mix(prev, pos, prev.y / (prev.y - pos.y));
|
|
139
|
+
float x = length(hit.xz);
|
|
140
|
+
if (x > RIN && x < uOuter){
|
|
141
|
+
// Shakura-Sunyaev thin disk: T ~ r^-3/4 (1 - sqrt(rin/r))^1/4, peak ~0.488
|
|
142
|
+
float T = pow(x / RIN, -0.75) * pow(1.0 - sqrt(RIN / x), 0.25) / 0.488;
|
|
143
|
+
// Keplerian orbit: Omega = sqrt(GM/r^3) with GM = 1/2 in these units
|
|
144
|
+
float omega = sqrt(0.5 / (x * x * x));
|
|
145
|
+
float ang = atan(hit.z, hit.x);
|
|
146
|
+
float n = diskNoise(x, ang - omega * f0 * 7.0 * 6.0, off0) * w0
|
|
147
|
+
+ diskNoise(x, ang - omega * f1 * 7.0 * 6.0, off1) * (1.0 - w0);
|
|
148
|
+
// relativistic Doppler beaming and gravitational redshift
|
|
149
|
+
vec3 vdir = normalize(vec3(-hit.z, 0.0, hit.x));
|
|
150
|
+
float beta = min(sqrt(0.5 / max(x - 1.0, 0.5)), 0.7);
|
|
151
|
+
float cosA = dot(vdir, -normalize(vel));
|
|
152
|
+
float gam = 1.0 / sqrt(1.0 - beta * beta);
|
|
153
|
+
float D = 1.0 / (gam * (1.0 - beta * cosA));
|
|
154
|
+
float g = mix(1.0, D * sqrt(1.0 - 1.0 / x), uBeaming);
|
|
155
|
+
float Tobs = T * g;
|
|
156
|
+
float edge = smoothstep(RIN, RIN * 1.15, x) * (1.0 - smoothstep(uOuter * 0.7, uOuter, x));
|
|
157
|
+
float dens = clamp(0.2 + 1.1 * (n - 0.3), 0.0, 1.0) * edge;
|
|
158
|
+
float a = clamp(dens * uOpacity * 1.4, 0.0, 1.0);
|
|
159
|
+
vec3 emit = diskRamp(Tobs) * pow(max(Tobs, 0.0), 2.2) * 1.6 * uIntensity;
|
|
160
|
+
col += trans * emit * a;
|
|
161
|
+
trans *= 1.0 - a;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (trans < 0.02) break;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
col += trans * uColor * glow * 0.9 * uIntensity * (1.0 - captured);
|
|
168
|
+
float alpha = captured > 0.5 ? 1.0 : clamp(1.0 - trans + glow * 0.4, 0.0, 1.0);
|
|
76
169
|
gl_FragColor = vec4(col, alpha);
|
|
77
170
|
}
|
|
78
171
|
`;
|
|
79
|
-
const lensVert = /* glsl */ `
|
|
80
|
-
varying vec3 vNormal;
|
|
81
|
-
void main() {
|
|
82
|
-
vNormal = (modelMatrix * vec4(normal, 0.0)).xyz;
|
|
83
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
84
|
-
}
|
|
85
|
-
`;
|
|
86
|
-
// ── Jet particle shader ───────────────────────────────────────────────────────
|
|
87
172
|
const jetVert = /* glsl */ `
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
float r = uRadius * (1.0 - t * 0.85);
|
|
100
|
-
float a = aPhase + t * 4.0;
|
|
101
|
-
float x = cos(a) * r;
|
|
102
|
-
float z = sin(a) * r;
|
|
103
|
-
float y = uDir * t * uLength;
|
|
104
|
-
vec4 mv = modelViewMatrix * vec4(x, y, z, 1.0);
|
|
105
|
-
gl_PointSize = (1.0 - t) * 6.0 * (200.0 / -mv.z);
|
|
106
|
-
gl_Position = projectionMatrix * mv;
|
|
173
|
+
varying vec2 vUv;
|
|
174
|
+
varying vec3 vNormalW;
|
|
175
|
+
varying vec3 vViewW;
|
|
176
|
+
varying vec3 vAxisW;
|
|
177
|
+
void main(){
|
|
178
|
+
vUv = uv;
|
|
179
|
+
vec4 wp = modelMatrix * vec4(position, 1.0);
|
|
180
|
+
vNormalW = normalize(mat3(modelMatrix) * normal);
|
|
181
|
+
vViewW = normalize(cameraPosition - wp.xyz);
|
|
182
|
+
vAxisW = normalize(mat3(modelMatrix) * vec3(0.0, 1.0, 0.0));
|
|
183
|
+
gl_Position = projectionMatrix * viewMatrix * wp;
|
|
107
184
|
}
|
|
108
185
|
`;
|
|
109
186
|
const jetFrag = /* glsl */ `
|
|
187
|
+
uniform float uTime;
|
|
110
188
|
uniform vec3 uJetColor;
|
|
189
|
+
uniform float uIntensity;
|
|
111
190
|
uniform float uOpacity;
|
|
112
|
-
varying
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
191
|
+
varying vec2 vUv;
|
|
192
|
+
varying vec3 vNormalW;
|
|
193
|
+
varying vec3 vViewW;
|
|
194
|
+
varying vec3 vAxisW;
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
float hash13(vec3 p3){
|
|
198
|
+
p3 = fract(p3 * 0.1031);
|
|
199
|
+
p3 += dot(p3, p3.zyx + 31.32);
|
|
200
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
201
|
+
}
|
|
202
|
+
float vnoise(vec3 p){
|
|
203
|
+
vec3 i = floor(p);
|
|
204
|
+
vec3 f = fract(p);
|
|
205
|
+
f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
|
206
|
+
float n000 = hash13(i);
|
|
207
|
+
float n100 = hash13(i + vec3(1.0, 0.0, 0.0));
|
|
208
|
+
float n010 = hash13(i + vec3(0.0, 1.0, 0.0));
|
|
209
|
+
float n110 = hash13(i + vec3(1.0, 1.0, 0.0));
|
|
210
|
+
float n001 = hash13(i + vec3(0.0, 0.0, 1.0));
|
|
211
|
+
float n101 = hash13(i + vec3(1.0, 0.0, 1.0));
|
|
212
|
+
float n011 = hash13(i + vec3(0.0, 1.0, 1.0));
|
|
213
|
+
float n111 = hash13(i + vec3(1.0, 1.0, 1.0));
|
|
214
|
+
return mix(mix(mix(n000, n100, f.x), mix(n010, n110, f.x), f.y),
|
|
215
|
+
mix(mix(n001, n101, f.x), mix(n011, n111, f.x), f.y), f.z);
|
|
216
|
+
}
|
|
217
|
+
// low-frequency fBm; the rotation between octaves hides the lattice
|
|
218
|
+
const mat3 FBM_ROT = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
|
219
|
+
float fbm3(vec3 p, int octaves){
|
|
220
|
+
float a = 0.5, s = 0.0;
|
|
221
|
+
for (int i = 0; i < 5; i++){
|
|
222
|
+
if (i >= octaves) break;
|
|
223
|
+
s += a * vnoise(p);
|
|
224
|
+
p = FBM_ROT * p * 2.02;
|
|
225
|
+
a *= 0.5;
|
|
226
|
+
}
|
|
227
|
+
return s;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
void main(){
|
|
232
|
+
// optical depth is largest through the middle of the cone
|
|
233
|
+
float ndv = abs(dot(normalize(vNormalW), normalize(vViewW)));
|
|
234
|
+
float core = pow(ndv, 1.6);
|
|
235
|
+
float v = vUv.y; // 0 at the base, 1 at the tip
|
|
236
|
+
// knots of plasma flowing outward
|
|
237
|
+
float knots = fbm3(vec3(vUv.x * 6.2832 * 0.5, v * 5.0 - uTime * 1.2, 0.0), 3);
|
|
238
|
+
float fall = exp(-v * 2.4) * smoothstep(0.0, 0.06, v);
|
|
239
|
+
// relativistic beaming: the jet pointing at the camera is brighter
|
|
240
|
+
float beta = 0.6;
|
|
241
|
+
float cosT = dot(normalize(vAxisW), normalize(vViewW));
|
|
242
|
+
float D = 1.0 / (1.25 * (1.0 - beta * cosT));
|
|
243
|
+
float I = core * fall * (0.35 + knots) * pow(D, 2.0) * uIntensity;
|
|
244
|
+
gl_FragColor = vec4(uJetColor * I * 1.6 + vec3(I * I * 0.3), clamp(I * uOpacity, 0.0, 1.0));
|
|
120
245
|
}
|
|
121
246
|
`;
|
|
247
|
+
const _inv = new THREE.Matrix4();
|
|
248
|
+
const _cam = new THREE.Vector3();
|
|
122
249
|
const BlackHoleEffect = ({ boundingRadius, config, animations, onObjectReady, onObjectDispose }) => {
|
|
123
|
-
const { diskColor, jetEnabled, jetColor, rotationSpeed, tilt,
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
250
|
+
const { intensity = 1.2, speed = 1, color = '#ffd2a0', opacity = 0.95, diskColor = '#ff6600', jetEnabled = true, jetColor = '#88aaff', rotationSpeed = 1, tilt = 15, horizonSize = 0.4, diskOuter = 3, lensing = 1, beaming = 1, } = config;
|
|
251
|
+
const rootRef = useRef(null);
|
|
252
|
+
const diskRef = useRef(null);
|
|
253
|
+
const insideRef = useRef(false);
|
|
254
|
+
const animCache = useRef({});
|
|
255
|
+
useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
|
|
256
|
+
// a standalone effect gets boundingRadius 1; guard against an empty host
|
|
257
|
+
const b = boundingRadius > 0 ? boundingRadius : 1;
|
|
258
|
+
const Rs = b * horizonSize;
|
|
259
|
+
// outer edge of the disk, in horizon radii; never inside the photon sphere region
|
|
260
|
+
const outerRs = Math.max(diskOuter / Math.max(horizonSize, 1e-3), 3.5);
|
|
261
|
+
const proxyR = Rs * outerRs * 1.03;
|
|
262
|
+
const uniforms = useMemo(() => ({
|
|
263
|
+
uTime: { value: 0 },
|
|
264
|
+
uSpeed: { value: 1 },
|
|
265
|
+
uIntensity: { value: 1 },
|
|
266
|
+
uOpacity: { value: 1 },
|
|
267
|
+
uColor: { value: new THREE.Color() },
|
|
268
|
+
uDiskColor: { value: new THREE.Color() },
|
|
269
|
+
uJetColor: { value: new THREE.Color() },
|
|
270
|
+
uRotationSpeed: { value: 1 },
|
|
271
|
+
uLensing: { value: 1 },
|
|
272
|
+
uBeaming: { value: 1 },
|
|
273
|
+
uRs: { value: 1 },
|
|
274
|
+
uOuter: { value: 7.5 },
|
|
275
|
+
uInside: { value: 0 },
|
|
276
|
+
}), []);
|
|
277
|
+
const materials = useMemo(() => [
|
|
278
|
+
new THREE.ShaderMaterial({ vertexShader: blackHoleVert, fragmentShader: blackHoleFrag, uniforms, ...PRE_NORMAL }),
|
|
279
|
+
new THREE.ShaderMaterial({ vertexShader: jetVert, fragmentShader: jetFrag, uniforms, ...ADD, side: THREE.DoubleSide }),
|
|
280
|
+
], [uniforms]);
|
|
281
|
+
useEffect(() => () => materials.forEach((m) => m.dispose()), [materials]);
|
|
282
|
+
const proxyGeometry = useMemo(() => new THREE.SphereGeometry(proxyR, 64, 40), [proxyR]);
|
|
283
|
+
const jetGeometry = useMemo(() => {
|
|
284
|
+
const jetH = b * 2.4;
|
|
285
|
+
const g = new THREE.CylinderGeometry(Rs * 1.8, Rs * 0.25, jetH, 32, 1, true);
|
|
286
|
+
g.translate(0, jetH / 2 + Rs * 1.2, 0);
|
|
287
|
+
return g;
|
|
288
|
+
}, [b, Rs]);
|
|
289
|
+
useEffect(() => () => proxyGeometry.dispose(), [proxyGeometry]);
|
|
290
|
+
useEffect(() => () => jetGeometry.dispose(), [jetGeometry]);
|
|
291
|
+
useLayoutEffect(() => {
|
|
292
|
+
uniforms.uSpeed.value = speed;
|
|
293
|
+
uniforms.uIntensity.value = intensity;
|
|
294
|
+
uniforms.uOpacity.value = opacity;
|
|
295
|
+
uniforms.uColor.value.set(color);
|
|
296
|
+
uniforms.uDiskColor.value.set(diskColor);
|
|
297
|
+
uniforms.uJetColor.value.set(jetColor);
|
|
298
|
+
uniforms.uRotationSpeed.value = rotationSpeed;
|
|
299
|
+
uniforms.uLensing.value = lensing;
|
|
300
|
+
uniforms.uBeaming.value = beaming;
|
|
301
|
+
uniforms.uRs.value = Rs;
|
|
302
|
+
uniforms.uOuter.value = outerRs;
|
|
303
|
+
}, [uniforms, speed, intensity, opacity, color, diskColor, jetColor, rotationSpeed, lensing, beaming, Rs, outerRs]);
|
|
304
|
+
useFrame((state, delta) => {
|
|
305
|
+
uniforms.uTime.value += delta * uniforms.uSpeed.value;
|
|
306
|
+
const disk = diskRef.current;
|
|
307
|
+
if (disk) {
|
|
308
|
+
disk.updateWorldMatrix(true, false);
|
|
309
|
+
_inv.copy(disk.matrixWorld).invert();
|
|
310
|
+
const inside = _cam.copy(state.camera.position).applyMatrix4(_inv).length() < proxyR;
|
|
311
|
+
if (inside !== insideRef.current) {
|
|
312
|
+
insideRef.current = inside;
|
|
313
|
+
const mat = materials[0];
|
|
314
|
+
uniforms.uInside.value = inside ? 1 : 0;
|
|
315
|
+
mat.side = inside ? THREE.BackSide : THREE.FrontSide;
|
|
316
|
+
mat.depthTest = !inside;
|
|
317
|
+
mat.needsUpdate = true;
|
|
318
|
+
}
|
|
190
319
|
}
|
|
320
|
+
if (animations?.length)
|
|
321
|
+
applyGenerativeAnimations(materials, animations, animCache.current, Date.now(), false);
|
|
191
322
|
});
|
|
192
|
-
|
|
193
|
-
return (_jsxs("group", { ref: groupRef, rotation: [0, 0, tiltRad], children: [_jsx("mesh", { material: lensMat, children: _jsx("sphereGeometry", { args: [r * 0.55, 48, 48] }) }), _jsx("mesh", { material: diskMat, rotation: [Math.PI / 2, 0, 0], children: _jsx("ringGeometry", { args: [r * 0.38, r * 1.15, 72] }) }), jetEnabled && (_jsxs(_Fragment, { children: [_jsx("points", { geometry: jetGeo, material: jetMat1 }), _jsx("points", { geometry: jetGeo, material: jetMat2 })] }))] }));
|
|
323
|
+
return (_jsx("group", { ref: rootRef, children: _jsxs("group", { rotation: [0, 0, (tilt * Math.PI) / 180], children: [_jsx("mesh", { ref: diskRef, geometry: proxyGeometry, material: materials[0] }), _jsxs("group", { visible: jetEnabled, children: [_jsx("mesh", { geometry: jetGeometry, material: materials[1], frustumCulled: false }), _jsx("mesh", { geometry: jetGeometry, material: materials[1], scale: [1, -1, 1], frustumCulled: false })] })] }) }));
|
|
194
324
|
};
|
|
195
325
|
export default BlackHoleEffect;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AnimationOptions, DandelionSeedsConfig } from '@3driseai/3drise-core';
|
|
3
|
+
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
4
|
+
export interface DandelionSeedsEffectProps extends ObjectReadyProps {
|
|
5
|
+
boundingRadius: number;
|
|
6
|
+
config: DandelionSeedsConfig;
|
|
7
|
+
animations?: AnimationOptions[];
|
|
8
|
+
/** True when the effect is attached to an object, so it can react to the host. */
|
|
9
|
+
hasHost?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const DandelionSeedsEffect: React.FC<DandelionSeedsEffectProps>;
|
|
12
|
+
export default DandelionSeedsEffect;
|
|
13
|
+
//# sourceMappingURL=DandelionSeedsEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DandelionSeedsEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/DandelionSeedsEffect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAG3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAGpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AA6cD,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA+B7D,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|