@3driseai/3drise-viewer 0.1.30 → 0.1.32

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 (88) hide show
  1. package/dist/animationsV2/ClipPlayer.d.ts.map +1 -1
  2. package/dist/animationsV2/ClipPlayer.js +14 -12
  3. package/dist/animationsV2/ClipsRuntime.d.ts +9 -0
  4. package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
  5. package/dist/animationsV2/ClipsRuntime.js +54 -7
  6. package/dist/animationsV2/appliers.d.ts.map +1 -1
  7. package/dist/animationsV2/appliers.js +21 -2
  8. package/dist/animationsV2/clipUtils.d.ts.map +1 -1
  9. package/dist/animationsV2/clipUtils.js +4 -0
  10. package/dist/animationsV2/sequenceUtils.js +4 -5
  11. package/dist/animationsV2/sunSystemLive.d.ts +12 -0
  12. package/dist/animationsV2/sunSystemLive.d.ts.map +1 -0
  13. package/dist/animationsV2/sunSystemLive.js +8 -0
  14. package/dist/api/sceneHandle.d.ts +3 -1
  15. package/dist/api/sceneHandle.d.ts.map +1 -1
  16. package/dist/api/sceneHandle.js +2 -2
  17. package/dist/components/AdaptiveResolution.d.ts +9 -0
  18. package/dist/components/AdaptiveResolution.d.ts.map +1 -0
  19. package/dist/components/AdaptiveResolution.js +61 -0
  20. package/dist/components/CameraController.d.ts.map +1 -1
  21. package/dist/components/CameraController.js +24 -7
  22. package/dist/components/MoonDisc.d.ts.map +1 -1
  23. package/dist/components/MoonDisc.js +2 -1
  24. package/dist/components/OceanBuilder.d.ts +4 -1
  25. package/dist/components/OceanBuilder.d.ts.map +1 -1
  26. package/dist/components/OceanBuilder.js +2 -1
  27. package/dist/components/ParticlesGenerator.d.ts.map +1 -1
  28. package/dist/components/ParticlesGenerator.js +2 -0
  29. package/dist/components/SceneBuilder.d.ts.map +1 -1
  30. package/dist/components/SceneBuilder.js +5 -2
  31. package/dist/components/Skybox.d.ts.map +1 -1
  32. package/dist/components/Skybox.js +2 -1
  33. package/dist/components/SunLight.d.ts.map +1 -1
  34. package/dist/components/SunLight.js +3 -2
  35. package/dist/components/index.d.ts +1 -0
  36. package/dist/components/index.d.ts.map +1 -1
  37. package/dist/components/index.js +1 -0
  38. package/dist/components/lightBulb/LightBulb.d.ts.map +1 -1
  39. package/dist/components/lightBulb/LightBulb.js +7 -2
  40. package/dist/components/particles/FireworksParticles.d.ts +22 -0
  41. package/dist/components/particles/FireworksParticles.d.ts.map +1 -0
  42. package/dist/components/particles/FireworksParticles.js +1649 -0
  43. package/dist/components/particles/index.d.ts +2 -0
  44. package/dist/components/particles/index.d.ts.map +1 -1
  45. package/dist/components/particles/index.js +1 -0
  46. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
  47. package/dist/components/terrain/TerrainSurface.js +26 -4
  48. package/dist/components/water/OceanSurface.d.ts.map +1 -1
  49. package/dist/components/water/OceanSurface.js +5 -1
  50. package/dist/components/water/types.d.ts +3 -1
  51. package/dist/components/water/types.d.ts.map +1 -1
  52. package/dist/hooks/useOceanMaterial.d.ts +6 -2
  53. package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
  54. package/dist/hooks/useOceanMaterial.js +22 -2
  55. package/dist/hooks/useOrbitTargetFollow.d.ts +10 -0
  56. package/dist/hooks/useOrbitTargetFollow.d.ts.map +1 -0
  57. package/dist/hooks/useOrbitTargetFollow.js +194 -0
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +1 -0
  61. package/dist/shaders/glsl/terrainCore.glsl.d.ts +18 -3
  62. package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -1
  63. package/dist/shaders/glsl/terrainCore.glsl.js +42 -21
  64. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +36 -11
  65. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -1
  66. package/dist/shaders/ocean/OceanSurfaceMaterial.js +96 -5
  67. package/dist/triggers/hosts/actions.d.ts.map +1 -1
  68. package/dist/triggers/hosts/actions.js +2 -0
  69. package/dist/triggers/hosts/timelineCues.js +1 -1
  70. package/dist/triggers/kinds/change.d.ts +4 -0
  71. package/dist/triggers/kinds/change.d.ts.map +1 -0
  72. package/dist/triggers/kinds/change.js +50 -0
  73. package/dist/triggers/kinds/index.d.ts +1 -0
  74. package/dist/triggers/kinds/index.d.ts.map +1 -1
  75. package/dist/triggers/kinds/index.js +1 -0
  76. package/dist/utils/CameraSingleton.d.ts +4 -0
  77. package/dist/utils/CameraSingleton.d.ts.map +1 -1
  78. package/dist/utils/CameraSingleton.js +4 -0
  79. package/dist/utils/deviceTier.d.ts +2 -0
  80. package/dist/utils/deviceTier.d.ts.map +1 -0
  81. package/dist/utils/deviceTier.js +16 -0
  82. package/dist/utils/environmentDrawOrder.d.ts +23 -0
  83. package/dist/utils/environmentDrawOrder.d.ts.map +1 -0
  84. package/dist/utils/environmentDrawOrder.js +22 -0
  85. package/dist/utils/terrainUniforms.d.ts +7 -0
  86. package/dist/utils/terrainUniforms.d.ts.map +1 -1
  87. package/dist/utils/terrainUniforms.js +15 -2
  88. package/package.json +2 -2
@@ -26,8 +26,12 @@
26
26
  * per octave, nine octaves, several evaluations per pixel puts it into the
27
27
  * billions of transcendentals per frame.
28
28
  */
29
- /** Every uniform the height field and the shading read. */
30
- export const terrainUniforms = /* glsl */ `
29
+ /**
30
+ * The uniforms the height field and the sun-shadow march read — and nothing else,
31
+ * so another material (the ocean) can include the field without redeclaring its
32
+ * own u_curvature, u_exposure, u_roughness… GLSL refuses a uniform declared twice.
33
+ */
34
+ export const terrainFormUniforms = /* glsl */ `
31
35
  uniform int u_terrainType;
32
36
 
33
37
  uniform float u_elevation;
@@ -49,6 +53,29 @@ uniform float u_plateau;
49
53
  uniform float u_valleyDepth;
50
54
  uniform float u_valleyWidth;
51
55
 
56
+ // The analytic sun-shadow march (terrainShadow) - shared with the ocean, which
57
+ // marches the same field to put headland shadows on the water.
58
+ uniform float u_sunShadow, u_shadowSoftness;
59
+ uniform float u_shadowDistance;
60
+ uniform int u_shadowSteps;
61
+
62
+ // A land object: a bounded patch of this field, placed by its object's transform.
63
+ // Its "terrain space" is metres from the object's origin, unrotated, plus a seed
64
+ // offset; height is above the object's base. See TerrainMaterial's patch vertex.
65
+ #ifdef TERRAIN_PATCH
66
+ uniform vec2 u_patchSize; // footprint in metres (object scale x / z)
67
+ uniform vec2 u_patchOffset; // terrain-space centre: the seed's offset into the field
68
+ uniform float u_edgeWidth; // metres over which the land eases down to its base
69
+ uniform vec3 u_camTerrain; // the camera, in terrain space
70
+ uniform float u_scaleY; // object scale y: terrain metres = local y x this
71
+ uniform float u_patchCell; // metres per grid cell
72
+ #define TERRAIN_CAM u_camTerrain
73
+ #else
74
+ #define TERRAIN_CAM cameraPosition
75
+ #endif
76
+ `;
77
+ /** The terrain surface's own uniforms: shading, lighting, textures. */
78
+ export const terrainSurfaceUniforms = /* glsl */ `
52
79
  uniform float u_cellSize;
53
80
  uniform float u_curvature;
54
81
 
@@ -66,10 +93,8 @@ uniform float u_roughness, u_specular;
66
93
  // per pixel removes an acos, a pow and three exps from every fragment.
67
94
  uniform vec3 u_skyAmbient;
68
95
  uniform vec3 u_groundAmbient;
69
- uniform float u_ambient, u_bounce, u_sunShadow, u_shadowSoftness;
70
- uniform float u_shadowDistance;
96
+ uniform float u_ambient, u_bounce;
71
97
  uniform float u_fogDensity, u_exposure;
72
- uniform int u_shadowSteps;
73
98
 
74
99
  // Ground textures. The far colour per layer is always set: the flat colour for an
75
100
  // untextured layer, the texture's own mean x tint for a textured one, so the
@@ -88,20 +113,6 @@ uniform float u_tDistance;
88
113
  uniform float u_tHeightBlend;
89
114
  #endif
90
115
 
91
- // A land object: a bounded patch of this field, placed by its object's transform.
92
- // Its "terrain space" is metres from the object's origin, unrotated, plus a seed
93
- // offset; height is above the object's base. See TerrainMaterial's patch vertex.
94
- #ifdef TERRAIN_PATCH
95
- uniform vec2 u_patchSize; // footprint in metres (object scale x / z)
96
- uniform vec2 u_patchOffset; // terrain-space centre: the seed's offset into the field
97
- uniform float u_edgeWidth; // metres over which the land eases down to its base
98
- uniform vec3 u_camTerrain; // the camera, in terrain space
99
- uniform float u_scaleY; // object scale y: terrain metres = local y x this
100
- uniform float u_patchCell; // metres per grid cell
101
- #define TERRAIN_CAM u_camTerrain
102
- #else
103
- #define TERRAIN_CAM cameraPosition
104
- #endif
105
116
  `;
106
117
  /**
107
118
  * Gradient noise with an analytic derivative.
@@ -515,7 +526,7 @@ float terrainOccluderAt(vec2 p, float lodCell){ return terrainHeightAt(p, lodCel
515
526
  * The terminator itself stays per-pixel: `terrainLight` takes N·L from the
516
527
  * fragment's own normal, so only the CAST shadow is interpolated.
517
528
  */
518
- export const terrainShading = /* glsl */ `
529
+ export const terrainShadow = /* glsl */ `
519
530
  /** 1 lit, 0 shadowed, soft in between. */
520
531
  float terrainSunShadow(vec3 p, vec3 n, float lodCell, int steps){
521
532
  if (steps < 1 || u_sunShadow <= 0.0) return 1.0;
@@ -585,6 +596,8 @@ float terrainShadowAt(vec3 p, vec3 n, float lodCell, float dist){
585
596
  return mix(1.0, terrainSunShadow(p, n, lodCell, steps), fade);
586
597
  }
587
598
 
599
+ `;
600
+ export const terrainShading = /* glsl */ `
588
601
  /**
589
602
  * Albedo.
590
603
  *
@@ -867,5 +880,13 @@ void terrainSurfaceNear(vec3 wp, vec3 n, vec4 w, TerrainGrads g,
867
880
  `;
868
881
  /** Everything a surface material needs, in include order. Requires three's
869
882
  * `<common>` and `skyLib` from cloudCore before it. */
883
+ /** Every uniform the terrain material reads. */
884
+ export const terrainUniforms = [terrainFormUniforms, terrainSurfaceUniforms].join('\n');
870
885
  export const terrainField = [terrainUniforms, terrainNoise, terrainHeight].join('\n');
871
- export const terrainFull = [terrainField, terrainShading].join('\n');
886
+ /**
887
+ * The height field and its sun-shadow march, with only the uniforms they read.
888
+ * What another material includes to stand water (or anything else) on the
889
+ * terrain: the ocean uses it for shoreline depth and headland shadows.
890
+ */
891
+ export const terrainFieldOnly = [terrainFormUniforms, terrainNoise, terrainHeight, terrainShadow].join('\n');
892
+ export const terrainFull = [terrainField, terrainShadow, terrainShading].join('\n');
@@ -6,6 +6,40 @@ export interface OceanMaterialUniforms {
6
6
  /** Uniform-space defaults. Config units are converted by `applyOceanUniforms`;
7
7
  * these are only what the material holds before anything is applied. */
8
8
  export declare const oceanMaterialDefaults: {
9
+ u_sunDir: THREE.Vector3;
10
+ u_sunColor: THREE.Color;
11
+ u_skyAmbient: THREE.Color;
12
+ u_groundAmbient: THREE.Color;
13
+ u_sunIntensity: number;
14
+ u_moonDir: THREE.Vector3;
15
+ u_moonColor: THREE.Color;
16
+ u_turbidity: number;
17
+ u_rayleigh: number;
18
+ u_mieCoefficient: number;
19
+ u_mieG: number;
20
+ u_terrainType: number;
21
+ u_elevation: number;
22
+ u_seaLevel: number;
23
+ u_baseScale: number;
24
+ u_octaves: number;
25
+ u_lacunarity: number;
26
+ u_gain: number;
27
+ u_ridge: number;
28
+ u_warpStrength: number;
29
+ u_warpScale: number;
30
+ u_erosion: number;
31
+ u_terraces: number;
32
+ u_terraceSharp: number;
33
+ u_bearingDir: THREE.Vector2;
34
+ u_duneFreq: number;
35
+ u_duneAsym: number;
36
+ u_plateau: number;
37
+ u_valleyDepth: number;
38
+ u_valleyWidth: number;
39
+ u_sunShadow: number;
40
+ u_shadowSoftness: number;
41
+ u_shadowDistance: number;
42
+ u_shadowSteps: number;
9
43
  u_waveA: THREE.Vector4[];
10
44
  u_waveB: THREE.Vector4[];
11
45
  u_waveCount: number;
@@ -36,17 +70,8 @@ export declare const oceanMaterialDefaults: {
36
70
  u_exposure: number;
37
71
  u_curvature: number;
38
72
  u_receiveShadows: number;
39
- u_sunDir: THREE.Vector3;
40
- u_sunColor: THREE.Color;
41
- u_skyAmbient: THREE.Color;
42
- u_groundAmbient: THREE.Color;
43
- u_sunIntensity: number;
44
- u_moonDir: THREE.Vector3;
45
- u_moonColor: THREE.Color;
46
- u_turbidity: number;
47
- u_rayleigh: number;
48
- u_mieCoefficient: number;
49
- u_mieG: number;
73
+ u_shoreDepth: number;
74
+ u_shoreFoam: number;
50
75
  };
51
76
  export declare class OceanSurfaceMaterial extends THREE.ShaderMaterial {
52
77
  constructor();
@@ -1 +1 @@
1
- {"version":3,"file":"OceanSurfaceMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/ocean/OceanSurfaceMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAmM9D,MAAM,WAAW,qBAAqB;IAClC,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAA;CAChC;AAMD;yEACyE;AACzE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDjC,CAAA;AAgBD,qBAAa,oBAAqB,SAAQ,KAAK,CAAC,cAAc;;CAa7D;AAID,OAAO,QAAQ,oBAAoB,CAAC;IAChC,UAAU,aAAa;QACnB,oBAAoB,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAA;KAClE;CACJ"}
1
+ {"version":3,"file":"OceanSurfaceMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/ocean/OceanSurfaceMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AA0R9D,MAAM,WAAW,qBAAqB;IAClC,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAA;CAChC;AAMD;yEACyE;AACzE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDjC,CAAA;AAgBD,qBAAa,oBAAqB,SAAQ,KAAK,CAAC,cAAc;;CAa7D;AAID,OAAO,QAAQ,oBAAoB,CAAC;IAChC,UAAU,aAAa;QACnB,oBAAoB,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAA;KAClE;CACJ"}
@@ -2,6 +2,7 @@ import * as THREE from 'three';
2
2
  import { extend } from '@react-three/fiber';
3
3
  import { skyLib } from '../glsl/cloudCore.glsl.js';
4
4
  import { oceanFull, MAX_WAVES } from '../glsl/oceanCore.glsl.js';
5
+ import { terrainFieldOnly } from '../glsl/terrainCore.glsl.js';
5
6
  /**
6
7
  * The water surface material. Used by both hosts — the world clipmap and a
7
8
  * placed body — and by all four water types, which differ in the spectrum the
@@ -44,6 +45,16 @@ const vertex = /* glsl */ `
44
45
  ${skyLib}
45
46
  ${oceanFull}
46
47
 
48
+ // The ground under the water (phase 4 of the ocean plan). Only the height field
49
+ // and its sun-shadow march, with only their own uniforms - the ocean has its own
50
+ // u_curvature, u_exposure... and GLSL refuses a uniform declared twice. Mind the
51
+ // trap in oceanCore: the field's u_seaLevel is the TERRAIN's; the water's level
52
+ // is u_waterLevel.
53
+ #ifdef OCEAN_TERRAIN
54
+ ${terrainFieldOnly}
55
+ #endif
56
+ uniform float u_shoreDepth;
57
+
47
58
  /** World size of this vertex's cell. Per-vertex so one material serves every
48
59
  * clipmap ring, and a placed body sets it from its own grid. */
49
60
  attribute float aCell;
@@ -59,6 +70,8 @@ varying float vFoam;
59
70
  varying float vRelHeight;
60
71
  varying float vDist;
61
72
  varying float vDepthFactor;
73
+ varying float vShoreDepth;
74
+ varying float vTerrainShadow;
62
75
 
63
76
  void main(){
64
77
  // Geomorph first, waves second. The other order blends two different points on
@@ -85,15 +98,41 @@ void main(){
85
98
  bool isBody = u_bodyHalf.x > 0.0;
86
99
  vec2 fieldXZ = isBody ? local : wxz;
87
100
 
101
+ // Water depth from the terrain height field under this vertex.
102
+ //
103
+ // Waves lose their height as the water shoals and are gone at the waterline.
104
+ // That is the physics, and it is also the fix for the shoreline: an open-sea
105
+ // swell heaving a couple of metres up and down a 1:4 beach swept the waterline
106
+ // ~8 m in and out on every wave, and with the edge being a hard depth-buffer
107
+ // cut through the rock, that read as jitter. With the amplitude gone at depth
108
+ // 0, the line sits still where the ground meets the level. Waves get twice the
109
+ // shore depth to die in, because they need more room than the colour does.
110
+ float shoal = 1.0;
111
+ vShoreDepth = 1.0e4;
112
+ vTerrainShadow = 1.0;
113
+ #ifdef OCEAN_TERRAIN
114
+ if (!isBody) {
115
+ float ground = terrainHeightAt(wxz, max(cellLod, 0.5));
116
+ vShoreDepth = u_waterLevel - ground;
117
+ shoal = smoothstep(0.0, max(u_shoreDepth, 0.05) * 2.0, vShoreDepth);
118
+ // A headland's shadow across the bay: the terrain's own analytic march, from
119
+ // the flat water level, faded and stepped by distance exactly as on land.
120
+ vec3 sp = vec3(wxz.x, u_waterLevel, wxz.y);
121
+ float shadow = terrainShadowAt(sp, vec3(0.0, 1.0, 0.0), cellLod, distance(sp, cameraPosition));
122
+ vTerrainShadow = mix(1.0, shadow, saturate(u_sunShadow));
123
+ }
124
+ #endif
125
+
88
126
  vec3 disp; vec3 nrm; float jac; float rel;
89
- oceanWaveSum(fieldXZ, cellLod, u_amplitudeScale * edge, disp, nrm, jac, rel);
127
+ oceanWaveSum(fieldXZ, cellLod, u_amplitudeScale * edge * shoal, disp, nrm, jac, rel);
90
128
 
91
129
  vFoam = oceanFoam(jac, rel, vec3(fieldXZ.x, 0.0, fieldXZ.y));
92
130
  vRelHeight = rel;
93
131
 
94
- // Open water until the refraction grab lands; the shoreline reads its depth
95
- // from that, and from the terrain field when it is included.
96
- vDepthFactor = 1.0;
132
+ // 1 in open water, ramping to 0 as the bottom comes up (shallow colour). Open
133
+ // water everywhere without terrain, until the refraction grab gives depth for
134
+ // anything else standing in the water.
135
+ vDepthFactor = saturate(vShoreDepth / max(u_shoreDepth, 0.05));
97
136
 
98
137
  // Displacement is in field space, which for both hosts is object space up to a
99
138
  // translation - so it can be added to transformed directly. Deriving it from
@@ -148,6 +187,11 @@ varying float vFoam;
148
187
  varying float vRelHeight;
149
188
  varying float vDist;
150
189
  varying float vDepthFactor;
190
+ varying float vShoreDepth;
191
+ varying float vTerrainShadow;
192
+
193
+ uniform float u_shoreDepth;
194
+ uniform float u_shoreFoam;
151
195
 
152
196
  void main(){
153
197
  vec3 viewDir = normalize(vWorld - cameraPosition);
@@ -179,7 +223,19 @@ void main(){
179
223
  sceneShadow = mix(1.0, getShadowMask(), u_receiveShadows);
180
224
  #endif
181
225
 
182
- vec3 col = oceanLight(vWorld, n, viewDir, vFoam, vRelHeight, sceneShadow, vDepthFactor, roughAA, vec3(0.0));
226
+ sceneShadow *= vTerrainShadow;
227
+
228
+ // Shore foam: a band where the ground comes up through the surface, broken by
229
+ // drifting noise so it reads as wash rather than a painted outline. It also
230
+ // covers the hard depth-buffer edge where the water plane meets the rock.
231
+ float foam = vFoam;
232
+ if (u_shoreFoam > 0.0 && vShoreDepth < 1.0e3) {
233
+ float band = 1.0 - smoothstep(0.0, max(u_shoreDepth * 0.35, 0.05), vShoreDepth);
234
+ float wash = oNoised(vWorld.xz * 0.35 + vec2(u_time * 0.15, -u_time * 0.07)).x * 0.5 + 0.5;
235
+ foam = max(foam, saturate(band * (0.45 + 0.55 * wash) * u_shoreFoam));
236
+ }
237
+
238
+ vec3 col = oceanLight(vWorld, n, viewDir, foam, vRelHeight, sceneShadow, vDepthFactor, roughAA, vec3(0.0));
183
239
  col = oceanAerial(col, viewDir, vDist);
184
240
  col *= u_exposure;
185
241
 
@@ -190,6 +246,36 @@ void main(){
190
246
  #include <fog_fragment>
191
247
  }
192
248
  `;
249
+ /** The terrain field's uniforms (terrainFormUniforms), at harmless values until
250
+ * applyTerrainFieldUniforms fills them. u_sunShadow here is the WATER's
251
+ * terrainShadow strength, steps and distance its own quality knobs. */
252
+ function terrainFieldDefaults() {
253
+ return {
254
+ u_terrainType: 2,
255
+ u_elevation: 180,
256
+ u_seaLevel: 0,
257
+ u_baseScale: 1 / 2600,
258
+ u_octaves: 8,
259
+ u_lacunarity: 2.06,
260
+ u_gain: 0.46,
261
+ u_ridge: 0.05,
262
+ u_warpStrength: 0.35,
263
+ u_warpScale: 0.6,
264
+ u_erosion: 0.45,
265
+ u_terraces: 0,
266
+ u_terraceSharp: 0.6,
267
+ u_bearingDir: new THREE.Vector2(0.978, 0.208),
268
+ u_duneFreq: (2 * Math.PI) / 340,
269
+ u_duneAsym: 0.62,
270
+ u_plateau: 0,
271
+ u_valleyDepth: 0,
272
+ u_valleyWidth: 0.25,
273
+ u_sunShadow: 1,
274
+ u_shadowSoftness: 12,
275
+ u_shadowDistance: 4000,
276
+ u_shadowSteps: 10,
277
+ };
278
+ }
193
279
  function emptyWaveTable() {
194
280
  return Array.from({ length: MAX_WAVES }, () => new THREE.Vector4());
195
281
  }
@@ -226,6 +312,11 @@ export const oceanMaterialDefaults = {
226
312
  u_exposure: 1,
227
313
  u_curvature: 1 / (2 * 6371000),
228
314
  u_receiveShadows: 1,
315
+ // Shoreline (applyOceanShore). Read with or without terrain; the terrain
316
+ // field's own uniforms below only when OCEAN_TERRAIN is defined.
317
+ u_shoreDepth: 3,
318
+ u_shoreFoam: 1,
319
+ ...terrainFieldDefaults(),
229
320
  // Shared with the cloud and terrain materials, set by the same
230
321
  // applySunUniforms() off the same useCloudSun state.
231
322
  u_sunDir: new THREE.Vector3(0.35, 0.42, 0.84).normalize(),
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/triggers/hosts/actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG3F,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,YAAY,EACrC,CAAC;AAE9D,0EAA0E;AAC1E,eAAO,MAAM,eAAe,GAAI,QAAQ,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,eAAe,EACY,CAAC;AAEjH,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAUxF"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../src/triggers/hosts/actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG3F,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,YAAY,EACrC,CAAC;AAE9D,0EAA0E;AAC1E,eAAO,MAAM,eAAe,GAAI,QAAQ,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,eAAe,EACY,CAAC;AAEjH,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAWxF"}
@@ -14,6 +14,8 @@ export function runActionCommands(action, mode) {
14
14
  runCommand({ ...c, command: mode }, { source });
15
15
  else if (c.kind === 'action')
16
16
  runCommand({ ...c, command: mode }, { source });
17
+ else if (c.kind === 'change')
18
+ runCommand({ ...c, command: mode }, { source });
17
19
  else if (mode === 'apply')
18
20
  runCommand(c, { source });
19
21
  else if (c.command === 'play' || c.command === 'toggle')
@@ -16,7 +16,7 @@ ClipsRuntime.setCueRunner((cmd, mode, { effects, host, timelineId, getAction })
16
16
  // fire: one-shot — an effect plays (apply), anything else runs its own command
17
17
  const run = mode === 'fire'
18
18
  ? (cmd.kind === 'effect' ? { ...cmd, command: 'apply' } : cmd)
19
- : cmd.kind === 'effect' || cmd.kind === 'effectClip' || cmd.kind === 'action' ? { ...cmd, command: mode } : cmd;
19
+ : cmd.kind === 'effect' || cmd.kind === 'effectClip' || cmd.kind === 'action' || cmd.kind === 'change' ? { ...cmd, command: mode } : cmd;
20
20
  runCommand(run, { source, chain: [], effects, ...(catalog ? { catalog } : {}) });
21
21
  return true;
22
22
  });
@@ -0,0 +1,4 @@
1
+ export declare const changeLayerId: (c: {
2
+ id: string;
3
+ }) => string;
4
+ //# sourceMappingURL=change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../../../src/triggers/kinds/change.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,aAAa,GAAI,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,WAAqB,CAAC"}
@@ -0,0 +1,50 @@
1
+ // Triggerable: an inline change — an action's targets (element + settings patch) without
2
+ // the action. On lays the patches over the elements as a silent SceneActions layer
3
+ // (`change:<id>`): the elements re-render with them, exactly as with an action, but nothing
4
+ // lists it as an applied action. Off removes the layer. A timeline's Change cue.
5
+ //
6
+ // Collisions: when another action / change / the timeline's switch tracks already set the
7
+ // same settings on an element, it is logged as a clash — not resolved (the last one to
8
+ // change sits on top).
9
+ import { SceneActions } from '@3driseai/3drise-core';
10
+ import { defineTriggerable } from '../registry.js';
11
+ import { logTrigger } from '../log.js';
12
+ import { currentChain } from '../engine.js';
13
+ const ENV = new Set(['camera', 'sky', 'clouds', 'ocean', 'terrain']);
14
+ export const changeLayerId = (c) => `change:${c.id}`;
15
+ const ownerName = (o) => (o.startsWith('layer:change:') ? `change ${o.slice(13)}` : o === 'layer:timeline' ? 'a switch track' : `action ${o}`);
16
+ const patchesOf = (c) => {
17
+ const out = {};
18
+ for (const t of c.targets ?? [])
19
+ if (t?.state && t.patch && Object.keys(t.patch).length)
20
+ out[t.state] = t.patch;
21
+ return out;
22
+ };
23
+ defineTriggerable({
24
+ kind: 'change',
25
+ commands: ['apply', 'revert', 'toggle'],
26
+ timeline: 'state',
27
+ targets: (c) => (c.targets ?? []).map(t => t.state).filter(s => s && !ENV.has(s)),
28
+ subject: (c) => c.label || `change ${c.id}`,
29
+ claimKey: (c) => `change:${c.id}`,
30
+ isOn: (c) => SceneActions.hasLayer(changeLayerId(c)),
31
+ run: (c, ctx) => {
32
+ const id = changeLayerId(c);
33
+ const on = c.command === 'apply' || (c.command === 'toggle' && !SceneActions.hasLayer(id));
34
+ if (!on) {
35
+ SceneActions.setLayer(id, null);
36
+ return;
37
+ }
38
+ const patches = patchesOf(c);
39
+ for (const [state, patch] of Object.entries(patches)) {
40
+ const others = SceneActions.overlaps(state, patch, `layer:${id}`);
41
+ if (others.length) {
42
+ logTrigger({
43
+ type: 'clash', kind: 'change', subject: c.label || id, source: ctx.source, chain: currentChain(),
44
+ detail: `sets the same settings on ${state} as ${others.map(ownerName).join(', ')} — the last one to change wins`,
45
+ });
46
+ }
47
+ }
48
+ SceneActions.setLayer(id, patches);
49
+ },
50
+ });
@@ -1,4 +1,5 @@
1
1
  import './effects';
2
2
  import './action';
3
3
  import './animations';
4
+ import './change';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/triggers/kinds/index.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,CAAC;AACnB,OAAO,UAAU,CAAC;AAClB,OAAO,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/triggers/kinds/index.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,CAAC;AACnB,OAAO,UAAU,CAAC;AAClB,OAAO,cAAc,CAAC;AACtB,OAAO,UAAU,CAAC"}
@@ -2,3 +2,4 @@
2
2
  import './effects.js';
3
3
  import './action.js';
4
4
  import './animations.js';
5
+ import './change.js';
@@ -13,6 +13,10 @@ declare class CameraSingleton {
13
13
  animateCameraPosition(position: Vector3Array): Promise<void>;
14
14
  setCamera(camera: PerspectiveCamera): void;
15
15
  getCamera(): PerspectiveCamera | null;
16
+ /** The live OrbitControls (registered by CameraController) — controllers drag it directly. */
17
+ private controls;
18
+ setControls(controls: any): void;
19
+ getControls(): any;
16
20
  getPosition(): Vector3;
17
21
  getRotation(): Euler;
18
22
  isSynced(position: Vector3Array, orientation: Vector3Array | [number, number, number, number]): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"CameraSingleton.d.ts","sourceRoot":"","sources":["../../src/utils/CameraSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAsB,OAAO,EAAE,KAAK,EAAc,MAAM,OAAO,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAExF,cAAM,eAAe;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IACxB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAe;;IAEnC,MAAM,CAAC,WAAW,IAAI,eAAe;IAMrC,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB5D,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAM1C,SAAS,IAAI,iBAAiB,GAAG,IAAI;IACrC,WAAW,IAAI,OAAO;IACtB,WAAW,IAAI,KAAK;IACpB,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAyBvG,iBAAiB,IAAI,OAAO;IAI5B,MAAM,IAAI,MAAM;IAChB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAI3C,OAAO,CAAC,eAAe;IAGvB,WAAW,IAAI,OAAO;IACtB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM;IAG5C,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAM7B,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG;QAC9C,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAClB;IAeT,wBAAwB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG;QAC5B,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;KACnB;IAqBT,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,OAAO,GAAE,MAAU,GAAG,OAAO;IA6CvH,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI;IAIhF,mBAAmB,CAAC,OAAO,GAAE,MAAc,GAAG,OAAO;CAiBxD;AACD,eAAO,MAAM,aAAa,EAAE,eAA+C,CAAC;AAC5E,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"CameraSingleton.d.ts","sourceRoot":"","sources":["../../src/utils/CameraSingleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAsB,OAAO,EAAE,KAAK,EAAc,MAAM,OAAO,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAExF,cAAM,eAAe;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;IACxB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAe;;IAEnC,MAAM,CAAC,WAAW,IAAI,eAAe;IAMrC,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB5D,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAM1C,SAAS,IAAI,iBAAiB,GAAG,IAAI;IACrC,8FAA8F;IAC9F,OAAO,CAAC,QAAQ,CAAa;IAC7B,WAAW,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI;IAChC,WAAW,IAAI,GAAG;IAClB,WAAW,IAAI,OAAO;IACtB,WAAW,IAAI,KAAK;IACpB,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAyBvG,iBAAiB,IAAI,OAAO;IAI5B,MAAM,IAAI,MAAM;IAChB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAI3C,OAAO,CAAC,eAAe;IAGvB,WAAW,IAAI,OAAO;IACtB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM;IAG5C,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAM7B,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG;QAC9C,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAClB;IAeT,wBAAwB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG;QAC5B,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,OAAO,CAAC;QACpB,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;KACnB;IAqBT,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,YAAY,EAAE,OAAO,GAAE,MAAU,GAAG,OAAO;IA6CvH,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI;IAIhF,mBAAmB,CAAC,OAAO,GAAE,MAAc,GAAG,OAAO;CAiBxD;AACD,eAAO,MAAM,aAAa,EAAE,eAA+C,CAAC;AAC5E,eAAe,aAAa,CAAC"}
@@ -43,6 +43,10 @@ class CameraSingleton {
43
43
  this.notifyCallbacks();
44
44
  }
45
45
  getCamera() { return this.camera; }
46
+ /** The live OrbitControls (registered by CameraController) — controllers drag it directly. */
47
+ controls = null;
48
+ setControls(controls) { this.controls = controls; }
49
+ getControls() { return this.controls; }
46
50
  getPosition() { return this.camera ? this.camera.position.clone() : new Vector3(); }
47
51
  getRotation() { return this.camera ? this.camera.rotation.clone() : new Euler(); }
48
52
  isSynced(position, orientation) {
@@ -0,0 +1,2 @@
1
+ export declare function isMobileDevice(): boolean;
2
+ //# sourceMappingURL=deviceTier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceTier.d.ts","sourceRoot":"","sources":["../../src/utils/deviceTier.ts"],"names":[],"mappings":"AAOA,wBAAgB,cAAc,IAAI,OAAO,CAOxC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Coarse device tier, for render-time quality caps. A phone or tablet: a coarse
3
+ * primary pointer on a small screen. Read once — it does not change while a page
4
+ * is open, and render code must not branch on something that flickers.
5
+ */
6
+ let cached = null;
7
+ export function isMobileDevice() {
8
+ if (cached !== null)
9
+ return cached;
10
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function')
11
+ return (cached = false);
12
+ const coarse = window.matchMedia('(pointer: coarse)').matches;
13
+ const shortSide = Math.min(window.screen?.width ?? 0, window.screen?.height ?? 0);
14
+ cached = coarse && shortSide > 0 && shortSide < 1000;
15
+ return cached;
16
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Draw order of the camera-centred environment surfaces.
3
+ *
4
+ * three sorts opaque objects by renderOrder, then by MATERIAL ID, then by depth.
5
+ * The world ocean and the terrain clipmaps are both centred on the camera, so the
6
+ * depth tie never helps, and with renderOrder left at 0 the material id decides:
7
+ * whichever surface was created last draws last. That made the frame cost depend
8
+ * on mount order — measured 13 ms vs 22-27 ms GPU in the same view — because when
9
+ * the terrain drew first, every terrain pixel under the sea ran the full terrain
10
+ * shader (textures, 8 noise octaves) and was then painted over by water.
11
+ *
12
+ * Fixed order instead, all below the scene's objects (0):
13
+ * 1. water, inner rings first (cheap shader; hides the seabed from the depth test)
14
+ * 2. terrain, inner rings first (near ground hides far ground: front to back)
15
+ * Drawing near-to-far is what lets the early depth test throw hidden pixels away
16
+ * before their shader runs. Wasted water pixels behind land are cheap; wasted
17
+ * terrain pixels under water were most of the frame.
18
+ */
19
+ export declare const OCEAN_DRAW_ORDER = -40;
20
+ export declare const TERRAIN_DRAW_ORDER = -20;
21
+ /** Inner ring (level 0) first, then outward. */
22
+ export declare const ringDrawOrder: (base: number, level: number) => number;
23
+ //# sourceMappingURL=environmentDrawOrder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environmentDrawOrder.d.ts","sourceRoot":"","sources":["../../src/utils/environmentDrawOrder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,gDAAgD;AAChD,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,WAAiB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Draw order of the camera-centred environment surfaces.
3
+ *
4
+ * three sorts opaque objects by renderOrder, then by MATERIAL ID, then by depth.
5
+ * The world ocean and the terrain clipmaps are both centred on the camera, so the
6
+ * depth tie never helps, and with renderOrder left at 0 the material id decides:
7
+ * whichever surface was created last draws last. That made the frame cost depend
8
+ * on mount order — measured 13 ms vs 22-27 ms GPU in the same view — because when
9
+ * the terrain drew first, every terrain pixel under the sea ran the full terrain
10
+ * shader (textures, 8 noise octaves) and was then painted over by water.
11
+ *
12
+ * Fixed order instead, all below the scene's objects (0):
13
+ * 1. water, inner rings first (cheap shader; hides the seabed from the depth test)
14
+ * 2. terrain, inner rings first (near ground hides far ground: front to back)
15
+ * Drawing near-to-far is what lets the early depth test throw hidden pixels away
16
+ * before their shader runs. Wasted water pixels behind land are cheap; wasted
17
+ * terrain pixels under water were most of the frame.
18
+ */
19
+ export const OCEAN_DRAW_ORDER = -40;
20
+ export const TERRAIN_DRAW_ORDER = -20;
21
+ /** Inner ring (level 0) first, then outward. */
22
+ export const ringDrawOrder = (base, level) => base + level;
@@ -2,6 +2,13 @@ import * as THREE from 'three';
2
2
  import type { TerrainConfig, TerrainQualityConfig } from '@3driseai/3drise-core';
3
3
  import type { TerrainTextureState } from '../hooks/useTerrainTextures';
4
4
  import type { CloudSunState } from '../hooks/useCloudSun';
5
+ /**
6
+ * The height field's own uniforms (terrainFormUniforms): landform, scale, octaves,
7
+ * warp, erosion, shaping. Shared by the terrain material and by every material that
8
+ * includes `terrainFieldOnly` to read the ground — the ocean, for its shoreline —
9
+ * so the two can never disagree about where the ground is.
10
+ */
11
+ export declare function applyTerrainFieldUniforms(material: THREE.ShaderMaterial, config: TerrainConfig): void;
5
12
  export declare function applyTerrainUniforms(material: THREE.ShaderMaterial, config: TerrainConfig, quality: TerrainQualityConfig): void;
6
13
  export default applyTerrainUniforms;
7
14
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"terrainUniforms.d.ts","sourceRoot":"","sources":["../../src/utils/terrainUniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAe,MAAM,uBAAuB,CAAC;AAE9F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAoD1D,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,oBAAoB,GAC9B,IAAI,CAwDN;AAED,eAAe,oBAAoB,CAAC;AAUpC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,mBAAmB,GACzB,IAAI,CAyDN;AAiCD,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CA4BlG;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAwC5F"}
1
+ {"version":3,"file":"terrainUniforms.d.ts","sourceRoot":"","sources":["../../src/utils/terrainUniforms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAe,MAAM,uBAAuB,CAAC;AAE9F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAoD1D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAwBrG;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,oBAAoB,GAC9B,IAAI,CAqCN;AAED,eAAe,oBAAoB,CAAC;AAUpC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,mBAAmB,GACzB,IAAI,CAyDN;AAiCD,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CA4BlG;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAwC5F"}
@@ -45,9 +45,15 @@ function setColor(uniform, hex) {
45
45
  return;
46
46
  uniform.value.setStyle(hex, THREE.SRGBColorSpace);
47
47
  }
48
- export function applyTerrainUniforms(material, config, quality) {
48
+ /**
49
+ * The height field's own uniforms (terrainFormUniforms): landform, scale, octaves,
50
+ * warp, erosion, shaping. Shared by the terrain material and by every material that
51
+ * includes `terrainFieldOnly` to read the ground — the ocean, for its shoreline —
52
+ * so the two can never disagree about where the ground is.
53
+ */
54
+ export function applyTerrainFieldUniforms(material, config) {
49
55
  const u = material.uniforms;
50
- if (!u)
56
+ if (!u || !u.u_terrainType)
51
57
  return;
52
58
  u.u_terrainType.value = TYPE_INDEX[config.terrainType] ?? 2;
53
59
  u.u_elevation.value = Math.max(config.elevation, 0.01);
@@ -68,6 +74,13 @@ export function applyTerrainUniforms(material, config, quality) {
68
74
  u.u_plateau.value = config.plateau;
69
75
  u.u_valleyDepth.value = config.valleyDepth;
70
76
  u.u_valleyWidth.value = config.valleyWidth;
77
+ u.u_shadowSoftness.value = config.shadowSoftness;
78
+ }
79
+ export function applyTerrainUniforms(material, config, quality) {
80
+ const u = material.uniforms;
81
+ if (!u)
82
+ return;
83
+ applyTerrainFieldUniforms(material, config);
71
84
  setColor(u.u_lowColor, config.lowColor);
72
85
  setColor(u.u_midColor, config.midColor);
73
86
  setColor(u.u_rockColor, config.rockColor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3driseai/3drise-viewer",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
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.23"
42
+ "@3driseai/3drise-core": "^1.0.24"
43
43
  }
44
44
  }