@3driseai/3drise-viewer 0.1.16 → 0.1.17
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/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 +36 -8
- 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 +16 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +8 -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/package.json +2 -2
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';
|
|
3
|
+
import * as THREE from 'three';
|
|
4
|
+
import { useFrame } from '@react-three/fiber';
|
|
5
|
+
import { applyGenerativeAnimations } from '../../utils/handleGenerativeEffectsAnimations.js';
|
|
6
|
+
import { useObjectReady } from '../../hooks/useObjectReady.js';
|
|
7
|
+
/**
|
|
8
|
+
* Atmospheric ice optics around the object as a light source: a dispersed 22° halo, sun dogs, a parhelic circle and a light pillar. Use for cold skies, suns, lamps, magic light.
|
|
9
|
+
*
|
|
10
|
+
* D = 2·asin(n·sin30°) − 60° per channel (n 1.307→1.317) · parhelia use the Bravais index n′ = √(n²−sin²e)/cos e
|
|
11
|
+
*/
|
|
12
|
+
const NOISE3 = /* glsl */ `
|
|
13
|
+
float hash13(vec3 p3){
|
|
14
|
+
p3 = fract(p3 * 0.1031);
|
|
15
|
+
p3 += dot(p3, p3.zyx + 31.32);
|
|
16
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
17
|
+
}
|
|
18
|
+
float vnoise(vec3 p){
|
|
19
|
+
vec3 i = floor(p);
|
|
20
|
+
vec3 f = fract(p);
|
|
21
|
+
f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
|
22
|
+
float n000 = hash13(i);
|
|
23
|
+
float n100 = hash13(i + vec3(1.0, 0.0, 0.0));
|
|
24
|
+
float n010 = hash13(i + vec3(0.0, 1.0, 0.0));
|
|
25
|
+
float n110 = hash13(i + vec3(1.0, 1.0, 0.0));
|
|
26
|
+
float n001 = hash13(i + vec3(0.0, 0.0, 1.0));
|
|
27
|
+
float n101 = hash13(i + vec3(1.0, 0.0, 1.0));
|
|
28
|
+
float n011 = hash13(i + vec3(0.0, 1.0, 1.0));
|
|
29
|
+
float n111 = hash13(i + vec3(1.0, 1.0, 1.0));
|
|
30
|
+
return mix(mix(mix(n000, n100, f.x), mix(n010, n110, f.x), f.y),
|
|
31
|
+
mix(mix(n001, n101, f.x), mix(n011, n111, f.x), f.y), f.z);
|
|
32
|
+
}
|
|
33
|
+
// low-frequency fBm; the rotation between octaves hides the lattice
|
|
34
|
+
const mat3 FBM_ROT = mat3(0.00, 0.80, 0.60, -0.80, 0.36, -0.48, -0.60, -0.48, 0.64);
|
|
35
|
+
float fbm3(vec3 p, int octaves){
|
|
36
|
+
float a = 0.5, s = 0.0;
|
|
37
|
+
for (int i = 0; i < 5; i++){
|
|
38
|
+
if (i >= octaves) break;
|
|
39
|
+
s += a * vnoise(p);
|
|
40
|
+
p = FBM_ROT * p * 2.02;
|
|
41
|
+
a *= 0.5;
|
|
42
|
+
}
|
|
43
|
+
return s;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Halos are refraction, not glow. A hexagonal ice prism has 60° side faces;
|
|
48
|
+
// a ray through two of them is deviated by at least D = 2 asin(n sin30°) - 60°,
|
|
49
|
+
// and randomly tumbling crystals pile light up at that minimum, so a ring of
|
|
50
|
+
// radius D appears around the light with a razor inner edge and a diffuse
|
|
51
|
+
// outer skirt. Ice is dispersive (n = 1.307 red, 1.317 blue), so the inner
|
|
52
|
+
// edge is red and the outside washes to white-blue; inside the ring no light
|
|
53
|
+
// is deviated at all, so the sky there is darker. The 90° prism faces give the
|
|
54
|
+
// same construction at 46°. Flat plate crystals drift with their faces level,
|
|
55
|
+
// so their 60° prisms act in the horizontal plane only: they put the same
|
|
56
|
+
// caustic left and right of the source at the Bravais index
|
|
57
|
+
// n' = sqrt(n^2 - sin^2 e)/cos e, which is why sun dogs sit a little further
|
|
58
|
+
// out as the source climbs, and vanish above e = 61°. Reflections off those
|
|
59
|
+
// same level faces give the parhelic circle and, off their ends, the pillar.
|
|
60
|
+
// Everything is drawn on one billboard by measuring, per pixel, the angle
|
|
61
|
+
// between the view ray and the direction to the source.
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
const haloVert = /* glsl */ `
|
|
64
|
+
uniform float uHaloScale;
|
|
65
|
+
uniform float uBound;
|
|
66
|
+
varying vec3 vViewPos;
|
|
67
|
+
varying vec3 vSunView;
|
|
68
|
+
varying float vScale;
|
|
69
|
+
varying float vHalf;
|
|
70
|
+
varying float vSrc;
|
|
71
|
+
void main(){
|
|
72
|
+
vec4 hostView = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);
|
|
73
|
+
float D = max(-hostView.z, 0.05);
|
|
74
|
+
// angular radius of the source; keep the 22 deg ring clear of it
|
|
75
|
+
float hostAng = atan(uBound / max(D, uBound * 1.02));
|
|
76
|
+
float s = max(uHaloScale, hostAng * 1.7 / 0.38397);
|
|
77
|
+
vScale = s;
|
|
78
|
+
float A = clamp(0.8029 * s * 1.3 + 0.10, 0.22, 1.31);
|
|
79
|
+
vHalf = A;
|
|
80
|
+
// apparent size of the source, in the same units the halo angles are measured in
|
|
81
|
+
vSrc = max(hostAng / s * 57.2957795, 0.6);
|
|
82
|
+
float zq = max(D - uBound * 1.05, 0.06);
|
|
83
|
+
vec3 c = hostView.xyz * (zq / D);
|
|
84
|
+
float hq = zq * tan(A) * 1.3;
|
|
85
|
+
vec3 p = c + vec3(position.x * hq, position.y * hq, 0.0);
|
|
86
|
+
vViewPos = p;
|
|
87
|
+
vSunView = hostView.xyz;
|
|
88
|
+
gl_Position = projectionMatrix * vec4(p, 1.0);
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
const haloFrag = /* glsl */ `
|
|
92
|
+
uniform float uTime;
|
|
93
|
+
uniform vec3 uColor;
|
|
94
|
+
uniform float uIntensity;
|
|
95
|
+
uniform float uOpacity;
|
|
96
|
+
uniform float uSunDogs;
|
|
97
|
+
uniform float uOuterHalo;
|
|
98
|
+
uniform float uParhelicCircle;
|
|
99
|
+
uniform float uPillar;
|
|
100
|
+
uniform float uGlare;
|
|
101
|
+
${NOISE3}
|
|
102
|
+
varying vec3 vViewPos;
|
|
103
|
+
varying vec3 vSunView;
|
|
104
|
+
varying float vScale;
|
|
105
|
+
varying float vHalf;
|
|
106
|
+
varying float vSrc;
|
|
107
|
+
|
|
108
|
+
const float DEG = 57.2957795;
|
|
109
|
+
|
|
110
|
+
// minimum deviation of a prism of apex angle 2*half (in degrees in, degrees out)
|
|
111
|
+
float minDev(float n, float sinHalf, float apex){
|
|
112
|
+
float q = n * sinHalf;
|
|
113
|
+
if (q >= 0.9999) return 999.0;
|
|
114
|
+
return 2.0 * asin(q) * DEG - apex;
|
|
115
|
+
}
|
|
116
|
+
// the caustic profile: nothing inside, a sharp edge, a 1/sqrt pile-up, a skirt
|
|
117
|
+
float ringProfile(float th, float d, float aa, float tail){
|
|
118
|
+
if (d > 500.0) return 0.0;
|
|
119
|
+
float x = th - d;
|
|
120
|
+
float e = smoothstep(-aa, aa, x);
|
|
121
|
+
return e * (0.45 / sqrt(max(x, 0.0) + 0.45)) * exp(-max(x, 0.0) / tail);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void main(){
|
|
125
|
+
vec3 d = normalize(vViewPos);
|
|
126
|
+
vec3 sV = normalize(vSunView);
|
|
127
|
+
// view space -> world space (the view matrix rotation is orthonormal)
|
|
128
|
+
vec3 dW = normalize((vec4(d, 0.0) * viewMatrix).xyz);
|
|
129
|
+
vec3 sW = normalize((vec4(sV, 0.0) * viewMatrix).xyz);
|
|
130
|
+
float cd = dot(dW, sW);
|
|
131
|
+
if (cd <= 0.05) discard;
|
|
132
|
+
|
|
133
|
+
// frame around the source: h horizontal (world XZ), vv upward
|
|
134
|
+
vec3 hx = cross(sW, vec3(0.0, 1.0, 0.0));
|
|
135
|
+
float hl = length(hx);
|
|
136
|
+
hx = hl > 0.02 ? hx / hl : normalize(cross(sW, vec3(1.0, 0.0, 0.0)));
|
|
137
|
+
vec3 vv = cross(hx, sW);
|
|
138
|
+
|
|
139
|
+
vec2 t = vec2(dot(dW, hx), dot(dW, vv)) / cd; // gnomonic tangent plane
|
|
140
|
+
float rho = atan(length(t));
|
|
141
|
+
float edgeFade = 1.0 - smoothstep(vHalf * 0.8, vHalf * 0.99, rho);
|
|
142
|
+
if (edgeFade <= 0.001) discard;
|
|
143
|
+
float rhoP = rho / max(vScale, 0.02); // physical angle from the source
|
|
144
|
+
float TH = rhoP * DEG;
|
|
145
|
+
vec2 dir = length(t) > 1e-6 ? normalize(t) : vec2(1.0, 0.0);
|
|
146
|
+
vec3 D3 = normalize(sW * cos(rhoP) + (hx * dir.x + vv * dir.y) * sin(rhoP));
|
|
147
|
+
|
|
148
|
+
float es = asin(clamp(sW.y, -1.0, 1.0));
|
|
149
|
+
float E = asin(clamp(D3.y, -1.0, 1.0));
|
|
150
|
+
vec2 a1 = vec2(D3.x, D3.z);
|
|
151
|
+
vec2 a0 = vec2(sW.x, sW.z);
|
|
152
|
+
float la1 = length(a1), la0 = length(a0);
|
|
153
|
+
a1 = la1 > 1e-4 ? a1 / la1 : vec2(1.0, 0.0);
|
|
154
|
+
a0 = la0 > 1e-4 ? a0 / la0 : vec2(1.0, 0.0);
|
|
155
|
+
float dphi = atan(a1.x * a0.y - a1.y * a0.x, dot(a1, a0)) * DEG;
|
|
156
|
+
float dE = (E - es) * DEG;
|
|
157
|
+
|
|
158
|
+
float aa = max(0.30, fwidth(TH) * 0.9);
|
|
159
|
+
// slow shimmer: crystal swarms drifting through the beam, never flickering
|
|
160
|
+
float shim = 0.86 + 0.3 * vnoise(vec3(dir * 2.1 + vec2(0.0, -uTime * 0.05), uTime * 0.09));
|
|
161
|
+
|
|
162
|
+
// ---- 22 deg halo, dispersed per channel ------------------------------
|
|
163
|
+
float nR = 1.307, nG = 1.3112, nB = 1.317;
|
|
164
|
+
float d22r = minDev(nR, 0.5, 60.0);
|
|
165
|
+
float d22g = minDev(nG, 0.5, 60.0);
|
|
166
|
+
float d22b = minDev(nB, 0.5, 60.0);
|
|
167
|
+
vec3 halo = vec3(ringProfile(TH, d22r, aa, 4.2),
|
|
168
|
+
ringProfile(TH, d22g, aa, 5.0),
|
|
169
|
+
ringProfile(TH, d22b, aa, 7.5)) * 0.8 * shim;
|
|
170
|
+
|
|
171
|
+
// ---- 46 deg halo from the 90 deg prism faces -------------------------
|
|
172
|
+
float s45 = 0.70710678;
|
|
173
|
+
vec3 halo46 = vec3(ringProfile(TH, minDev(nR, s45, 90.0), aa * 1.6, 7.0),
|
|
174
|
+
ringProfile(TH, minDev(nG, s45, 90.0), aa * 1.6, 8.0),
|
|
175
|
+
ringProfile(TH, minDev(nB, s45, 90.0), aa * 1.6, 11.0)) * 0.13 * uOuterHalo * shim;
|
|
176
|
+
|
|
177
|
+
// ---- sun dogs: the same caustic in the horizontal plane, Bravais index
|
|
178
|
+
float ce = max(cos(es), 0.05);
|
|
179
|
+
float se = sin(es);
|
|
180
|
+
float npR = sqrt(max(nR * nR - se * se, 0.0)) / ce;
|
|
181
|
+
float npG = sqrt(max(nG * nG - se * se, 0.0)) / ce;
|
|
182
|
+
float npB = sqrt(max(nB * nB - se * se, 0.0)) / ce;
|
|
183
|
+
float aph = abs(dphi);
|
|
184
|
+
float vert = exp(-dE * dE / (2.0 * 1.25 * 1.25)) * (1.0 - smoothstep(50.0, 61.0, abs(es) * DEG));
|
|
185
|
+
vec3 dogs = vec3(ringProfile(aph, minDev(npR, 0.5, 60.0), aa * 1.2, 5.0),
|
|
186
|
+
ringProfile(aph, minDev(npG, 0.5, 60.0), aa * 1.2, 6.5),
|
|
187
|
+
ringProfile(aph, minDev(npB, 0.5, 60.0), aa * 1.2, 11.0));
|
|
188
|
+
// the outward tail of a sun dog runs white along the parhelic circle
|
|
189
|
+
float tail = smoothstep(-aa, aa, aph - minDev(npG, 0.5, 60.0)) * exp(-max(aph - minDev(npG, 0.5, 60.0), 0.0) / 11.0);
|
|
190
|
+
dogs = (dogs + vec3(tail) * 0.12) * vert * 1.5 * uSunDogs * shim;
|
|
191
|
+
|
|
192
|
+
// ---- parhelic circle: reflection off the vertical faces of plates -----
|
|
193
|
+
float pc = exp(-dE * dE / (2.0 * 0.55 * 0.55)) / (1.0 + aph / 45.0);
|
|
194
|
+
pc *= uParhelicCircle * 0.085 * (0.8 + 0.4 * shim);
|
|
195
|
+
|
|
196
|
+
// ---- light pillar: reflection off the near-horizontal basal faces -----
|
|
197
|
+
float pilW = 1.1 + 0.06 * abs(dE);
|
|
198
|
+
float pil = exp(-pow(dphi * cos(E) / pilW, 2.0)) * (exp(-max(dE, 0.0) / 8.0) + 0.55 * exp(-max(-dE, 0.0) / 6.0));
|
|
199
|
+
pil *= uPillar * 0.5 * shim;
|
|
200
|
+
|
|
201
|
+
// ---- glare around the source -----------------------------------------
|
|
202
|
+
// the glare hugs the source, so it is sized by the source, not by a fixed angle
|
|
203
|
+
float G = vSrc;
|
|
204
|
+
float gl = uGlare * (0.95 * exp(-TH / (0.5 * G)) + 0.3 * exp(-TH / (1.5 * G)) + 0.07 * exp(-TH / (5.0 * G)));
|
|
205
|
+
|
|
206
|
+
vec3 tint = uColor;
|
|
207
|
+
vec3 col = (halo + halo46 + dogs) * mix(vec3(1.0), tint, 0.35)
|
|
208
|
+
+ (pc + pil + gl) * tint;
|
|
209
|
+
col *= edgeFade * uIntensity * uOpacity;
|
|
210
|
+
float lum = max(col.r, max(col.g, col.b));
|
|
211
|
+
if (lum < 0.002) discard;
|
|
212
|
+
// premultiplied: the alpha follows the light, so the quad never shows as a rectangle
|
|
213
|
+
gl_FragColor = vec4(col, min(lum, 1.0));
|
|
214
|
+
}
|
|
215
|
+
`;
|
|
216
|
+
function createUniforms() {
|
|
217
|
+
return {
|
|
218
|
+
uTime: { value: 0 },
|
|
219
|
+
uSpeed: { value: 1 },
|
|
220
|
+
uIntensity: { value: 1 },
|
|
221
|
+
uOpacity: { value: 1 },
|
|
222
|
+
uColor: { value: new THREE.Color('#fff2dd') },
|
|
223
|
+
uHaloScale: { value: 0.35 },
|
|
224
|
+
uSunDogs: { value: 0.8 },
|
|
225
|
+
uOuterHalo: { value: 0.4 },
|
|
226
|
+
uParhelicCircle: { value: 0.35 },
|
|
227
|
+
uPillar: { value: 0.45 },
|
|
228
|
+
uGlare: { value: 0.9 },
|
|
229
|
+
uBound: { value: 1 },
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function applyConfig(u, c, bound, env) {
|
|
233
|
+
u.uSpeed.value = c.speed;
|
|
234
|
+
u.uIntensity.value = c.intensity;
|
|
235
|
+
u.uOpacity.value = c.opacity;
|
|
236
|
+
u.uColor.value.set(c.color);
|
|
237
|
+
u.uHaloScale.value = c.haloScale;
|
|
238
|
+
u.uSunDogs.value = c.sunDogs;
|
|
239
|
+
u.uOuterHalo.value = c.outerHalo;
|
|
240
|
+
u.uParhelicCircle.value = c.parhelicCircle;
|
|
241
|
+
u.uPillar.value = c.pillar;
|
|
242
|
+
u.uGlare.value = c.glare;
|
|
243
|
+
u.uBound.value = bound;
|
|
244
|
+
}
|
|
245
|
+
function build(u, c, bound, env) {
|
|
246
|
+
const mat = new THREE.ShaderMaterial({
|
|
247
|
+
vertexShader: haloVert, fragmentShader: haloFrag, uniforms: u,
|
|
248
|
+
transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, premultipliedAlpha: true, side: THREE.DoubleSide,
|
|
249
|
+
});
|
|
250
|
+
const quad = new THREE.PlaneGeometry(2, 2);
|
|
251
|
+
const sheet = new THREE.Mesh(quad, mat);
|
|
252
|
+
sheet.frustumCulled = false;
|
|
253
|
+
const group = new THREE.Group();
|
|
254
|
+
group.add(sheet);
|
|
255
|
+
return {
|
|
256
|
+
object: group,
|
|
257
|
+
materials: [mat],
|
|
258
|
+
apply(c2) {
|
|
259
|
+
},
|
|
260
|
+
update(dt, camera) {
|
|
261
|
+
u.uTime.value += dt * u.uSpeed.value;
|
|
262
|
+
},
|
|
263
|
+
dispose() {
|
|
264
|
+
quad.dispose();
|
|
265
|
+
mat.dispose();
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/** Defaults for every knob, so an older saved config still renders. */
|
|
270
|
+
const DEFAULTS = {
|
|
271
|
+
intensity: 1,
|
|
272
|
+
speed: 1,
|
|
273
|
+
color: '#fff2dd',
|
|
274
|
+
opacity: 1,
|
|
275
|
+
haloScale: 0.35,
|
|
276
|
+
sunDogs: 0.8,
|
|
277
|
+
outerHalo: 0.4,
|
|
278
|
+
parhelicCircle: 0.35,
|
|
279
|
+
pillar: 0.45,
|
|
280
|
+
glare: 0.9,
|
|
281
|
+
};
|
|
282
|
+
const IceHaloEffect = ({ boundingRadius, config, animations, hasHost = false, onObjectReady, onObjectDispose }) => {
|
|
283
|
+
const rootRef = useRef(null);
|
|
284
|
+
const animCache = useRef({});
|
|
285
|
+
useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
|
|
286
|
+
// a standalone effect gets boundingRadius 1
|
|
287
|
+
const b = boundingRadius > 0 ? boundingRadius : 1;
|
|
288
|
+
const cfg = useMemo(() => ({ ...DEFAULTS, ...config }), [config]);
|
|
289
|
+
const env = useMemo(() => ({ hasHost: hasHost }), [hasHost]);
|
|
290
|
+
// uniforms outlive the objects, so keyframe animations survive a rebuild
|
|
291
|
+
const uniforms = useMemo(() => createUniforms(), []);
|
|
292
|
+
// rebuilt only when the host size or a structural knob changes
|
|
293
|
+
const instance = useMemo(() => build(uniforms, { ...DEFAULTS, ...config }, b, env), [uniforms, b, env]);
|
|
294
|
+
useEffect(() => () => instance.dispose(), [instance]);
|
|
295
|
+
useLayoutEffect(() => {
|
|
296
|
+
applyConfig(uniforms, cfg, b, env);
|
|
297
|
+
instance.apply(cfg);
|
|
298
|
+
}, [instance, uniforms, cfg, b, env]);
|
|
299
|
+
useFrame((state, delta) => {
|
|
300
|
+
instance.update(Math.min(delta, 0.1), state.camera);
|
|
301
|
+
if (animations?.length)
|
|
302
|
+
applyGenerativeAnimations(instance.materials, animations, animCache.current, Date.now(), false);
|
|
303
|
+
});
|
|
304
|
+
return (_jsx("group", { ref: rootRef, children: _jsx("primitive", { object: instance.object }) }));
|
|
305
|
+
};
|
|
306
|
+
export default IceHaloEffect;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AnimationOptions, LichtenbergConfig } from '@3driseai/3drise-core';
|
|
3
|
+
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
4
|
+
export interface LichtenbergEffectProps extends ObjectReadyProps {
|
|
5
|
+
boundingRadius: number;
|
|
6
|
+
config: LichtenbergConfig;
|
|
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 LichtenbergEffect: React.FC<LichtenbergEffectProps>;
|
|
12
|
+
export default LichtenbergEffect;
|
|
13
|
+
//# sourceMappingURL=LichtenbergEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LichtenbergEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/LichtenbergEffect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAG3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAChC,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AA6cD,QAAA,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA+BvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|