@3driseai/3drise-viewer 0.1.10 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CloudsGenerator.d.ts.map +1 -1
- package/dist/components/CloudsGenerator.js +3 -1
- package/dist/components/effects/DataStreamEffect.d.ts.map +1 -1
- package/dist/components/effects/DataStreamEffect.js +14 -8
- package/dist/components/effects/NeuralNetworkEffect.d.ts.map +1 -1
- package/dist/components/effects/NeuralNetworkEffect.js +11 -9
- package/dist/components/volumetricClouds/Cirrus.d.ts +4 -0
- package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -1
- package/dist/components/volumetricClouds/Cirrus.js +4 -0
- package/dist/components/volumetricClouds/Cumulonimbus.js +2 -2
- package/dist/components/volumetricClouds/Cumulus.js +2 -2
- package/dist/components/volumetricClouds/Stratocumulus.js +2 -2
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +4 -1
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
- package/dist/components/volumetricClouds/VolumetricCloudsPass.js +55 -4
- package/dist/components/volumetricClouds/types.d.ts +3 -1
- package/dist/components/volumetricClouds/types.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useCloudLive.d.ts +1 -0
- package/dist/hooks/useCloudLive.d.ts.map +1 -1
- package/dist/hooks/useCloudLive.js +2 -1
- package/dist/hooks/useThunder.d.ts +37 -0
- package/dist/hooks/useThunder.d.ts.map +1 -0
- package/dist/hooks/useThunder.js +145 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/shaders/clouds/CloudShadowMaterial.d.ts +52 -0
- package/dist/shaders/clouds/CloudShadowMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/CloudShadowMaterial.js +110 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +10 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudVolumeMaterial.js +38 -2
- package/dist/shaders/glsl/cloudCore.glsl.d.ts +3 -3
- package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -1
- package/dist/shaders/glsl/cloudCore.glsl.js +81 -9
- package/dist/shaders/glsl/cloudShadow.glsl.d.ts +15 -0
- package/dist/shaders/glsl/cloudShadow.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/cloudShadow.glsl.js +35 -0
- package/dist/types/cloudConfigs.d.ts +66 -0
- package/dist/types/cloudConfigs.d.ts.map +1 -1
- package/dist/types/cloudConfigs.js +108 -51
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/utils/cloudShadowMap.d.ts +43 -0
- package/dist/utils/cloudShadowMap.d.ts.map +1 -0
- package/dist/utils/cloudShadowMap.js +60 -0
- package/dist/utils/cloudUniforms.d.ts +6 -1
- package/dist/utils/cloudUniforms.d.ts.map +1 -1
- package/dist/utils/cloudUniforms.js +18 -0
- package/dist/utils/gpuProfiler.d.ts +33 -0
- package/dist/utils/gpuProfiler.d.ts.map +1 -0
- package/dist/utils/gpuProfiler.js +115 -0
- package/dist/utils/handleCloudsAnimations.d.ts +12 -1
- package/dist/utils/handleCloudsAnimations.d.ts.map +1 -1
- package/dist/utils/handleCloudsAnimations.js +13 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudsGenerator.d.ts","sourceRoot":"","sources":["../../src/components/CloudsGenerator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAOtE,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC1D;sFACkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"CloudsGenerator.d.ts","sourceRoot":"","sources":["../../src/components/CloudsGenerator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAOtE,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC1D;sFACkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA8CnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
|
-
import { CLOUD_DECK_DEFAULTS, normalizeCirrus, normalizeCloudDeck, normalizeCloudQuality } from '../types/cloudConfigs.js';
|
|
3
|
+
import { CLOUD_DECK_DEFAULTS, normalizeCirrus, normalizeCloudDeck, normalizeCloudQuality, normalizeThunder } from '../types/cloudConfigs.js';
|
|
4
4
|
import Cumulus from './volumetricClouds/Cumulus.js';
|
|
5
5
|
import Stratocumulus from './volumetricClouds/Stratocumulus.js';
|
|
6
6
|
import Cumulonimbus from './volumetricClouds/Cumulonimbus.js';
|
|
@@ -25,6 +25,7 @@ const CloudsGenerator = ({ settings, skySettings, timeSettings, sunIntensity, on
|
|
|
25
25
|
const deck = useMemo(() => normalizeCloudDeck(settings?.config), [settings?.config]);
|
|
26
26
|
const cirrus = useMemo(() => normalizeCirrus(settings?.cirrus), [settings?.cirrus]);
|
|
27
27
|
const quality = useMemo(() => normalizeCloudQuality(settings?.quality), [settings?.quality]);
|
|
28
|
+
const thunder = useMemo(() => normalizeThunder(settings?.thunder), [settings?.thunder]);
|
|
28
29
|
const deckOn = !!deck?.enabled;
|
|
29
30
|
const cirrusOn = !!cirrus?.enabled;
|
|
30
31
|
// The cirrus-only branch ignores the deck entirely (it passes deck={null} to the
|
|
@@ -37,6 +38,7 @@ const CloudsGenerator = ({ settings, skySettings, timeSettings, sunIntensity, on
|
|
|
37
38
|
deck: deckOrDefault,
|
|
38
39
|
cirrus: cirrusOn ? cirrus : null,
|
|
39
40
|
quality,
|
|
41
|
+
thunder,
|
|
40
42
|
skySettings,
|
|
41
43
|
timeSettings,
|
|
42
44
|
sunIntensity,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataStreamEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/DataStreamEffect.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"DataStreamEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/DataStreamEffect.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAuFD,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAoErD,CAAC;AACF,eAAe,gBAAgB,CAAC"}
|
|
@@ -18,17 +18,19 @@ const vertexShader = /* glsl */ `
|
|
|
18
18
|
uniform float uHeight;
|
|
19
19
|
uniform float uPointSize;
|
|
20
20
|
uniform float uIntensity;
|
|
21
|
+
uniform vec3 uColdColor;
|
|
22
|
+
uniform vec3 uMidColor;
|
|
23
|
+
uniform vec3 uHotColor;
|
|
24
|
+
uniform vec3 uTintColor;
|
|
21
25
|
|
|
22
26
|
varying float vAlpha;
|
|
23
27
|
varying vec3 vColor;
|
|
24
28
|
|
|
25
|
-
//
|
|
29
|
+
// Four-stop gradient: cold -> mid -> hot -> tint (config.color)
|
|
26
30
|
vec3 palette(float t) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (t < 0.5) return mix(cold, mid, t * 2.0);
|
|
31
|
-
else return mix(mid, hot, (t - 0.5) * 2.0);
|
|
31
|
+
if (t < 0.333) return mix(uColdColor, uMidColor, t * 3.0);
|
|
32
|
+
else if (t < 0.666) return mix(uMidColor, uHotColor, (t - 0.333) * 3.0);
|
|
33
|
+
else return mix(uHotColor, uTintColor, (t - 0.666) * 3.0);
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
void main() {
|
|
@@ -87,7 +89,7 @@ const fragmentShader = /* glsl */ `
|
|
|
87
89
|
}
|
|
88
90
|
`;
|
|
89
91
|
const DataStreamEffect = ({ boundingRadius, config, animations, onObjectReady, onObjectDispose }) => {
|
|
90
|
-
const { particleCount, spiralTurns, streamRadius, inward, particleSize, opacity, speed, intensity } = config;
|
|
92
|
+
const { particleCount, spiralTurns, streamRadius, inward, particleSize, opacity, speed, intensity, color = '#ffffff', coldColor = '#0d26e6', midColor = '#00d9ff', hotColor = '#ffeb8c', } = config;
|
|
91
93
|
const startValuesCacheRef = useRef({});
|
|
92
94
|
const rootRef = useRef(null);
|
|
93
95
|
useObjectReady(rootRef, config, onObjectReady, onObjectDispose);
|
|
@@ -123,13 +125,17 @@ const DataStreamEffect = ({ boundingRadius, config, animations, onObjectReady, o
|
|
|
123
125
|
uPointSize: { value: particleSize * 80 },
|
|
124
126
|
uIntensity: { value: intensity },
|
|
125
127
|
uOpacity: { value: opacity },
|
|
128
|
+
uColdColor: { value: new THREE.Color(coldColor) },
|
|
129
|
+
uMidColor: { value: new THREE.Color(midColor) },
|
|
130
|
+
uHotColor: { value: new THREE.Color(hotColor) },
|
|
131
|
+
uTintColor: { value: new THREE.Color(color) },
|
|
126
132
|
},
|
|
127
133
|
transparent: true,
|
|
128
134
|
depthWrite: false,
|
|
129
135
|
blending: THREE.AdditiveBlending,
|
|
130
136
|
});
|
|
131
137
|
return { geometry: geo, material: mat };
|
|
132
|
-
}, [particleCount, spiralTurns, r, h, inward, particleSize, intensity, speed, opacity]);
|
|
138
|
+
}, [particleCount, spiralTurns, r, h, inward, particleSize, intensity, speed, opacity, coldColor, midColor, hotColor, color]);
|
|
133
139
|
useFrame((state) => {
|
|
134
140
|
material.uniforms.u_time.value = state.clock.getElapsedTime();
|
|
135
141
|
if (animations?.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NeuralNetworkEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/NeuralNetworkEffect.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,UAAU,wBAAyB,SAAQ,gBAAgB;IACvD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"NeuralNetworkEffect.d.ts","sourceRoot":"","sources":["../../../src/components/effects/NeuralNetworkEffect.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,UAAU,wBAAyB,SAAQ,gBAAgB;IACvD,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AA+BD,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA4J3D,CAAC;AACF,eAAe,mBAAmB,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { useFrame } from '@react-three/fiber';
|
|
|
4
4
|
import * as THREE from 'three';
|
|
5
5
|
import { applyGenerativeAnimations } from '../../utils/handleGenerativeEffectsAnimations.js';
|
|
6
6
|
import { useObjectReady } from '../../hooks/useObjectReady.js';
|
|
7
|
-
//
|
|
7
|
+
// Tight point sprites for electrical signals moving through the connections.
|
|
8
8
|
const pulseVert = /* glsl */ `
|
|
9
9
|
attribute float aBright;
|
|
10
10
|
uniform float uSize;
|
|
@@ -13,7 +13,7 @@ const pulseVert = /* glsl */ `
|
|
|
13
13
|
vB = aBright;
|
|
14
14
|
if (vB < 0.01) { gl_PointSize = 0.0; gl_Position = vec4(0); return; }
|
|
15
15
|
vec4 mv = modelViewMatrix * vec4(position, 1.0);
|
|
16
|
-
gl_PointSize = uSize * vB * (200.0 / -mv.z);
|
|
16
|
+
gl_PointSize = uSize * (0.75 + vB * 0.25) * (200.0 / -mv.z);
|
|
17
17
|
gl_Position = projectionMatrix * mv;
|
|
18
18
|
}
|
|
19
19
|
`;
|
|
@@ -23,10 +23,12 @@ const pulseFrag = /* glsl */ `
|
|
|
23
23
|
varying float vB;
|
|
24
24
|
void main() {
|
|
25
25
|
if (vB < 0.01) discard;
|
|
26
|
-
vec2
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
vec2 c = gl_PointCoord - 0.5;
|
|
27
|
+
float radius = length(c);
|
|
28
|
+
if (radius > 0.5) discard;
|
|
29
|
+
float core = smoothstep(0.24, 0.0, radius);
|
|
30
|
+
float halo = smoothstep(0.5, 0.12, radius) * 0.2;
|
|
31
|
+
gl_FragColor = vec4(uColor, (core + halo) * vB * uOpacity);
|
|
30
32
|
}
|
|
31
33
|
`;
|
|
32
34
|
const MAX_PULSES = 4;
|
|
@@ -105,7 +107,7 @@ const NeuralNetworkEffect = ({ boundingRadius, config, animations, onObjectReady
|
|
|
105
107
|
const pulseMat = new THREE.ShaderMaterial({
|
|
106
108
|
vertexShader: pulseVert, fragmentShader: pulseFrag,
|
|
107
109
|
uniforms: {
|
|
108
|
-
uSize: { value:
|
|
110
|
+
uSize: { value: 7 * intensity },
|
|
109
111
|
uColor: { value: new THREE.Vector3(pc.r, pc.g, pc.b) },
|
|
110
112
|
uOpacity: { value: opacity },
|
|
111
113
|
},
|
|
@@ -176,11 +178,11 @@ const NeuralNetworkEffect = ({ boundingRadius, config, animations, onObjectReady
|
|
|
176
178
|
}
|
|
177
179
|
const pos = curPos[p.fromIdx].clone().lerp(curPos[p.toIdx], p.progress);
|
|
178
180
|
ptPos.setXYZ(pi, pos.x, pos.y, pos.z);
|
|
179
|
-
ptBright.setX(pi, 0.
|
|
181
|
+
ptBright.setX(pi, 0.75 + 0.25 * Math.sin(p.progress * Math.PI * 3.0));
|
|
180
182
|
});
|
|
181
183
|
ptPos.needsUpdate = true;
|
|
182
184
|
ptBright.needsUpdate = true;
|
|
183
|
-
pulseMat.uniforms.uSize.value =
|
|
185
|
+
pulseMat.uniforms.uSize.value = 7 * intensity;
|
|
184
186
|
if (animations?.length) {
|
|
185
187
|
applyGenerativeAnimations([pulseMat], animations, startValuesCacheRef.current, Date.now(), false);
|
|
186
188
|
}
|
|
@@ -8,6 +8,10 @@ import type { CloudLayerProps } from './types';
|
|
|
8
8
|
* case where the deck is switched off entirely, so the deck march is skipped and
|
|
9
9
|
* only the three-sample ice pass runs. That is a fraction of the cost of any
|
|
10
10
|
* volumetric type, which is why a clear-with-cirrus sky is close to free.
|
|
11
|
+
*
|
|
12
|
+
* No thunder here, deliberately: a bolt needs a deck to sit inside and a volume to
|
|
13
|
+
* light. An ice sheet has neither, so the flash would have nowhere to originate and
|
|
14
|
+
* nothing to scatter through.
|
|
11
15
|
*/
|
|
12
16
|
declare const Cirrus: React.FC<CloudLayerProps>;
|
|
13
17
|
export default Cirrus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cirrus.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/Cirrus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C
|
|
1
|
+
{"version":3,"file":"Cirrus.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/Cirrus.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAErC,CAAC;AACF,eAAe,MAAM,CAAC"}
|
|
@@ -8,6 +8,10 @@ import VolumetricCloudsPass from './VolumetricCloudsPass.js';
|
|
|
8
8
|
* case where the deck is switched off entirely, so the deck march is skipped and
|
|
9
9
|
* only the three-sample ice pass runs. That is a fraction of the cost of any
|
|
10
10
|
* volumetric type, which is why a clear-with-cirrus sky is close to free.
|
|
11
|
+
*
|
|
12
|
+
* No thunder here, deliberately: a bolt needs a deck to sit inside and a volume to
|
|
13
|
+
* light. An ice sheet has neither, so the flash would have nowhere to originate and
|
|
14
|
+
* nothing to scatter through.
|
|
11
15
|
*/
|
|
12
16
|
const Cirrus = ({ cirrus, quality, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => (_jsx(VolumetricCloudsPass, { deck: null, cirrus: cirrus, quality: quality, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
13
17
|
export default Cirrus;
|
|
@@ -13,8 +13,8 @@ import VolumetricCloudsPass from './VolumetricCloudsPass.js';
|
|
|
13
13
|
* Cost scales with depth, since the fine step is derived from it, so a shallow step
|
|
14
14
|
* budget on a 9 km tower gives kilometre steps and loses the structure. Floored here.
|
|
15
15
|
*/
|
|
16
|
-
const Cumulonimbus = ({ deck, cirrus, quality, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
16
|
+
const Cumulonimbus = ({ deck, cirrus, quality, thunder, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
17
17
|
const resolvedQuality = useMemo(() => ({ ...quality, steps: Math.max(quality.steps, 96) }), [quality]);
|
|
18
|
-
return (_jsx(VolumetricCloudsPass, { deck: deck, cirrus: cirrus, quality: resolvedQuality, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
18
|
+
return (_jsx(VolumetricCloudsPass, { deck: deck, cirrus: cirrus, quality: resolvedQuality, thunder: thunder, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
19
19
|
};
|
|
20
20
|
export default Cumulonimbus;
|
|
@@ -10,8 +10,8 @@ import VolumetricCloudsPass from './VolumetricCloudsPass.js';
|
|
|
10
10
|
* inside the shader anyway, so leaving a stale value in the config would do nothing
|
|
11
11
|
* visible while making the panel read as though it should.
|
|
12
12
|
*/
|
|
13
|
-
const Cumulus = ({ deck, cirrus, quality, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
13
|
+
const Cumulus = ({ deck, cirrus, quality, thunder, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
14
14
|
const resolved = useMemo(() => ({ ...deck, anvil: 0, precipitation: 0 }), [deck]);
|
|
15
|
-
return (_jsx(VolumetricCloudsPass, { deck: resolved, cirrus: cirrus, quality: quality, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
15
|
+
return (_jsx(VolumetricCloudsPass, { deck: resolved, cirrus: cirrus, quality: quality, thunder: thunder, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
16
16
|
};
|
|
17
17
|
export default Cumulus;
|
|
@@ -8,9 +8,9 @@ import VolumetricCloudsPass from './VolumetricCloudsPass.js';
|
|
|
8
8
|
* small and a large step budget is wasted; it is capped here. Anvil and
|
|
9
9
|
* precipitation are off for the same reason as cumulus.
|
|
10
10
|
*/
|
|
11
|
-
const Stratocumulus = ({ deck, cirrus, quality, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
11
|
+
const Stratocumulus = ({ deck, cirrus, quality, thunder, skySettings, timeSettings, sunIntensity, animations, mouseMove, id, onObjectReady, onObjectDispose }) => {
|
|
12
12
|
const resolved = useMemo(() => ({ ...deck, anvil: 0, precipitation: 0 }), [deck]);
|
|
13
13
|
const resolvedQuality = useMemo(() => ({ ...quality, steps: Math.min(quality.steps, 112) }), [quality]);
|
|
14
|
-
return (_jsx(VolumetricCloudsPass, { deck: resolved, cirrus: cirrus, quality: resolvedQuality, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
14
|
+
return (_jsx(VolumetricCloudsPass, { deck: resolved, cirrus: cirrus, quality: resolvedQuality, thunder: thunder, skySettings: skySettings, timeSettings: timeSettings, sunIntensity: sunIntensity, animations: animations, mouseMove: mouseMove, id: id, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
|
|
15
15
|
};
|
|
16
16
|
export default Stratocumulus;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
3
3
|
import type { SkySettings, TimeSettings } from '@3driseai/3drise-core';
|
|
4
|
-
import type { CirrusLayerConfig, CloudDeckConfig, CloudsQualityConfig } from '../../types/cloudConfigs';
|
|
4
|
+
import type { CirrusLayerConfig, CloudDeckConfig, CloudsQualityConfig, ThunderConfig } from '../../types/cloudConfigs';
|
|
5
5
|
import type { ObjectAnimations, MouseMoveInteractions } from '@3driseai/3drise-core';
|
|
6
6
|
/**
|
|
7
7
|
* The cloud render pipeline. The only component in this package that takes over
|
|
@@ -28,6 +28,9 @@ export interface VolumetricCloudsPassProps extends ObjectReadyProps {
|
|
|
28
28
|
deck?: CloudDeckConfig | null;
|
|
29
29
|
cirrus?: CirrusLayerConfig | null;
|
|
30
30
|
quality: CloudsQualityConfig;
|
|
31
|
+
/** Lightning. Needs a deck — the bolt sits inside it and lights it from within —
|
|
32
|
+
* so it is ignored on the cirrus-only path. */
|
|
33
|
+
thunder?: ThunderConfig;
|
|
31
34
|
skySettings?: SkySettings;
|
|
32
35
|
timeSettings?: TimeSettings;
|
|
33
36
|
/** Multiplies sun radiance for the clouds only. Matches SkySystem's sunIntensity. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VolumetricCloudsPass.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/VolumetricCloudsPass.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkD,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VolumetricCloudsPass.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/VolumetricCloudsPass.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAKvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAQvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAErF;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IAC/D,6EAA6E;IAC7E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,mBAAmB,CAAC;IAC7B;oDACgD;IAChD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAkBD,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAmW7D,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import * as THREE from 'three';
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { useFrame, useThree } from '@react-three/fiber';
|
|
5
5
|
import { useFrameRenderer } from '../../hooks/useFrameRenderer.js';
|
|
6
|
+
import { useThunder } from '../../hooks/useThunder.js';
|
|
6
7
|
import { useObjectReady } from '../../hooks/useObjectReady.js';
|
|
7
8
|
import { CLOUD_LIVE_KEY } from '../../hooks/useCloudLive.js';
|
|
8
9
|
import { useCloudNoise } from '../../hooks/useCloudNoise.js';
|
|
@@ -11,7 +12,7 @@ import { CloudVolumeMaterial } from '../../shaders/clouds/CloudVolumeMaterial.js
|
|
|
11
12
|
import { CirrusMaterial } from '../../shaders/clouds/CirrusMaterial.js';
|
|
12
13
|
import { CloudResolveMaterial } from '../../shaders/clouds/CloudResolveMaterial.js';
|
|
13
14
|
import { CloudCompositeMaterial } from '../../shaders/clouds/CloudCompositeMaterial.js';
|
|
14
|
-
import { applyCameraUniforms, applyCirrusUniforms, applyDeckUniforms, applySunUniforms, } from '../../utils/cloudUniforms.js';
|
|
15
|
+
import { applyCameraUniforms, applyCirrusUniforms, applyDeckUniforms, applySunUniforms, applyThunderUniforms } from '../../utils/cloudUniforms.js';
|
|
15
16
|
import { applyCloudsKeyframeAnimations, applyCloudsMouseMove, resolveDeckConfig, } from '../../utils/handleCloudsAnimations.js';
|
|
16
17
|
const quad = new THREE.PlaneGeometry(2, 2);
|
|
17
18
|
const orthoCam = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
@@ -26,7 +27,7 @@ function emptyTexture() {
|
|
|
26
27
|
tex.needsUpdate = true;
|
|
27
28
|
return tex;
|
|
28
29
|
}
|
|
29
|
-
const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, skySettings, timeSettings, sunIntensity = 1, animations, mouseMove, onObjectReady, onObjectDispose, }) => {
|
|
30
|
+
const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, thunder, skySettings, timeSettings, sunIntensity = 1, animations, mouseMove, onObjectReady, onObjectDispose, }) => {
|
|
30
31
|
const gl = useThree((s) => s.gl);
|
|
31
32
|
const scene = useThree((s) => s.scene);
|
|
32
33
|
const size = useThree((s) => s.size);
|
|
@@ -107,16 +108,29 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
107
108
|
// React tree sixty times a second.
|
|
108
109
|
const override = useRef({});
|
|
109
110
|
const startValues = useRef({});
|
|
111
|
+
// When the current animation set started, in ms. calculateTimeProgress divides by
|
|
112
|
+
// duration, so it wants time *since the animation began* — not a wall clock and not
|
|
113
|
+
// seconds. Reset when the animations change so editing one restarts it from the
|
|
114
|
+
// beginning rather than dropping the user somewhere mid-cycle.
|
|
115
|
+
const animStart = useRef(0);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
animStart.current = performance.now();
|
|
118
|
+
startValues.current = {};
|
|
119
|
+
}, [animations]);
|
|
110
120
|
// Live controller overrides. A slider drag writes here every pointer-move and the
|
|
111
121
|
// frame loop reads it on top of the config, so the deck responds without a Redux
|
|
112
122
|
// dispatch per frame. Cleared when the config identity changes, which is exactly
|
|
113
123
|
// slider-end committing the same value.
|
|
124
|
+
const thunderDriver = useThunder();
|
|
125
|
+
const boltRef = useRef(null);
|
|
114
126
|
const liveDeck = useRef({});
|
|
127
|
+
const liveThunder = useRef({});
|
|
115
128
|
const liveCirrus = useRef({});
|
|
116
129
|
const liveQuality = useRef({});
|
|
117
130
|
useEffect(() => { liveDeck.current = {}; }, [deck]);
|
|
118
131
|
useEffect(() => { liveCirrus.current = {}; }, [cirrus]);
|
|
119
132
|
useEffect(() => { liveQuality.current = {}; }, [quality]);
|
|
133
|
+
useEffect(() => { liveThunder.current = {}; }, [thunder]);
|
|
120
134
|
// The handle a controller reaches through findById(id).userData. Set in an effect,
|
|
121
135
|
// never as a userData JSX prop: R3F replaces the whole userData object on every
|
|
122
136
|
// render, which would drop the handle the moment anything above re-renders.
|
|
@@ -125,6 +139,7 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
125
139
|
deck: (key, value) => { liveDeck.current[key] = value; },
|
|
126
140
|
cirrus: (key, value) => { liveCirrus.current[key] = value; },
|
|
127
141
|
quality: (key, value) => { liveQuality.current[key] = value; },
|
|
142
|
+
thunder: (key, value) => { liveThunder.current[key] = value; },
|
|
128
143
|
}), []);
|
|
129
144
|
useEffect(() => {
|
|
130
145
|
const root = rootRef.current;
|
|
@@ -159,6 +174,29 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
159
174
|
frame.current += 1;
|
|
160
175
|
time.current += Math.min(delta, 0.05);
|
|
161
176
|
updateSun();
|
|
177
|
+
// Lightning is scheduled on the CPU because three things need the same event:
|
|
178
|
+
// the emission uniforms, the scene light, and the temporal blend below.
|
|
179
|
+
const liveThunderCfg = (thunder
|
|
180
|
+
? { ...thunder, ...liveThunder.current }
|
|
181
|
+
: undefined);
|
|
182
|
+
const bolt = (liveThunderCfg && deck)
|
|
183
|
+
? thunderDriver.update(delta, deck, liveThunderCfg, camera)
|
|
184
|
+
: null;
|
|
185
|
+
// The scene light is what stops the flash looking like it happens in a
|
|
186
|
+
// separate universe from the ground. decay 0 / distance 0 on purpose: a bolt
|
|
187
|
+
// 2 km up with physical falloff contributes nothing at ground level, and what
|
|
188
|
+
// a distant flash actually does is brighten everything at once.
|
|
189
|
+
if (boltRef.current) {
|
|
190
|
+
const lit = bolt && liveThunderCfg
|
|
191
|
+
? bolt.intensity * liveThunderCfg.sceneFlash
|
|
192
|
+
: 0;
|
|
193
|
+
boltRef.current.intensity = lit;
|
|
194
|
+
boltRef.current.visible = lit > 0.001;
|
|
195
|
+
if (lit > 0.001) {
|
|
196
|
+
boltRef.current.position.copy(bolt.position);
|
|
197
|
+
boltRef.current.color.set(liveThunderCfg.color);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
162
200
|
// ---- 1. scene ----
|
|
163
201
|
const sceneRT = (frame.current & 1) ? targets.sceneA : targets.sceneB;
|
|
164
202
|
const prevTarget = gl.getRenderTarget();
|
|
@@ -194,7 +232,7 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
194
232
|
// the pointer snapping back to the stored config every frame.
|
|
195
233
|
for (const k in override.current)
|
|
196
234
|
delete override.current[k];
|
|
197
|
-
applyCloudsKeyframeAnimations(animations?.clouds?.animations, startValues.current, deck, override.current,
|
|
235
|
+
applyCloudsKeyframeAnimations(animations?.clouds?.animations, startValues.current, deck, override.current, performance.now() - animStart.current);
|
|
198
236
|
if (mouseMove?.enabled && mouseMove.clouds?.enabled) {
|
|
199
237
|
applyCloudsMouseMove(mouseMove.clouds.properties, deck, override.current, pointer);
|
|
200
238
|
}
|
|
@@ -204,6 +242,12 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
204
242
|
const liveQual = { ...quality, ...liveQuality.current };
|
|
205
243
|
const m = passes.deckMat;
|
|
206
244
|
applyDeckUniforms(m, live, liveQual);
|
|
245
|
+
if (liveThunderCfg && bolt) {
|
|
246
|
+
applyThunderUniforms(m, liveThunderCfg, bolt.intensity, bolt.position);
|
|
247
|
+
}
|
|
248
|
+
else if (m.uniforms.u_flash) {
|
|
249
|
+
m.uniforms.u_flash.value = 0;
|
|
250
|
+
}
|
|
207
251
|
m.uniforms.u_base.value = noise.base;
|
|
208
252
|
m.uniforms.u_detail.value = noise.detail;
|
|
209
253
|
m.uniforms.u_weather.value = noise.weather;
|
|
@@ -236,6 +280,13 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
236
280
|
// and a high history weight smears. Ease off, and restore it once still.
|
|
237
281
|
const moved = camera.position.distanceToSquared(prevCamPos.current) > 1e-8
|
|
238
282
|
|| Math.abs(camera.quaternion.dot(prevCamQuat.current)) < 0.9999995;
|
|
283
|
+
// Deliberately NOT special-cased for lightning. The resolve clamps history
|
|
284
|
+
// to the 3x3 neighbourhood of the current frame before blending, and that
|
|
285
|
+
// clamp already handles a flash in both directions: dark history is pulled
|
|
286
|
+
// up when the bolt fires, and the bright frame is clamped away the moment
|
|
287
|
+
// it stops. Dropping the blend during a flash — which is what this used to
|
|
288
|
+
// do — throws away the temporal accumulation that turns the march's
|
|
289
|
+
// sub-pixel jitter into detail, and the whole deck visibly shakes.
|
|
239
290
|
r.u_blend.value = moved ? Math.min(quality.temporalBlend, 0.7) : quality.temporalBlend;
|
|
240
291
|
gl.setRenderTarget(destination);
|
|
241
292
|
gl.render(passes.resolveScene, orthoCam);
|
|
@@ -293,6 +344,6 @@ const VolumetricCloudsPass = ({ id = '3drise-clouds', deck, cirrus, quality, sky
|
|
|
293
344
|
useFrameRenderer(renderCompleteFrame);
|
|
294
345
|
// An empty group, but a real one: it carries userData.id so findById() can reach
|
|
295
346
|
// this layer, and the live handle so a controller can drive it without Redux.
|
|
296
|
-
return _jsx("group", { ref: rootRef });
|
|
347
|
+
return (_jsx("group", { ref: rootRef, children: _jsx("pointLight", { ref: boltRef, visible: false, intensity: 0, distance: 0, decay: 0 }) }));
|
|
297
348
|
};
|
|
298
349
|
export default VolumetricCloudsPass;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { MouseMoveInteractions, ObjectAnimations, SkySettings, TimeSettings } from '@3driseai/3drise-core';
|
|
2
2
|
import type { ObjectReadyProps } from '../../types/objectReady';
|
|
3
|
-
import type { CirrusLayerConfig, CloudDeckConfig, CloudsQualityConfig } from '../../types/cloudConfigs';
|
|
3
|
+
import type { CirrusLayerConfig, CloudDeckConfig, CloudsQualityConfig, ThunderConfig } from '../../types/cloudConfigs';
|
|
4
4
|
/** Shared by every layer component. The generator hands all four the same shape. */
|
|
5
5
|
export interface CloudLayerProps extends ObjectReadyProps {
|
|
6
6
|
/** Scene id, so a controller can findById() the layer and drive it live. */
|
|
@@ -8,6 +8,8 @@ export interface CloudLayerProps extends ObjectReadyProps {
|
|
|
8
8
|
deck: CloudDeckConfig;
|
|
9
9
|
cirrus: CirrusLayerConfig | null;
|
|
10
10
|
quality: CloudsQualityConfig;
|
|
11
|
+
/** Lightning. Absent or disabled means the flash path never runs. */
|
|
12
|
+
thunder?: ThunderConfig;
|
|
11
13
|
skySettings?: SkySettings;
|
|
12
14
|
timeSettings?: TimeSettings;
|
|
13
15
|
sunIntensity?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/volumetricClouds/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvH,oFAAoF;AACpF,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACrD,4EAA4E;IAC5E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,qEAAqE;IACrE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,SAAS,CAAC,EAAE,qBAAqB,CAAC;CACrC"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export { useCubeCamera } from './useCubeCamera';
|
|
|
25
25
|
export type { UseEnvironmentProbeOptions } from './useEnvironmentProbe';
|
|
26
26
|
export { useEnvironmentProbe } from './useEnvironmentProbe';
|
|
27
27
|
export { useFrameRenderer } from './useFrameRenderer';
|
|
28
|
+
export type { ThunderDriver, ThunderState } from './useThunder';
|
|
29
|
+
export { createThunderDriver, useThunder } from './useThunder';
|
|
28
30
|
export type { UseEnvironmentEffectsOptions } from './useEnvironmentEffects';
|
|
29
31
|
export { useEnvironmentEffects } from './useEnvironmentEffects';
|
|
30
32
|
export { useFrameAnimations } from './useFrameAnimations';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAKA,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE7D,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9D,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEpE,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEvF,YAAY,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export { useContinuousEffects } from './useContinuousEffects.js';
|
|
|
17
17
|
export { useCubeCamera } from './useCubeCamera.js';
|
|
18
18
|
export { useEnvironmentProbe } from './useEnvironmentProbe.js';
|
|
19
19
|
export { useFrameRenderer } from './useFrameRenderer.js';
|
|
20
|
+
export { createThunderDriver, useThunder } from './useThunder.js';
|
|
20
21
|
export { useEnvironmentEffects } from './useEnvironmentEffects.js';
|
|
21
22
|
export { useFrameAnimations } from './useFrameAnimations.js';
|
|
22
23
|
export { useFrameEffects } from './useFrameEffects.js';
|
|
@@ -18,6 +18,7 @@ export interface CloudLiveHandle {
|
|
|
18
18
|
deck(key: string, value: number | boolean): void;
|
|
19
19
|
cirrus(key: string, value: number | boolean): void;
|
|
20
20
|
quality(key: string, value: number | boolean): void;
|
|
21
|
+
thunder(key: string, value: number | boolean | string): void;
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Safe before the layer mounts and after it unmounts: the handle is resolved at call
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCloudLive.d.ts","sourceRoot":"","sources":["../../src/hooks/useCloudLive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC;;;;;;;;;;;;GAYG;AAEH,mFAAmF;AACnF,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACnD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"useCloudLive.d.ts","sourceRoot":"","sources":["../../src/hooks/useCloudLive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC;;;;;;;;;;;;GAYG;AAEH,mFAAmF;AACnF,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACjD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACnD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CAChE;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,eAAe,CAmB/E;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -15,7 +15,7 @@ import { findById } from '../utils/sceneQuery.js';
|
|
|
15
15
|
*/
|
|
16
16
|
/** Where VolumetricCloudsPass stashes its handle on the root object's userData. */
|
|
17
17
|
export const CLOUD_LIVE_KEY = '__cloudLive';
|
|
18
|
-
const NOOP = { deck: () => { }, cirrus: () => { }, quality: () => { } };
|
|
18
|
+
const NOOP = { deck: () => { }, cirrus: () => { }, quality: () => { }, thunder: () => { } };
|
|
19
19
|
/**
|
|
20
20
|
* Safe before the layer mounts and after it unmounts: the handle is resolved at call
|
|
21
21
|
* time, not at hook time, so a controller opened before the scene is ready still works
|
|
@@ -37,6 +37,7 @@ export function useCloudLive(target) {
|
|
|
37
37
|
deck: (key, value) => resolve().deck(key, value),
|
|
38
38
|
cirrus: (key, value) => resolve().cirrus(key, value),
|
|
39
39
|
quality: (key, value) => resolve().quality(key, value),
|
|
40
|
+
thunder: (key, value) => resolve().thunder(key, value),
|
|
40
41
|
};
|
|
41
42
|
}, [target]);
|
|
42
43
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import type { CloudDeckConfig, ThunderConfig } from '../types/cloudConfigs';
|
|
3
|
+
/**
|
|
4
|
+
* Flash scheduling for lightning.
|
|
5
|
+
*
|
|
6
|
+
* On the CPU rather than as a time hash in the shader, because three consumers need
|
|
7
|
+
* the *same* event: the volumetric emission uniforms, the scene light, and the
|
|
8
|
+
* temporal resolve (which has to stop blending while a flash is on screen, or the
|
|
9
|
+
* flash both under-reads and then ghosts for twenty frames). A GPU-side hash can
|
|
10
|
+
* drive only the first of those.
|
|
11
|
+
*
|
|
12
|
+
* Two things make it read as lightning rather than a blinking lamp:
|
|
13
|
+
*
|
|
14
|
+
* - **Exponential spacing.** Storms do not fire on a metronome. Waiting an
|
|
15
|
+
* exponentially distributed interval around the mean rate is the actual arrival
|
|
16
|
+
* process, and it costs one log().
|
|
17
|
+
* - **Multi-stroke flicker.** A single bolt is 2-5 return strokes over ~200 ms, each
|
|
18
|
+
* a fast attack and exponential decay. One clean flash looks synthetic; the
|
|
19
|
+
* stutter is what the eye recognises.
|
|
20
|
+
*/
|
|
21
|
+
export interface ThunderState {
|
|
22
|
+
/** 0 when dark. Peaks at ThunderConfig.intensity. */
|
|
23
|
+
intensity: number;
|
|
24
|
+
/** Bolt position in world space. Only meaningful while intensity > 0. */
|
|
25
|
+
position: THREE.Vector3;
|
|
26
|
+
/** True while the bolt is actually emitting light. */
|
|
27
|
+
active: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface ThunderDriver {
|
|
30
|
+
/** Advance by delta seconds and return the current state. */
|
|
31
|
+
update(dt: number, deck: CloudDeckConfig, cfg: ThunderConfig, camera: THREE.Camera): ThunderState;
|
|
32
|
+
}
|
|
33
|
+
export declare function createThunderDriver(): ThunderDriver;
|
|
34
|
+
/** One driver per mounted pass, stable across renders. */
|
|
35
|
+
export declare function useThunder(): ThunderDriver;
|
|
36
|
+
export default useThunder;
|
|
37
|
+
//# sourceMappingURL=useThunder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useThunder.d.ts","sourceRoot":"","sources":["../../src/hooks/useThunder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE5E;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,YAAY;IACzB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC;IACxB,sDAAsD;IACtD,MAAM,EAAE,OAAO,CAAC;CACnB;AAID,MAAM,WAAW,aAAa;IAC1B,6DAA6D;IAC7D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC;CACrG;AAuED,wBAAgB,mBAAmB,IAAI,aAAa,CAiEnD;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,IAAI,aAAa,CAM1C;AAED,eAAe,UAAU,CAAC"}
|