@3driseai/3drise-viewer 0.1.9 → 0.1.11

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.
Files changed (60) hide show
  1. package/dist/components/CloudsGenerator.d.ts.map +1 -1
  2. package/dist/components/CloudsGenerator.js +3 -1
  3. package/dist/components/EnvironmentManager.d.ts +30 -14
  4. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  5. package/dist/components/EnvironmentManager.js +7 -2
  6. package/dist/components/effects/DataStreamEffect.d.ts.map +1 -1
  7. package/dist/components/effects/DataStreamEffect.js +14 -8
  8. package/dist/components/effects/NeuralNetworkEffect.d.ts.map +1 -1
  9. package/dist/components/effects/NeuralNetworkEffect.js +11 -9
  10. package/dist/components/volumetricClouds/Cirrus.d.ts +4 -0
  11. package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -1
  12. package/dist/components/volumetricClouds/Cirrus.js +4 -0
  13. package/dist/components/volumetricClouds/Cumulonimbus.js +2 -2
  14. package/dist/components/volumetricClouds/Cumulus.js +2 -2
  15. package/dist/components/volumetricClouds/Stratocumulus.js +2 -2
  16. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +4 -1
  17. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
  18. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +45 -3
  19. package/dist/components/volumetricClouds/types.d.ts +3 -1
  20. package/dist/components/volumetricClouds/types.d.ts.map +1 -1
  21. package/dist/hooks/index.d.ts +2 -0
  22. package/dist/hooks/index.d.ts.map +1 -1
  23. package/dist/hooks/index.js +1 -0
  24. package/dist/hooks/useCloudLive.d.ts +1 -0
  25. package/dist/hooks/useCloudLive.d.ts.map +1 -1
  26. package/dist/hooks/useCloudLive.js +2 -1
  27. package/dist/hooks/useThunder.d.ts +37 -0
  28. package/dist/hooks/useThunder.d.ts.map +1 -0
  29. package/dist/hooks/useThunder.js +145 -0
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/shaders/clouds/CloudShadowMaterial.d.ts +52 -0
  34. package/dist/shaders/clouds/CloudShadowMaterial.d.ts.map +1 -0
  35. package/dist/shaders/clouds/CloudShadowMaterial.js +110 -0
  36. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +10 -0
  37. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
  38. package/dist/shaders/clouds/CloudVolumeMaterial.js +38 -2
  39. package/dist/shaders/glsl/cloudCore.glsl.d.ts +3 -3
  40. package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -1
  41. package/dist/shaders/glsl/cloudCore.glsl.js +81 -9
  42. package/dist/shaders/glsl/cloudShadow.glsl.d.ts +15 -0
  43. package/dist/shaders/glsl/cloudShadow.glsl.d.ts.map +1 -0
  44. package/dist/shaders/glsl/cloudShadow.glsl.js +35 -0
  45. package/dist/types/cloudConfigs.d.ts +53 -0
  46. package/dist/types/cloudConfigs.d.ts.map +1 -1
  47. package/dist/types/cloudConfigs.js +83 -51
  48. package/dist/types/index.d.ts +2 -2
  49. package/dist/types/index.d.ts.map +1 -1
  50. package/dist/types/index.js +1 -1
  51. package/dist/utils/cloudShadowMap.d.ts +43 -0
  52. package/dist/utils/cloudShadowMap.d.ts.map +1 -0
  53. package/dist/utils/cloudShadowMap.js +60 -0
  54. package/dist/utils/cloudUniforms.d.ts +6 -1
  55. package/dist/utils/cloudUniforms.d.ts.map +1 -1
  56. package/dist/utils/cloudUniforms.js +18 -0
  57. package/dist/utils/gpuProfiler.d.ts +33 -0
  58. package/dist/utils/gpuProfiler.d.ts.map +1 -0
  59. package/dist/utils/gpuProfiler.js +115 -0
  60. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudShadowMap.d.ts","sourceRoot":"","sources":["../../src/utils/cloudShadowMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;;;;;;;GAcG;AAEH,eAAO,MAAM,mBAAmB;IAC5B,6EAA6E;;eAC1C,KAAK,CAAC,OAAO,GAAG,IAAI;;IACvD,gEAAgE;;;;IAEhE,8EAA8E;;;;CAEjF,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,EAC7B,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI,EAC5B,QAAQ,EAAE,MAAM,GACjB,IAAI,CAIN;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,KAAK,CAAC,kBAAkB,EAChC,MAAM,EAAE,KAAK,CAAC,OAAO,EACrB,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,MAAM,EAAE,KAAK,CAAC,OAAO,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GAChB,IAAI,CAkBN"}
@@ -0,0 +1,60 @@
1
+ import * as THREE from 'three';
2
+ /**
3
+ * The cloud shadow map, shared with every surface material that wants it.
4
+ *
5
+ * These are three.js *shared uniform objects*: a material that spreads
6
+ * `cloudShadowUniforms` into its own uniforms holds a reference to the same
7
+ * `{ value }` boxes, so the cloud pass updates them once per frame and terrain,
8
+ * ocean, landscape and anything else see the new texture without knowing about each
9
+ * other. Same idea as THREE.UniformsLib.
10
+ *
11
+ * The alternative — threading the texture down as props, or having each material
12
+ * poll a registry per frame — means every new surface material has to be taught
13
+ * about clouds. This way it costs one line at the material and nothing at the call
14
+ * site, which is the only version that will actually get adopted across a codebase
15
+ * with three custom surface shaders and an open-ended set of object materials.
16
+ */
17
+ export const cloudShadowUniforms = {
18
+ /** R channel is transmittance along the sun ray: 1 lit, 0 fully shadowed. */
19
+ u_cloudShadowMap: { value: null },
20
+ /** World -> shadow clip. The chunk does the 0.5 bias itself. */
21
+ u_cloudShadowMatrix: { value: new THREE.Matrix4() },
22
+ /** 0 disables the lookup entirely, so an unused material pays one compare. */
23
+ u_cloudShadowStrength: { value: 0 },
24
+ };
25
+ /** Called by the cloud pass each frame. Nothing else should write these. */
26
+ export function publishCloudShadowMap(texture, matrix, strength) {
27
+ cloudShadowUniforms.u_cloudShadowMap.value = texture;
28
+ if (matrix)
29
+ cloudShadowUniforms.u_cloudShadowMatrix.value.copy(matrix);
30
+ cloudShadowUniforms.u_cloudShadowStrength.value = texture ? strength : 0;
31
+ }
32
+ /**
33
+ * Orthographic frame for the shadow camera, looking along the sun.
34
+ *
35
+ * Centred ahead of the viewer rather than on it: shadows behind the camera are
36
+ * never seen, so spending half the map on them halves the effective resolution for
37
+ * no reason. Snapped to texel increments — without that, the map slides
38
+ * continuously as the camera moves and the shadow edges crawl and shimmer, which
39
+ * is far more distracting than a slightly coarse edge.
40
+ */
41
+ export function updateCloudShadowCamera(camera, viewer, viewDir, sunDir, extent, mapSize) {
42
+ const centre = new THREE.Vector3()
43
+ .copy(viewDir).setY(0).normalize().multiplyScalar(extent * 0.45)
44
+ .add(viewer);
45
+ centre.y = 0;
46
+ const texelWorld = (extent * 2) / mapSize;
47
+ centre.x = Math.round(centre.x / texelWorld) * texelWorld;
48
+ centre.z = Math.round(centre.z / texelWorld) * texelWorld;
49
+ // Far enough back that the near plane clears any cloud top.
50
+ camera.position.copy(centre).addScaledVector(sunDir, 60000);
51
+ camera.lookAt(centre);
52
+ camera.left = -extent;
53
+ camera.right = extent;
54
+ camera.top = extent;
55
+ camera.bottom = -extent;
56
+ camera.near = 1;
57
+ camera.far = 120000;
58
+ camera.updateProjectionMatrix();
59
+ camera.updateMatrixWorld(true);
60
+ }
@@ -1,7 +1,12 @@
1
1
  import * as THREE from 'three';
2
- import type { CloudDeckConfig, CirrusLayerConfig, CloudsQualityConfig } from '../types/cloudConfigs';
2
+ import type { CloudDeckConfig, CirrusLayerConfig, CloudsQualityConfig, ThunderConfig } from '../types/cloudConfigs';
3
3
  import type { CloudSunState } from '../hooks/useCloudSun';
4
4
  export declare function applyDeckUniforms(material: THREE.ShaderMaterial, deck: CloudDeckConfig, quality: CloudsQualityConfig): void;
5
+ /**
6
+ * Lightning uniforms. `intensity` comes from the scheduler, already through the
7
+ * stroke envelope — the config's own intensity is the peak it scales to.
8
+ */
9
+ export declare function applyThunderUniforms(material: THREE.ShaderMaterial, thunder: ThunderConfig, intensity: number, position: THREE.Vector3): void;
5
10
  export declare function applyCirrusUniforms(material: THREE.ShaderMaterial, cirrus: CirrusLayerConfig, quality: CloudsQualityConfig): void;
6
11
  /** Sun and atmosphere. Every cloud material and the sky background share these. */
7
12
  export declare function applySunUniforms(material: THREE.ShaderMaterial, sun: CloudSunState, intensity: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"cloudUniforms.d.ts","sourceRoot":"","sources":["../../src/utils/cloudUniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACrG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA0B1D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CA0C3H;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAkBjI;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAY5G;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,iBAAiB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUhK"}
1
+ {"version":3,"file":"cloudUniforms.d.ts","sourceRoot":"","sources":["../../src/utils/cloudUniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA0B1D,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CA0C3H;AAKD;;;GAGG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,KAAK,CAAC,OAAO,GACxB,IAAI,CAWN;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAkBjI;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAY5G;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,iBAAiB,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUhK"}
@@ -59,6 +59,24 @@ export function applyDeckUniforms(material, deck, quality) {
59
59
  u.u_detailFade.value = inverse(quality.detailFadeDistance, 16000);
60
60
  u.u_curvature.value = quality.curvature;
61
61
  }
62
+ /** Reused so a flash does not allocate a Color every frame. */
63
+ const flashColor = new THREE.Color();
64
+ /**
65
+ * Lightning uniforms. `intensity` comes from the scheduler, already through the
66
+ * stroke envelope — the config's own intensity is the peak it scales to.
67
+ */
68
+ export function applyThunderUniforms(material, thunder, intensity, position) {
69
+ const u = material.uniforms;
70
+ if (!u || !u.u_flash)
71
+ return;
72
+ u.u_flash.value = thunder.enabled ? intensity : 0;
73
+ if (!thunder.enabled || intensity <= 0)
74
+ return;
75
+ u.u_flashPos.value.copy(position);
76
+ u.u_flashColor.value.copy(flashColor.set(thunder.color));
77
+ u.u_flashRadius.value = Math.max(thunder.radius, 1);
78
+ u.u_flashScatter.value = thunder.scatter;
79
+ }
62
80
  export function applyCirrusUniforms(material, cirrus, quality) {
63
81
  const u = material.uniforms;
64
82
  if (!u)
@@ -0,0 +1,33 @@
1
+ import type * as THREE from 'three';
2
+ declare class GpuProfiler {
3
+ private gl;
4
+ private ext;
5
+ private enabled;
6
+ private active;
7
+ private pending;
8
+ private samples;
9
+ /** Frames counted while enabled, so dump() can report per-frame cost honestly. */
10
+ private frames;
11
+ attach(renderer: THREE.WebGLRenderer): void;
12
+ get available(): boolean;
13
+ get isEnabled(): boolean;
14
+ enable(): string;
15
+ disable(): void;
16
+ /** Open a timed region. Only one may be open at a time — the API allows no nesting. */
17
+ begin(label: string): void;
18
+ end(): void;
19
+ /** Call once per frame, after the last end(). Drains whatever the GPU has retired. */
20
+ collect(): void;
21
+ private discardPending;
22
+ /** Rolling mean ms per pass, plus each pass's share of the measured total. */
23
+ results(): {
24
+ label: string;
25
+ ms: number;
26
+ share: string;
27
+ samples: number;
28
+ }[];
29
+ dump(): void;
30
+ }
31
+ export declare const gpuProfiler: GpuProfiler;
32
+ export default gpuProfiler;
33
+ //# sourceMappingURL=gpuProfiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpuProfiler.d.ts","sourceRoot":"","sources":["../../src/utils/gpuProfiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AA2BpC,cAAM,WAAW;IACb,OAAO,CAAC,EAAE,CAAuC;IACjD,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAA+B;IAC9C,kFAAkF;IAClF,OAAO,CAAC,MAAM,CAAK;IAEnB,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,aAAa,GAAG,IAAI;IAQ3C,IAAI,SAAS,IAAI,OAAO,CAAuB;IAC/C,IAAI,SAAS,IAAI,OAAO,CAAuC;IAE/D,MAAM,IAAI,MAAM;IAQhB,OAAO,IAAI,IAAI;IAKf,uFAAuF;IACvF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAS1B,GAAG,IAAI,IAAI;IAOX,sFAAsF;IACtF,OAAO,IAAI,IAAI;IA4Bf,OAAO,CAAC,cAAc;IAMtB,8EAA8E;IAC9E,OAAO,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;IAY1E,IAAI,IAAI,IAAI;CAOf;AAED,eAAO,MAAM,WAAW,EAAE,WAA+B,CAAC;AAM1D,eAAe,WAAW,CAAC"}
@@ -0,0 +1,115 @@
1
+ const AVG_WINDOW = 60;
2
+ class GpuProfiler {
3
+ gl = null;
4
+ ext = null;
5
+ enabled = false;
6
+ active = null;
7
+ pending = [];
8
+ samples = new Map();
9
+ /** Frames counted while enabled, so dump() can report per-frame cost honestly. */
10
+ frames = 0;
11
+ attach(renderer) {
12
+ const gl = renderer.getContext();
13
+ if (this.gl === gl)
14
+ return;
15
+ this.gl = gl;
16
+ this.ext = gl.getExtension('EXT_disjoint_timer_query_webgl2')
17
+ ?? gl.getExtension('EXT_disjoint_timer_query');
18
+ }
19
+ get available() { return !!this.ext; }
20
+ get isEnabled() { return this.enabled && !!this.ext; }
21
+ enable() {
22
+ if (!this.ext)
23
+ return 'EXT_disjoint_timer_query_webgl2 not available in this browser';
24
+ this.enabled = true;
25
+ this.samples.clear();
26
+ this.frames = 0;
27
+ return 'GPU profiling on — let it run a second, then __cloudProfile.dump()';
28
+ }
29
+ disable() {
30
+ this.enabled = false;
31
+ this.discardPending();
32
+ }
33
+ /** Open a timed region. Only one may be open at a time — the API allows no nesting. */
34
+ begin(label) {
35
+ if (!this.isEnabled || this.active)
36
+ return;
37
+ const gl = this.gl;
38
+ const query = gl.createQuery();
39
+ if (!query)
40
+ return;
41
+ gl.beginQuery(this.ext.TIME_ELAPSED_EXT, query);
42
+ this.active = { label, query };
43
+ }
44
+ end() {
45
+ if (!this.active)
46
+ return;
47
+ this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
48
+ this.pending.push(this.active);
49
+ this.active = null;
50
+ }
51
+ /** Call once per frame, after the last end(). Drains whatever the GPU has retired. */
52
+ collect() {
53
+ if (!this.isEnabled)
54
+ return;
55
+ const gl = this.gl;
56
+ this.frames++;
57
+ // A disjoint means the GPU was interrupted (context switch, power state) and
58
+ // every result in flight is garbage — the spec requires discarding them.
59
+ if (gl.getParameter(this.ext.GPU_DISJOINT_EXT)) {
60
+ this.discardPending();
61
+ return;
62
+ }
63
+ const stillPending = [];
64
+ for (const p of this.pending) {
65
+ if (!gl.getQueryParameter(p.query, gl.QUERY_RESULT_AVAILABLE)) {
66
+ stillPending.push(p);
67
+ continue;
68
+ }
69
+ const ns = gl.getQueryParameter(p.query, gl.QUERY_RESULT);
70
+ gl.deleteQuery(p.query);
71
+ const arr = this.samples.get(p.label) ?? [];
72
+ arr.push(ns / 1e6); // ns -> ms
73
+ if (arr.length > AVG_WINDOW)
74
+ arr.shift();
75
+ this.samples.set(p.label, arr);
76
+ }
77
+ this.pending = stillPending;
78
+ }
79
+ discardPending() {
80
+ for (const p of this.pending)
81
+ this.gl.deleteQuery(p.query);
82
+ this.pending = [];
83
+ if (this.active) {
84
+ this.gl.endQuery(this.ext.TIME_ELAPSED_EXT);
85
+ this.active = null;
86
+ }
87
+ }
88
+ /** Rolling mean ms per pass, plus each pass's share of the measured total. */
89
+ results() {
90
+ const rows = [...this.samples.entries()].map(([label, a]) => ({
91
+ label,
92
+ ms: a.reduce((x, y) => x + y, 0) / a.length,
93
+ samples: a.length,
94
+ }));
95
+ const total = rows.reduce((s, r) => s + r.ms, 0);
96
+ return rows
97
+ .sort((a, b) => b.ms - a.ms)
98
+ .map((r) => ({ ...r, ms: +r.ms.toFixed(3), share: total > 0 ? `${Math.round((r.ms / total) * 100)}%` : '—' }));
99
+ }
100
+ dump() {
101
+ const rows = this.results();
102
+ if (!rows.length) {
103
+ console.log('[cloud profile] no results yet — give it a second');
104
+ return;
105
+ }
106
+ const total = rows.reduce((s, r) => s + r.ms, 0);
107
+ console.table(rows);
108
+ console.log(`[cloud profile] measured total ${total.toFixed(2)} ms/frame (${(1000 / total).toFixed(0)} fps if this were the only cost)`);
109
+ }
110
+ }
111
+ export const gpuProfiler = new GpuProfiler();
112
+ if (typeof window !== 'undefined') {
113
+ window.__cloudProfile = gpuProfiler;
114
+ }
115
+ export default gpuProfiler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3driseai/3drise-viewer",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,6 +39,6 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@3driseai/3drise-common": "^1.0.1",
42
- "@3driseai/3drise-core": "^1.0.5"
42
+ "@3driseai/3drise-core": "^1.0.6"
43
43
  }
44
44
  }