@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
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AnimationOptions, SmokePlumeConfig } from '@3driseai/3drise-core';
|
|
3
3
|
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
4
|
-
interface SmokePlumeEffectProps extends ObjectReadyProps {
|
|
4
|
+
export interface SmokePlumeEffectProps extends ObjectReadyProps {
|
|
5
5
|
boundingRadius: number;
|
|
6
6
|
config: SmokePlumeConfig;
|
|
7
7
|
animations?: AnimationOptions[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmokePlumeEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/SmokePlumeEffect.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SmokePlumeEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/SmokePlumeEffect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAG3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AA4JD,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+DrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,144 +1,208 @@
|
|
|
1
1
|
import { jsx as _jsx } 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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
/**
|
|
8
|
+
* A buoyant smoke plume rising from the top of the host.
|
|
9
|
+
*
|
|
10
|
+
* Puffs follow Morton-Taylor-Turner plume theory: height grows as t^(3/4) and
|
|
11
|
+
* the width grows linearly with height. A divergence-free curl field makes the
|
|
12
|
+
* billows, a crosswind bends the column as z^2, and an optional hot base glows
|
|
13
|
+
* like firelight. Each puff is lit from above and premultiplied, so dense
|
|
14
|
+
* smoke darkens what is behind it.
|
|
15
|
+
*
|
|
16
|
+
* Everything moves in the vertex shader; the CPU only uploads seeds once.
|
|
17
|
+
*/
|
|
18
|
+
const PRE_NORMAL = { transparent: true, depthWrite: false, blending: THREE.NormalBlending, premultipliedAlpha: true };
|
|
19
|
+
function mulberry32(seed) {
|
|
20
|
+
return () => {
|
|
21
|
+
seed |= 0;
|
|
22
|
+
seed = (seed + 0x6d2b79f5) | 0;
|
|
23
|
+
let r = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
|
24
|
+
r = (r + Math.imul(r ^ (r >>> 7), 61 | r)) ^ r;
|
|
25
|
+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function buildPlumeParticles(count) {
|
|
29
|
+
const n = Math.round(Math.min(Math.max(count, 40), 600));
|
|
30
|
+
const rand = mulberry32(17);
|
|
31
|
+
const aT = new Float32Array(n);
|
|
32
|
+
const aSeed = new Float32Array(n * 3);
|
|
33
|
+
for (let i = 0; i < n; i++) {
|
|
34
|
+
aT[i] = i / n;
|
|
35
|
+
// gaussian-ish disc: the plume is densest on its axis
|
|
36
|
+
const r = Math.sqrt(-2 * Math.log(1 - rand() * 0.95)) * 0.45;
|
|
37
|
+
const a = rand() * Math.PI * 2;
|
|
38
|
+
aSeed[i * 3] = Math.cos(a) * r;
|
|
39
|
+
aSeed[i * 3 + 1] = Math.sin(a) * r;
|
|
40
|
+
aSeed[i * 3 + 2] = rand();
|
|
41
|
+
}
|
|
42
|
+
return { count: n, aT, aSeed };
|
|
43
|
+
}
|
|
44
|
+
const plumeVert = /* glsl */ `
|
|
45
|
+
attribute float aT;
|
|
46
|
+
attribute vec3 aSeed; // x,y: base disc position (-1..1), z: random
|
|
47
|
+
uniform float uTime;
|
|
19
48
|
uniform float uHeight;
|
|
20
49
|
uniform float uSpread;
|
|
21
|
-
uniform float
|
|
22
|
-
uniform float
|
|
23
|
-
|
|
24
|
-
|
|
50
|
+
uniform float uTurbulence;
|
|
51
|
+
uniform float uWind;
|
|
52
|
+
uniform float uBound;
|
|
53
|
+
uniform float uIntensity;
|
|
54
|
+
varying float vLife;
|
|
25
55
|
varying float vAlpha;
|
|
56
|
+
varying float vRot;
|
|
57
|
+
varying float vSeed;
|
|
58
|
+
varying vec3 vLight;
|
|
26
59
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
float z = aBase.y * expand * uSpread;
|
|
36
|
-
|
|
37
|
-
// Turbulent horizontal drift — two layers of sine turbulence
|
|
38
|
-
float t1 = sin(life * 4.2 + aPhase) * uTurb * uSpread * life * 0.9;
|
|
39
|
-
float t2 = sin(life * 7.1 + aPhase * 1.7 + 1.3) * uTurb * uSpread * life * 0.4;
|
|
40
|
-
float t3 = cos(life * 3.5 - aPhase * 0.8) * uTurb * uSpread * life * 0.3;
|
|
41
|
-
x += t1 + t2;
|
|
42
|
-
z += t3 + t2 * 0.5;
|
|
43
|
-
|
|
44
|
-
float y = life * uHeight - uHeight * 0.45;
|
|
45
|
-
|
|
46
|
-
// Particle grows from tiny to large, then fades to nothing
|
|
47
|
-
float growFade = smoothstep(0.0, 0.15, life) * smoothstep(1.0, 0.6, life);
|
|
48
|
-
float sz = aSize * uSizeScale * growFade;
|
|
60
|
+
// Divergence-free swirl: the curl of A = (sin(k1 y), sin(k2 z), sin(k3 x))
|
|
61
|
+
// is (-k2 cos(k2 z), -k3 cos(k3 x), -k1 cos(k1 y)), summed over two octaves.
|
|
62
|
+
vec3 curlField(vec3 p, float t){
|
|
63
|
+
vec3 c = -vec3(1.7 * cos(1.7 * p.z + t * 0.6), 1.3 * cos(1.3 * p.x - t * 0.4), 1.1 * cos(1.1 * p.y + t * 0.5));
|
|
64
|
+
vec3 q = vec3(p.y, p.z, p.x) * 2.3 + 4.0;
|
|
65
|
+
c += -0.5 * vec3(3.1 * cos(3.1 * q.z - t), 2.7 * cos(2.7 * q.x + t * 0.8), 2.9 * cos(2.9 * q.y - t * 0.7));
|
|
66
|
+
return c * 0.35;
|
|
67
|
+
}
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
void main(){
|
|
70
|
+
float life = fract(aT + uTime * 0.11);
|
|
71
|
+
vLife = life;
|
|
72
|
+
// Morton-Taylor-Turner point-source plume: rise z ~ t^(3/4),
|
|
73
|
+
// width grows linearly with height (constant entrainment).
|
|
74
|
+
float Hs = uHeight * uBound;
|
|
75
|
+
float Ss = uSpread * uBound;
|
|
76
|
+
float z = pow(life, 0.75) * Hs;
|
|
77
|
+
float w = Ss * 0.35 + 0.24 * z;
|
|
78
|
+
vec3 base = vec3(aSeed.x * w, 0.0, aSeed.y * w);
|
|
79
|
+
// the plume leaves from the top of the object
|
|
80
|
+
vec3 pos = base + vec3(0.0, z + uBound * 0.6, 0.0);
|
|
81
|
+
pos += curlField(vec3(aSeed.xy * 2.0, z / max(Hs, 1e-3) * 3.0), uTime * 0.5 + aSeed.z * 6.0) * uTurbulence * w * 1.6;
|
|
82
|
+
// a crosswind bends the plume parabolically
|
|
83
|
+
pos.x += uWind * z * z / max(Hs, 1e-3);
|
|
52
84
|
|
|
53
|
-
vec4 mv = modelViewMatrix * vec4(
|
|
54
|
-
|
|
55
|
-
|
|
85
|
+
vec4 mv = modelViewMatrix * vec4(pos, 1.0);
|
|
86
|
+
float grow = smoothstep(0.0, 0.08, life);
|
|
87
|
+
float size = (0.45 * Ss + 0.5 * w) * grow;
|
|
88
|
+
// mass spreads over a growing cross-section, so density thins out
|
|
89
|
+
float thin = pow(clamp(Ss * 0.35 / max(w, 1e-3), 0.0, 1.0), 0.9);
|
|
90
|
+
vAlpha = grow * (1.0 - smoothstep(0.7, 1.0, life)) * (0.35 + 0.65 * thin);
|
|
91
|
+
vRot = aSeed.z * 6.2832 + life * (aSeed.z - 0.5) * 2.0;
|
|
92
|
+
vSeed = aSeed.z;
|
|
93
|
+
vLight = normalize((viewMatrix * vec4(0.35, 1.0, 0.25, 0.0)).xyz);
|
|
94
|
+
gl_PointSize = size * uIntensity * 900.0 / max(-mv.z, 1e-3);
|
|
95
|
+
gl_Position = projectionMatrix * mv;
|
|
56
96
|
}
|
|
57
97
|
`;
|
|
58
|
-
const
|
|
98
|
+
const plumeFrag = /* glsl */ `
|
|
59
99
|
uniform vec3 uSmokeColor;
|
|
60
100
|
uniform float uOpacity;
|
|
101
|
+
uniform float uHeat;
|
|
61
102
|
varying float vLife;
|
|
62
103
|
varying float vAlpha;
|
|
104
|
+
varying float vRot;
|
|
105
|
+
varying float vSeed;
|
|
106
|
+
varying vec3 vLight;
|
|
63
107
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
108
|
+
|
|
109
|
+
float hash12(vec2 p){
|
|
110
|
+
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
|
111
|
+
p3 += dot(p3, p3.yzx + 33.33);
|
|
112
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
113
|
+
}
|
|
114
|
+
float vnoise2(vec2 p){
|
|
115
|
+
vec2 i = floor(p);
|
|
116
|
+
vec2 f = fract(p);
|
|
117
|
+
f = f * f * (3.0 - 2.0 * f);
|
|
118
|
+
return mix(mix(hash12(i), hash12(i + vec2(1.0, 0.0)), f.x),
|
|
119
|
+
mix(hash12(i + vec2(0.0, 1.0)), hash12(i + vec2(1.0, 1.0)), f.x), f.y);
|
|
120
|
+
}
|
|
121
|
+
float fbm2(vec2 p){
|
|
122
|
+
float a = 0.5, s = 0.0;
|
|
123
|
+
for (int i = 0; i < 4; i++){
|
|
124
|
+
s += a * vnoise2(p);
|
|
125
|
+
p = mat2(1.6, 1.2, -1.2, 1.6) * p;
|
|
126
|
+
a *= 0.5;
|
|
127
|
+
}
|
|
128
|
+
return s;
|
|
129
|
+
}
|
|
73
130
|
|
|
74
|
-
// Slightly darken as smoke ages (hot white → grey → dark)
|
|
75
|
-
float darkening = 1.0 - vLife * 0.45;
|
|
76
|
-
vec3 col = uSmokeColor * darkening;
|
|
77
131
|
|
|
78
|
-
|
|
132
|
+
void main(){
|
|
133
|
+
vec2 c = gl_PointCoord * 2.0 - 1.0;
|
|
134
|
+
c.y = -c.y;
|
|
135
|
+
float cr = cos(vRot), sr = sin(vRot);
|
|
136
|
+
vec2 rc = mat2(cr, -sr, sr, cr) * c;
|
|
137
|
+
float r = length(c);
|
|
138
|
+
if (r > 1.0) discard;
|
|
139
|
+
// billows: the silhouette is eroded by fBm, so no two puffs match
|
|
140
|
+
float b = fbm2(rc * 1.7 + vSeed * 31.0 + vLife * 0.8);
|
|
141
|
+
float shape = 1.0 - smoothstep(0.35, 1.0, r + (b - 0.5) * 0.6);
|
|
142
|
+
if (shape < 0.01) discard;
|
|
143
|
+
// treat the puff as a soft sphere: wrap lighting from above plus a
|
|
144
|
+
// bright rim on the side facing the light
|
|
145
|
+
vec3 n = normalize(vec3(c * 0.9, sqrt(max(1.0 - r * r, 0.0))));
|
|
146
|
+
float diff = 0.5 + 0.5 * dot(n, vLight);
|
|
147
|
+
float rim = pow(1.0 - n.z, 2.0) * max(dot(normalize(vec3(c, 0.0) + 1e-5), vLight.xyz), 0.0) * 0.5;
|
|
148
|
+
vec3 col = uSmokeColor * (0.25 + 0.85 * diff) * (0.75 + 0.5 * b) + vec3(rim) * uSmokeColor;
|
|
149
|
+
// hot smoke glows near the source: a blackbody-like ramp that cools fast
|
|
150
|
+
float hot = uHeat * exp(-vLife * 7.0);
|
|
151
|
+
col += mix(vec3(1.0, 0.25, 0.04), vec3(1.0, 0.75, 0.35), hot) * hot * 1.6;
|
|
152
|
+
float a = shape * vAlpha * uOpacity;
|
|
153
|
+
gl_FragColor = vec4(col * a, a);
|
|
79
154
|
}
|
|
80
155
|
`;
|
|
81
156
|
const SmokePlumeEffect = ({ boundingRadius, config, animations, onObjectReady, onObjectDispose }) => {
|
|
82
|
-
const { particleCount, height, spread, smokeColor, turbulence,
|
|
83
|
-
const startValuesCacheRef = useRef({});
|
|
157
|
+
const { intensity = 1, speed = 1, opacity = 0.6, particleCount = 180, height = 2, spread = 0.5, smokeColor = '#b4b4b8', turbulence = 0.5, heat = 0, wind = 0, } = config;
|
|
84
158
|
const rootRef = useRef(null);
|
|
159
|
+
const animCache = useRef({});
|
|
85
160
|
useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
161
|
+
// a standalone effect gets boundingRadius 1; guard against an empty host
|
|
162
|
+
const b = boundingRadius > 0 ? boundingRadius : 1;
|
|
163
|
+
const uniforms = useMemo(() => ({
|
|
164
|
+
uTime: { value: 0 },
|
|
165
|
+
uSpeed: { value: 1 },
|
|
166
|
+
uBound: { value: 1 },
|
|
167
|
+
uIntensity: { value: 1 },
|
|
168
|
+
uOpacity: { value: 1 },
|
|
169
|
+
uHeight: { value: 2 },
|
|
170
|
+
uSpread: { value: 0.5 },
|
|
171
|
+
uTurbulence: { value: 0.5 },
|
|
172
|
+
uWind: { value: 0 },
|
|
173
|
+
uHeat: { value: 0 },
|
|
174
|
+
uSmokeColor: { value: new THREE.Color() },
|
|
175
|
+
}), []);
|
|
176
|
+
const materials = useMemo(() => [
|
|
177
|
+
new THREE.ShaderMaterial({ vertexShader: plumeVert, fragmentShader: plumeFrag, uniforms, ...PRE_NORMAL }),
|
|
178
|
+
], [uniforms]);
|
|
179
|
+
useEffect(() => () => materials.forEach((m) => m.dispose()), [materials]);
|
|
180
|
+
const geometry = useMemo(() => {
|
|
181
|
+
const p = buildPlumeParticles(particleCount);
|
|
106
182
|
const g = new THREE.BufferGeometry();
|
|
107
|
-
g.setAttribute('position', new THREE.BufferAttribute(new Float32Array(
|
|
108
|
-
g.setAttribute('aT', new THREE.BufferAttribute(aT, 1));
|
|
109
|
-
g.setAttribute('
|
|
110
|
-
g
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
depthWrite: false,
|
|
130
|
-
// Normal blending (not additive) — smoke should look opaque/grey, not glowy
|
|
131
|
-
blending: THREE.NormalBlending,
|
|
132
|
-
});
|
|
133
|
-
return { geo: g, mat: m };
|
|
134
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
135
|
-
}, [particleCount, h, s, smokeColor, turbulence, opacity, speed, intensity]);
|
|
136
|
-
useFrame((state) => {
|
|
137
|
-
mat.uniforms.u_time.value = state.clock.getElapsedTime();
|
|
138
|
-
if (animations?.length) {
|
|
139
|
-
applyGenerativeAnimations([mat], animations, startValuesCacheRef.current, Date.now(), false);
|
|
140
|
-
}
|
|
183
|
+
g.setAttribute('position', new THREE.BufferAttribute(new Float32Array(p.count * 3), 3));
|
|
184
|
+
g.setAttribute('aT', new THREE.BufferAttribute(p.aT, 1));
|
|
185
|
+
g.setAttribute('aSeed', new THREE.BufferAttribute(p.aSeed, 3));
|
|
186
|
+
return g;
|
|
187
|
+
}, [particleCount]);
|
|
188
|
+
useEffect(() => () => geometry.dispose(), [geometry]);
|
|
189
|
+
useLayoutEffect(() => {
|
|
190
|
+
uniforms.uSpeed.value = speed;
|
|
191
|
+
uniforms.uBound.value = b;
|
|
192
|
+
uniforms.uIntensity.value = intensity;
|
|
193
|
+
uniforms.uOpacity.value = opacity;
|
|
194
|
+
uniforms.uHeight.value = height;
|
|
195
|
+
uniforms.uSpread.value = spread;
|
|
196
|
+
uniforms.uTurbulence.value = turbulence;
|
|
197
|
+
uniforms.uWind.value = wind;
|
|
198
|
+
uniforms.uHeat.value = heat;
|
|
199
|
+
uniforms.uSmokeColor.value.set(smokeColor);
|
|
200
|
+
}, [uniforms, speed, b, intensity, opacity, height, spread, turbulence, wind, heat, smokeColor]);
|
|
201
|
+
useFrame((_, delta) => {
|
|
202
|
+
uniforms.uTime.value += delta * uniforms.uSpeed.value;
|
|
203
|
+
if (animations?.length)
|
|
204
|
+
applyGenerativeAnimations(materials, animations, animCache.current, Date.now(), false);
|
|
141
205
|
});
|
|
142
|
-
return _jsx("
|
|
206
|
+
return (_jsx("group", { ref: rootRef, children: _jsx("points", { geometry: geometry, material: materials[0], frustumCulled: false }) }));
|
|
143
207
|
};
|
|
144
208
|
export default SmokePlumeEffect;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import type {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AnimationOptions, SmokeRingConfig } from '@3driseai/3drise-core';
|
|
3
3
|
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
4
|
-
interface SmokeRingEffectProps extends ObjectReadyProps {
|
|
4
|
+
export interface SmokeRingEffectProps extends ObjectReadyProps {
|
|
5
5
|
boundingRadius: number;
|
|
6
6
|
config: SmokeRingConfig;
|
|
7
7
|
animations?: AnimationOptions[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmokeRingEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/SmokeRingEffect.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SmokeRingEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/SmokeRingEffect.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;CACnC;AAoND,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+EnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|