@zephyr3d/scene 0.9.25 → 0.9.27

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 (299) hide show
  1. package/dist/animation/animationset.js +92 -30
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/hair/gpu_hair_simulation.js +1090 -0
  4. package/dist/animation/hair/gpu_hair_simulation.js.map +1 -0
  5. package/dist/animation/joint_dynamics/controller.js +7 -5
  6. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  7. package/dist/animation/joint_dynamics/convex_collider.js +320 -0
  8. package/dist/animation/joint_dynamics/convex_collider.js.map +1 -0
  9. package/dist/animation/joint_dynamics/joint_dynamics_system.js +81 -5
  10. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  11. package/dist/animation/morphtrack.js +3 -4
  12. package/dist/animation/morphtrack.js.map +1 -1
  13. package/dist/animation/skeleton.js +79 -25
  14. package/dist/animation/skeleton.js.map +1 -1
  15. package/dist/animation/spring/multi_chain_spring_system.js +577 -179
  16. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  17. package/dist/animation/spring/spring_collider.js +4 -3
  18. package/dist/animation/spring/spring_collider.js.map +1 -1
  19. package/dist/animation/spring/spring_node_pose_tracker.js +40 -0
  20. package/dist/animation/spring/spring_node_pose_tracker.js.map +1 -0
  21. package/dist/animation/spring/spring_particle.js +2 -0
  22. package/dist/animation/spring/spring_particle.js.map +1 -1
  23. package/dist/animation/spring/spring_system.js +11 -3
  24. package/dist/animation/spring/spring_system.js.map +1 -1
  25. package/dist/animation/spring_modifier.js +10 -0
  26. package/dist/animation/spring_modifier.js.map +1 -1
  27. package/dist/app/engine.js +53 -43
  28. package/dist/app/engine.js.map +1 -1
  29. package/dist/app/scriptingsystem.js +119 -6
  30. package/dist/app/scriptingsystem.js.map +1 -1
  31. package/dist/app/scriptregistry.js +3 -2
  32. package/dist/app/scriptregistry.js.map +1 -1
  33. package/dist/asset/assetmanager.js +284 -67
  34. package/dist/asset/assetmanager.js.map +1 -1
  35. package/dist/asset/loaders/zhair/zhair_format.js +288 -0
  36. package/dist/asset/loaders/zhair/zhair_format.js.map +1 -0
  37. package/dist/asset/loaders/zhair/zhair_loader.js +221 -0
  38. package/dist/asset/loaders/zhair/zhair_loader.js.map +1 -0
  39. package/dist/asset/model.js +184 -69
  40. package/dist/asset/model.js.map +1 -1
  41. package/dist/camera/camera.js +268 -44
  42. package/dist/camera/camera.js.map +1 -1
  43. package/dist/camera/perspectivecamera.js +3 -1
  44. package/dist/camera/perspectivecamera.js.map +1 -1
  45. package/dist/index.d.ts +9044 -5139
  46. package/dist/index.js +17 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/material/eye.js +932 -0
  49. package/dist/material/eye.js.map +1 -0
  50. package/dist/material/hair.js +917 -0
  51. package/dist/material/hair.js.map +1 -0
  52. package/dist/material/hairstrand.js +842 -0
  53. package/dist/material/hairstrand.js.map +1 -0
  54. package/dist/material/hairstrand_data.js +162 -0
  55. package/dist/material/hairstrand_data.js.map +1 -0
  56. package/dist/material/lambert.js +5 -2
  57. package/dist/material/lambert.js.map +1 -1
  58. package/dist/material/material.js +48 -10
  59. package/dist/material/material.js.map +1 -1
  60. package/dist/material/meshmaterial.js +120 -19
  61. package/dist/material/meshmaterial.js.map +1 -1
  62. package/dist/material/mixins/albedocolor.js +1 -1
  63. package/dist/material/mixins/albedocolor.js.map +1 -1
  64. package/dist/material/mixins/lightmodel/blinnphong.js +5 -3
  65. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  66. package/dist/material/mixins/lightmodel/lambert.js +5 -4
  67. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  68. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +3 -3
  69. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  70. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  71. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  72. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +3 -3
  73. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  74. package/dist/material/mixins/lit.js +106 -19
  75. package/dist/material/mixins/lit.js.map +1 -1
  76. package/dist/material/mixins/pbr/common.js +4 -4
  77. package/dist/material/mixins/pbr/common.js.map +1 -1
  78. package/dist/material/mixins/texture.js +48 -11
  79. package/dist/material/mixins/texture.js.map +1 -1
  80. package/dist/material/mtoon.js +6 -5
  81. package/dist/material/mtoon.js.map +1 -1
  82. package/dist/material/pbrblueprint.js +146 -28
  83. package/dist/material/pbrblueprint.js.map +1 -1
  84. package/dist/material/pbrblueprint_instance.js +501 -0
  85. package/dist/material/pbrblueprint_instance.js.map +1 -0
  86. package/dist/material/pbrmr.js +15 -16
  87. package/dist/material/pbrmr.js.map +1 -1
  88. package/dist/material/shader/helper.js +734 -23
  89. package/dist/material/shader/helper.js.map +1 -1
  90. package/dist/material/shader/terrain_blend.js +55 -0
  91. package/dist/material/shader/terrain_blend.js.map +1 -0
  92. package/dist/material/skin.js +192 -32
  93. package/dist/material/skin.js.map +1 -1
  94. package/dist/material/spriteblueprint.js +16 -1
  95. package/dist/material/spriteblueprint.js.map +1 -1
  96. package/dist/material/subsurfaceprofile.js +86 -23
  97. package/dist/material/subsurfaceprofile.js.map +1 -1
  98. package/dist/material/water.js +2059 -72
  99. package/dist/material/water.js.map +1 -1
  100. package/dist/posteffect/bloom.js +167 -7
  101. package/dist/posteffect/bloom.js.map +1 -1
  102. package/dist/posteffect/coloradjust.js +2 -1
  103. package/dist/posteffect/coloradjust.js.map +1 -1
  104. package/dist/posteffect/compositor.js.map +1 -1
  105. package/dist/posteffect/fxaa.js +2 -1
  106. package/dist/posteffect/fxaa.js.map +1 -1
  107. package/dist/posteffect/grayscale.js +3 -1
  108. package/dist/posteffect/grayscale.js.map +1 -1
  109. package/dist/posteffect/motionblur.js +664 -56
  110. package/dist/posteffect/motionblur.js.map +1 -1
  111. package/dist/posteffect/posteffect.js +12 -1
  112. package/dist/posteffect/posteffect.js.map +1 -1
  113. package/dist/posteffect/sao.js +46 -44
  114. package/dist/posteffect/sao.js.map +1 -1
  115. package/dist/posteffect/skinsss.js +368 -69
  116. package/dist/posteffect/skinsss.js.map +1 -1
  117. package/dist/posteffect/ssgi.js +16 -9
  118. package/dist/posteffect/ssgi.js.map +1 -1
  119. package/dist/posteffect/ssr.js +3 -0
  120. package/dist/posteffect/ssr.js.map +1 -1
  121. package/dist/posteffect/sss.js +121 -36
  122. package/dist/posteffect/sss.js.map +1 -1
  123. package/dist/posteffect/taa.js.map +1 -1
  124. package/dist/posteffect/tonemap.js +44 -1
  125. package/dist/posteffect/tonemap.js.map +1 -1
  126. package/dist/render/abuffer_oit.js +8 -2
  127. package/dist/render/abuffer_oit.js.map +1 -1
  128. package/dist/render/clipmap.js +156 -5
  129. package/dist/render/clipmap.js.map +1 -1
  130. package/dist/render/cull_visitor.js +20 -0
  131. package/dist/render/cull_visitor.js.map +1 -1
  132. package/dist/render/depthpass.js +36 -2
  133. package/dist/render/depthpass.js.map +1 -1
  134. package/dist/render/drawable_mixin.js +26 -1
  135. package/dist/render/drawable_mixin.js.map +1 -1
  136. package/dist/render/dualdepthpeeling_oit.js +3 -2
  137. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  138. package/dist/render/envlight.js +1 -1
  139. package/dist/render/envlight.js.map +1 -1
  140. package/dist/render/fbm_wavegenerator.js +6 -3
  141. package/dist/render/fbm_wavegenerator.js.map +1 -1
  142. package/dist/render/fft_wavegenerator.js +57 -15
  143. package/dist/render/fft_wavegenerator.js.map +1 -1
  144. package/dist/render/gerstner_wavegenerator.js +130 -20
  145. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  146. package/dist/render/globalbindgroup_allocator.js +3 -0
  147. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  148. package/dist/render/hzb.js +80 -22
  149. package/dist/render/hzb.js.map +1 -1
  150. package/dist/render/lightpass.js +6 -3
  151. package/dist/render/lightpass.js.map +1 -1
  152. package/dist/render/oit.js +29 -0
  153. package/dist/render/oit.js.map +1 -0
  154. package/dist/render/render_queue.js +39 -0
  155. package/dist/render/render_queue.js.map +1 -1
  156. package/dist/render/renderer.js +4 -0
  157. package/dist/render/renderer.js.map +1 -1
  158. package/dist/render/rendergraph/blackboard.js +1 -0
  159. package/dist/render/rendergraph/blackboard.js.map +1 -1
  160. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  161. package/dist/render/rendergraph/executor.js +2 -0
  162. package/dist/render/rendergraph/executor.js.map +1 -1
  163. package/dist/render/rendergraph/forward_plus_builder.js +379 -10
  164. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  165. package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
  166. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
  167. package/dist/render/rendergraph/history_resources.js +8 -1
  168. package/dist/render/rendergraph/history_resources.js.map +1 -1
  169. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  170. package/dist/render/rendergraph/texture_affinity_cache.js +1 -1
  171. package/dist/render/rendergraph/texture_affinity_cache.js.map +1 -1
  172. package/dist/render/rendergraph/types.js.map +1 -1
  173. package/dist/render/shadow_mask_pass.js +73 -8
  174. package/dist/render/shadow_mask_pass.js.map +1 -1
  175. package/dist/render/sky.js +166 -126
  176. package/dist/render/sky.js.map +1 -1
  177. package/dist/render/underwater.js +624 -0
  178. package/dist/render/underwater.js.map +1 -0
  179. package/dist/render/water_caustics.js +1380 -0
  180. package/dist/render/water_caustics.js.map +1 -0
  181. package/dist/render/weightedblended_oit.js +3 -2
  182. package/dist/render/weightedblended_oit.js.map +1 -1
  183. package/dist/scene/basesprite.js +8 -0
  184. package/dist/scene/basesprite.js.map +1 -1
  185. package/dist/scene/batchgroup.js +3 -0
  186. package/dist/scene/batchgroup.js.map +1 -1
  187. package/dist/scene/environment.js +4 -1
  188. package/dist/scene/environment.js.map +1 -1
  189. package/dist/scene/hair.js +963 -0
  190. package/dist/scene/hair.js.map +1 -0
  191. package/dist/scene/light.js +5 -1
  192. package/dist/scene/light.js.map +1 -1
  193. package/dist/scene/mesh.js +481 -47
  194. package/dist/scene/mesh.js.map +1 -1
  195. package/dist/scene/meshdrawable.js +6 -0
  196. package/dist/scene/meshdrawable.js.map +1 -1
  197. package/dist/scene/msdftext.js +3 -0
  198. package/dist/scene/msdftext.js.map +1 -1
  199. package/dist/scene/msdftextsprite.js +3 -0
  200. package/dist/scene/msdftextsprite.js.map +1 -1
  201. package/dist/scene/particlesys.js +6 -0
  202. package/dist/scene/particlesys.js.map +1 -1
  203. package/dist/scene/scene.js +3 -0
  204. package/dist/scene/scene.js.map +1 -1
  205. package/dist/scene/scene_node.js +6 -1
  206. package/dist/scene/scene_node.js.map +1 -1
  207. package/dist/scene/terrain-cm/grass.js +3 -0
  208. package/dist/scene/terrain-cm/grass.js.map +1 -1
  209. package/dist/scene/terrain-cm/grassmaterial.js +3 -0
  210. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  211. package/dist/scene/terrain-cm/terrain-cm.js +6 -0
  212. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  213. package/dist/scene/terrain-cm/texture_cache.js +309 -0
  214. package/dist/scene/terrain-cm/texture_cache.js.map +1 -0
  215. package/dist/scene/water.js +546 -4
  216. package/dist/scene/water.js.map +1 -1
  217. package/dist/shaders/atmosphere.js.map +1 -1
  218. package/dist/shaders/diffusion.js +54 -0
  219. package/dist/shaders/diffusion.js.map +1 -0
  220. package/dist/shaders/shadow.js +33 -21
  221. package/dist/shaders/shadow.js.map +1 -1
  222. package/dist/shaders/temporal.js +71 -33
  223. package/dist/shaders/temporal.js.map +1 -1
  224. package/dist/shaders/water.js +22 -19
  225. package/dist/shaders/water.js.map +1 -1
  226. package/dist/shaders/water_medium.js +56 -0
  227. package/dist/shaders/water_medium.js.map +1 -0
  228. package/dist/shadow/dom.js +546 -0
  229. package/dist/shadow/dom.js.map +1 -0
  230. package/dist/shadow/pcf_opt.js +3 -5
  231. package/dist/shadow/pcf_opt.js.map +1 -1
  232. package/dist/shadow/pcf_pd.js +1 -1
  233. package/dist/shadow/pcf_pd.js.map +1 -1
  234. package/dist/shadow/receiver_bias.js +41 -0
  235. package/dist/shadow/receiver_bias.js.map +1 -0
  236. package/dist/shadow/shader.js +20 -60
  237. package/dist/shadow/shader.js.map +1 -1
  238. package/dist/shadow/shadow_impl.js +89 -0
  239. package/dist/shadow/shadow_impl.js.map +1 -1
  240. package/dist/shadow/shadow_region.js +1 -1
  241. package/dist/shadow/shadow_region.js.map +1 -1
  242. package/dist/shadow/shadowmapper.js +150 -37
  243. package/dist/shadow/shadowmapper.js.map +1 -1
  244. package/dist/shapes/shape.js +11 -2
  245. package/dist/shapes/shape.js.map +1 -1
  246. package/dist/shapes/sphere.js +50 -9
  247. package/dist/shapes/sphere.js.map +1 -1
  248. package/dist/utility/blueprint/common/constants.js +112 -2
  249. package/dist/utility/blueprint/common/constants.js.map +1 -1
  250. package/dist/utility/blueprint/material/func.js +142 -49
  251. package/dist/utility/blueprint/material/func.js.map +1 -1
  252. package/dist/utility/blueprint/material/ir.js +490 -25
  253. package/dist/utility/blueprint/material/ir.js.map +1 -1
  254. package/dist/utility/blueprint/material/texture.js +898 -4
  255. package/dist/utility/blueprint/material/texture.js.map +1 -1
  256. package/dist/utility/serialization/manager.js +434 -101
  257. package/dist/utility/serialization/manager.js.map +1 -1
  258. package/dist/utility/serialization/scene/animation.js +401 -5
  259. package/dist/utility/serialization/scene/animation.js.map +1 -1
  260. package/dist/utility/serialization/scene/batch.js +4 -0
  261. package/dist/utility/serialization/scene/batch.js.map +1 -1
  262. package/dist/utility/serialization/scene/camera.js +186 -26
  263. package/dist/utility/serialization/scene/camera.js.map +1 -1
  264. package/dist/utility/serialization/scene/common.js +26 -5
  265. package/dist/utility/serialization/scene/common.js.map +1 -1
  266. package/dist/utility/serialization/scene/hair.js +1141 -0
  267. package/dist/utility/serialization/scene/hair.js.map +1 -0
  268. package/dist/utility/serialization/scene/light.js +84 -4
  269. package/dist/utility/serialization/scene/light.js.map +1 -1
  270. package/dist/utility/serialization/scene/material.js +1867 -166
  271. package/dist/utility/serialization/scene/material.js.map +1 -1
  272. package/dist/utility/serialization/scene/mesh.js +231 -14
  273. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  274. package/dist/utility/serialization/scene/node.js +141 -7
  275. package/dist/utility/serialization/scene/node.js.map +1 -1
  276. package/dist/utility/serialization/scene/particle.js +4 -0
  277. package/dist/utility/serialization/scene/particle.js.map +1 -1
  278. package/dist/utility/serialization/scene/primitive.js +18 -0
  279. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  280. package/dist/utility/serialization/scene/sprite.js +4 -0
  281. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  282. package/dist/utility/serialization/scene/terrain.js +4 -0
  283. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  284. package/dist/utility/serialization/scene/text.js +4 -0
  285. package/dist/utility/serialization/scene/text.js.map +1 -1
  286. package/dist/utility/serialization/scene/water.js +1105 -21
  287. package/dist/utility/serialization/scene/water.js.map +1 -1
  288. package/dist/utility/serialization/types.js.map +1 -1
  289. package/dist/utility/shprojector.js +9 -8
  290. package/dist/utility/shprojector.js.map +1 -1
  291. package/dist/values.js +49 -2
  292. package/dist/values.js.map +1 -1
  293. package/package.json +3 -3
  294. package/dist/render/rendergraph/frame_graph_context.js +0 -41
  295. package/dist/render/rendergraph/frame_graph_context.js.map +0 -1
  296. package/dist/shaders/ssgi.js +0 -63
  297. package/dist/shaders/ssgi.js.map +0 -1
  298. package/dist/shaders/ssgi_reprojection.js +0 -118
  299. package/dist/shaders/ssgi_reprojection.js.map +0 -1
@@ -1,6 +1,6 @@
1
- import { Vector2 } from '@zephyr3d/base';
1
+ import { Vector2, Vector3 } from '@zephyr3d/base';
2
2
  import '../../../scene/scene.js';
3
- import '../../../values.js';
3
+ import { MAX_GERSTNER_WAVE_COUNT } from '../../../values.js';
4
4
  import '../../../render/render_queue.js';
5
5
  import '../../../render/primitive.js';
6
6
  import '@zephyr3d/device';
@@ -11,7 +11,10 @@ import '../../../material/unlit.js';
11
11
  import '../../../material/particle.js';
12
12
  import '../../../material/subsurfaceprofile.js';
13
13
  import '../../../material/skin.js';
14
+ import '../../../material/eye.js';
14
15
  import '../../../material/meshmaterial.js';
16
+ import '../../../material/hair.js';
17
+ import '../../../material/hairstrand.js';
15
18
  import '../../../material/grassmaterial.js';
16
19
  import '../../../material/terrain-cm.js';
17
20
  import '../../../material/pbrmr.js';
@@ -29,6 +32,7 @@ import '../../../render/clipmap.js';
29
32
  import '../../../render/envlight.js';
30
33
  import '../../../render/dualdepthpeeling_oit.js';
31
34
  import { FFTWaveGenerator } from '../../../render/fft_wavegenerator.js';
35
+ import { GerstnerWaveGenerator } from '../../../render/gerstner_wavegenerator.js';
32
36
  import { FBMWaveGenerator } from '../../../render/fbm_wavegenerator.js';
33
37
  import '../../../render/rendergraph/scene_render_context.js';
34
38
  import { GraphNode } from '../../../scene/graph_node.js';
@@ -38,12 +42,14 @@ import '../../../scene/meshdrawable.js';
38
42
  import '../../../scene/basesprite.js';
39
43
  import '../../../material/msdf_text.js';
40
44
  import { Water } from '../../../scene/water.js';
45
+ import '../../../scene/hair.js';
41
46
  import '../../../scene/scene_node.js';
42
47
  import '../../../scene/particlesys.js';
43
48
  import '../../../scene/batchgroup.js';
44
49
  import '../../../scene/terrain-cm/terrain-cm.js';
45
50
  import '../../../scene/terrain-cm/grass.js';
46
51
  import '../../../scene/raycast_visitor.js';
52
+ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../material/water.js';
47
53
 
48
54
  /** @internal */ function getFBMWaveGeneratorClass() {
49
55
  return {
@@ -274,6 +280,345 @@ import '../../../scene/raycast_visitor.js';
274
280
  }
275
281
  };
276
282
  }
283
+ /** @internal */ function getGerstnerWaveGeneratorClass() {
284
+ return {
285
+ ctor: GerstnerWaveGenerator,
286
+ name: 'GerstnerWaveGenerator',
287
+ getProps () {
288
+ return defineProps([
289
+ {
290
+ name: 'NumWaves',
291
+ description: 'Number of independent Gerstner waves summed to form the surface',
292
+ type: 'int',
293
+ options: {
294
+ minValue: 1,
295
+ maxValue: MAX_GERSTNER_WAVE_COUNT
296
+ },
297
+ get (value) {
298
+ value.num[0] = this.numWaves;
299
+ },
300
+ set (value) {
301
+ this.numWaves = value.num[0];
302
+ }
303
+ },
304
+ {
305
+ name: 'Waves',
306
+ description: 'Per-wave parameters, one entry per wave in NumWaves order',
307
+ type: 'object_array',
308
+ options: {
309
+ objectTypes: [
310
+ GerstnerWave
311
+ ]
312
+ },
313
+ get (value) {
314
+ value.object = [];
315
+ for(let i = 0; i < this.numWaves; i++){
316
+ const wave = new GerstnerWave();
317
+ wave.bind(this, i);
318
+ value.object.push(wave);
319
+ }
320
+ },
321
+ set (value) {
322
+ const waves = value.object;
323
+ // The wave count is ground truth for how many slots the shader
324
+ // reads. NumWaves and Waves are applied concurrently during
325
+ // deserialization, so this setter must leave the generator in the
326
+ // state this array implies regardless of which one runs first.
327
+ this.numWaves = waves.length;
328
+ for(let i = 0; i < waves.length; i++){
329
+ waves[i].applyTo(this, i);
330
+ }
331
+ },
332
+ add (value, index) {
333
+ const wave = value?.object?.[0];
334
+ const insertAt = index ?? this.numWaves;
335
+ this.insertWave(insertAt);
336
+ wave?.applyTo(this, insertAt);
337
+ },
338
+ delete (index) {
339
+ this.deleteWave(index);
340
+ }
341
+ },
342
+ {
343
+ name: 'FoamWidth',
344
+ description: 'Width of foam bands generated on the wave crests',
345
+ type: 'float',
346
+ default: 1.2,
347
+ options: {
348
+ animatable: true,
349
+ minValue: 0,
350
+ maxValue: 10
351
+ },
352
+ get (value) {
353
+ value.num[0] = this.foamWidth;
354
+ },
355
+ set (value) {
356
+ this.foamWidth = value.num[0];
357
+ }
358
+ },
359
+ {
360
+ name: 'FoamContrast',
361
+ description: 'Contrast of the foam pattern on Gerstner waves',
362
+ type: 'float',
363
+ default: 7.2,
364
+ options: {
365
+ animatable: true,
366
+ minValue: 0,
367
+ maxValue: 10
368
+ },
369
+ get (value) {
370
+ value.num[0] = this.foamContrast;
371
+ },
372
+ set (value) {
373
+ this.foamContrast = value.num[0];
374
+ }
375
+ }
376
+ ]);
377
+ }
378
+ };
379
+ }
380
+ /**
381
+ * A single Gerstner wave, as the editor sees one entry of the
382
+ * `Waves` object array on a {@link GerstnerWaveGenerator}.
383
+ *
384
+ * It behaves as a live view while it is bound: the field setters write the new
385
+ * value straight through to the generator's wave buffer, which is what makes an
386
+ * edit in the property panel take effect on the water immediately. Without that
387
+ * the editor would only touch this object's own fields and the surface would
388
+ * keep the previous wave until something else bumped the generator's version.
389
+ *
390
+ * The binding is transient and scoped to one editor session: `_owner` and
391
+ * `_index` are set when the `Waves` getter builds the entry, and the editor
392
+ * rebuilds the whole array from that getter after every add/delete. A copy that
393
+ * survives a list mutation is never reused, so the cached index cannot drift
394
+ * onto a different wave - the same reason it is safe to write through with it.
395
+ */ class GerstnerWave {
396
+ _owner;
397
+ _index;
398
+ _direction;
399
+ _steepness;
400
+ _amplitude;
401
+ _length;
402
+ _omni;
403
+ _originX;
404
+ _originZ;
405
+ constructor(){
406
+ this._owner = null;
407
+ this._index = -1;
408
+ this._direction = 0;
409
+ this._steepness = 0;
410
+ this._amplitude = 0;
411
+ this._length = 1;
412
+ this._omni = false;
413
+ this._originX = 0;
414
+ this._originZ = 0;
415
+ }
416
+ /**
417
+ * Binds this entry to a slot of `owner`, so the field setters write through
418
+ * to the generator. Called by the `Waves` getter and by `add`; the index is
419
+ * the slot the entry currently represents.
420
+ * @internal
421
+ */ bind(owner, index) {
422
+ this._owner = owner;
423
+ this._index = index;
424
+ this.loadFromOwner(owner, index);
425
+ }
426
+ /**
427
+ * Copies the values in slot `index` of `owner` into this object, refreshing
428
+ * the cached fields without writing back.
429
+ * @internal
430
+ */ loadFromOwner(owner, index) {
431
+ this._direction = owner.getWaveDirection(index);
432
+ this._steepness = owner.getWaveSteepness(index);
433
+ this._amplitude = owner.getWaveAmplitude(index);
434
+ this._length = owner.getWaveLength(index);
435
+ this._omni = owner.isOmniWave(index);
436
+ this._originX = owner.getOriginX(index);
437
+ this._originZ = owner.getOriginZ(index);
438
+ }
439
+ /**
440
+ * Writes this object's values into slot `index` of `owner`, unconditionally.
441
+ *
442
+ * Used by the `Waves` setter for a serialised-in array, whose entries were
443
+ * constructed without an owner, and by `add` for a freshly created one. It is
444
+ * distinct from the write-through in the field setters, which fire on each
445
+ * individual edit.
446
+ * @internal
447
+ */ applyTo(owner, index) {
448
+ owner.setWaveDirection(index, this._direction);
449
+ owner.setWaveSteepness(index, this._steepness);
450
+ owner.setWaveAmplitude(index, this._amplitude);
451
+ owner.setWaveLength(index, this._length);
452
+ owner.setOmniWave(index, this._omni);
453
+ owner.setOrigin(index, this._originX, this._originZ);
454
+ this._owner = owner;
455
+ this._index = index;
456
+ }
457
+ /** @internal */ writethrough(setter, val) {
458
+ const owner = this._owner;
459
+ if (owner) {
460
+ setter(owner, this._index, val);
461
+ }
462
+ }
463
+ /** Gets the wave direction angle in radians. */ get direction() {
464
+ return this._direction;
465
+ }
466
+ set direction(val) {
467
+ this._direction = val;
468
+ this.writethrough((o, i, v)=>o.setWaveDirection(i, v), val);
469
+ }
470
+ /** Gets the wave steepness. */ get steepness() {
471
+ return this._steepness;
472
+ }
473
+ set steepness(val) {
474
+ this._steepness = val;
475
+ this.writethrough((o, i, v)=>o.setWaveSteepness(i, v), val);
476
+ }
477
+ /** Gets the wave amplitude. */ get amplitude() {
478
+ return this._amplitude;
479
+ }
480
+ set amplitude(val) {
481
+ this._amplitude = val;
482
+ this.writethrough((o, i, v)=>o.setWaveAmplitude(i, v), val);
483
+ }
484
+ /** Gets the wave length in meters. */ get length() {
485
+ return this._length;
486
+ }
487
+ set length(val) {
488
+ this._length = val;
489
+ this.writethrough((o, i, v)=>o.setWaveLength(i, v), val);
490
+ }
491
+ /** Gets whether the wave is omni-directional. */ get omni() {
492
+ return this._omni;
493
+ }
494
+ set omni(val) {
495
+ this._omni = val;
496
+ if (this._owner) {
497
+ this._owner.setOmniWave(this._index, val);
498
+ }
499
+ }
500
+ /** Gets the origin X of an omni-directional wave. */ get originX() {
501
+ return this._originX;
502
+ }
503
+ set originX(val) {
504
+ this._originX = val;
505
+ if (this._owner) {
506
+ this._owner.setOrigin(this._index, val, this._originZ);
507
+ }
508
+ }
509
+ /** Gets the origin Z of an omni-directional wave. */ get originZ() {
510
+ return this._originZ;
511
+ }
512
+ set originZ(val) {
513
+ this._originZ = val;
514
+ if (this._owner) {
515
+ this._owner.setOrigin(this._index, this._originX, val);
516
+ }
517
+ }
518
+ }
519
+ /** @internal */ function getGerstnerWaveClass() {
520
+ return {
521
+ ctor: GerstnerWave,
522
+ name: 'GerstnerWave',
523
+ getProps () {
524
+ return defineProps([
525
+ {
526
+ name: 'Direction',
527
+ description: 'Wave direction angle in radians',
528
+ type: 'float',
529
+ options: {
530
+ animatable: true,
531
+ minValue: -3.14,
532
+ maxValue: 3.14
533
+ },
534
+ get (value) {
535
+ value.num[0] = this.direction;
536
+ },
537
+ set (value) {
538
+ this.direction = value.num[0];
539
+ }
540
+ },
541
+ {
542
+ name: 'Steepness',
543
+ description: 'Wave steepness. The sum of steepness across waves sets how sharply crests fold',
544
+ type: 'float',
545
+ options: {
546
+ animatable: true,
547
+ minValue: 0,
548
+ maxValue: 2
549
+ },
550
+ get (value) {
551
+ value.num[0] = this.steepness;
552
+ },
553
+ set (value) {
554
+ this.steepness = value.num[0];
555
+ }
556
+ },
557
+ {
558
+ name: 'Amplitude',
559
+ description: 'Wave height amplitude',
560
+ type: 'float',
561
+ options: {
562
+ animatable: true,
563
+ minValue: 0,
564
+ maxValue: 5
565
+ },
566
+ get (value) {
567
+ value.num[0] = this.amplitude;
568
+ },
569
+ set (value) {
570
+ this.amplitude = value.num[0];
571
+ }
572
+ },
573
+ {
574
+ name: 'Length',
575
+ description: 'Wave length in meters',
576
+ type: 'float',
577
+ options: {
578
+ animatable: true,
579
+ minValue: 0,
580
+ maxValue: 100
581
+ },
582
+ get (value) {
583
+ value.num[0] = this.length;
584
+ },
585
+ set (value) {
586
+ this.length = value.num[0];
587
+ }
588
+ },
589
+ {
590
+ name: 'Omni',
591
+ description: 'If true, radiates outward from an origin rather than travelling in one direction',
592
+ type: 'bool',
593
+ get (value) {
594
+ value.bool[0] = this.omni;
595
+ },
596
+ set (value) {
597
+ this.omni = value.bool[0];
598
+ }
599
+ },
600
+ {
601
+ name: 'Origin',
602
+ description: 'Origin of an omni-directional wave, ignored by directional waves',
603
+ type: 'vec2',
604
+ options: {
605
+ animatable: true,
606
+ minValue: -1e3,
607
+ maxValue: 1000
608
+ },
609
+ get (value) {
610
+ value.num[0] = this.originX;
611
+ value.num[1] = this.originZ;
612
+ },
613
+ set (value) {
614
+ this.originX = value.num[0];
615
+ this.originZ = value.num[1];
616
+ }
617
+ }
618
+ ]);
619
+ }
620
+ };
621
+ }
277
622
  /** @internal */ function getWaterClass(manager) {
278
623
  return {
279
624
  ctor: Water,
@@ -296,7 +641,8 @@ import '../../../scene/raycast_visitor.js';
296
641
  options: {
297
642
  objectTypes: [
298
643
  FFTWaveGenerator,
299
- FBMWaveGenerator
644
+ FBMWaveGenerator,
645
+ GerstnerWaveGenerator
300
646
  ]
301
647
  },
302
648
  isNullable () {
@@ -359,53 +705,791 @@ import '../../../scene/raycast_visitor.js';
359
705
  }
360
706
  },
361
707
  {
362
- name: 'DepthScale',
363
- description: 'Depth attenuation scale for the water material',
708
+ name: 'Infinite',
709
+ description: 'Draw the surface as an unbounded ocean reaching the horizon instead of a body of water ending at the node extent. Reaches the horizon without enlarging the camera far plane, so near-scene depth precision is unaffected. Leave off for ponds, lakes and pools, which have an edge.',
710
+ type: 'bool',
711
+ default: false,
712
+ get (value) {
713
+ value.bool[0] = this.infinite;
714
+ },
715
+ set (value) {
716
+ this.infinite = value.bool[0];
717
+ }
718
+ },
719
+ {
720
+ name: 'ViewDistance',
721
+ description: 'How far the surface is built out from the camera, in meters, or 0 to derive it from the true horizon distance for the camera height. Keep the sky AerialPerspectiveDistance at least this large, or the far water stops converging towards the sky colour and the hard band comes back.',
364
722
  type: 'float',
365
- default: 10,
723
+ default: 0,
724
+ options: {
725
+ minValue: 0,
726
+ maxValue: 100000
727
+ },
728
+ isHidden () {
729
+ return !this.infinite;
730
+ },
731
+ get (value) {
732
+ value.num[0] = this.viewDistance;
733
+ },
734
+ set (value) {
735
+ this.viewDistance = value.num[0];
736
+ }
737
+ },
738
+ {
739
+ name: 'CausticsEnabled',
740
+ description: 'Whether the water projects caustics onto the geometry below it',
741
+ type: 'bool',
742
+ default: true,
743
+ get (value) {
744
+ value.bool[0] = this.causticsEnabled;
745
+ },
746
+ set (value) {
747
+ this.causticsEnabled = value.bool[0];
748
+ }
749
+ },
750
+ {
751
+ name: 'CausticsIntensity',
752
+ description: 'Strength of the caustic contrast',
753
+ type: 'float',
754
+ default: 1,
366
755
  options: {
367
756
  animatable: true,
368
757
  minValue: 0,
758
+ maxValue: 5
759
+ },
760
+ isHidden () {
761
+ return !this.causticsEnabled;
762
+ },
763
+ get (value) {
764
+ value.num[0] = this.causticsIntensity;
765
+ },
766
+ set (value) {
767
+ this.causticsIntensity = value.num[0];
768
+ }
769
+ },
770
+ {
771
+ name: 'CausticsDepth',
772
+ description: 'Depth in meters below the surface where the caustics are in focus',
773
+ type: 'float',
774
+ default: 4,
775
+ options: {
776
+ animatable: true,
777
+ minValue: 0.01,
369
778
  maxValue: 100
370
779
  },
780
+ isHidden () {
781
+ return !this.causticsEnabled;
782
+ },
371
783
  get (value) {
372
- value.num[0] = this.material.depthMulti;
784
+ value.num[0] = this.causticsDepth;
373
785
  },
374
786
  set (value) {
375
- this.material.depthMulti = value.num[0];
787
+ this.causticsDepth = value.num[0];
788
+ }
789
+ },
790
+ {
791
+ name: 'CausticsRange',
792
+ description: 'Furthest distance in meters from the camera the caustic map reaches',
793
+ type: 'float',
794
+ default: 4,
795
+ options: {
796
+ minValue: 1,
797
+ maxValue: 1000
798
+ },
799
+ isHidden () {
800
+ return !this.causticsEnabled;
801
+ },
802
+ get (value) {
803
+ value.num[0] = this.causticsRange;
804
+ },
805
+ set (value) {
806
+ this.causticsRange = value.num[0];
376
807
  }
377
808
  },
378
809
  {
379
- name: 'RefractionStrength',
380
- description: 'Strength of underwater refraction',
810
+ name: 'CausticsFadeDistance',
811
+ description: 'Width in meters the caustics fade out over at the edge of the map, or 0 to derive it from the range',
381
812
  type: 'float',
382
813
  default: 0,
814
+ options: {
815
+ minValue: 0,
816
+ maxValue: 100
817
+ },
818
+ isHidden () {
819
+ return !this.causticsEnabled;
820
+ },
821
+ get (value) {
822
+ value.num[0] = this.causticsFadeDistance;
823
+ },
824
+ set (value) {
825
+ this.causticsFadeDistance = value.num[0];
826
+ }
827
+ },
828
+ {
829
+ name: 'CausticsSceneDepth',
830
+ description: 'Land caustics on the scene instead of on a plane at CausticsDepth. Reuses the sun shadow cascade, so it costs no extra geometry pass; WebGL2 keeps the plane, which its shadow map format cannot avoid.',
831
+ type: 'bool',
832
+ default: true,
833
+ get (value) {
834
+ value.bool[0] = this.causticsSceneDepth;
835
+ },
836
+ set (value) {
837
+ this.causticsSceneDepth = value.bool[0];
838
+ }
839
+ },
840
+ {
841
+ name: 'CausticsWarp',
842
+ description: 'How strongly caustic map texels are concentrated near the camera; ignored while the map already fits the water within range',
843
+ type: 'float',
844
+ default: 1.5,
845
+ options: {
846
+ minValue: 0,
847
+ maxValue: 8
848
+ },
849
+ isHidden () {
850
+ return !this.causticsEnabled;
851
+ },
852
+ get (value) {
853
+ value.num[0] = this.causticsWarp;
854
+ },
855
+ set (value) {
856
+ this.causticsWarp = value.num[0];
857
+ }
858
+ },
859
+ {
860
+ name: 'UnderwaterEnabled',
861
+ description: 'Whether a camera inside this water sees it from the inside: the medium over the whole scene, the sky replaced by water, and the surface read from below with its Snell window. Atmospheric fog is suppressed while submerged.',
862
+ type: 'bool',
863
+ default: true,
864
+ get (value) {
865
+ value.bool[0] = this.underwaterEnabled;
866
+ },
867
+ set (value) {
868
+ this.underwaterEnabled = value.bool[0];
869
+ }
870
+ },
871
+ {
872
+ name: 'UnderwaterAmbientIntensity',
873
+ description: 'Scale on the downwelling sky light filling the water column. This is what the water fades to in the distance, so it sets how bright the underwater haze reads.',
874
+ type: 'float',
875
+ default: 1,
383
876
  options: {
384
877
  animatable: true,
385
878
  minValue: 0,
386
- maxValue: 1
879
+ maxValue: 5
880
+ },
881
+ isHidden () {
882
+ return !this.underwaterEnabled;
883
+ },
884
+ get (value) {
885
+ value.num[0] = this.underwaterAmbientIntensity;
886
+ },
887
+ set (value) {
888
+ this.underwaterAmbientIntensity = value.num[0];
889
+ }
890
+ },
891
+ {
892
+ name: 'UnderwaterGodRays',
893
+ description: 'Whether shafts of sunlight are marched through the water column. Reads the caustic map as the surface transmittance, so the shafts carry the pattern that lands on the sea bed; needs CausticsEnabled.',
894
+ type: 'bool',
895
+ default: true,
896
+ isHidden () {
897
+ return !this.underwaterEnabled;
387
898
  },
388
899
  get (value) {
389
- value.num[0] = this.material.refractionStrength;
900
+ value.bool[0] = this.underwaterGodRays;
390
901
  },
391
902
  set (value) {
392
- this.material.refractionStrength = value.num[0];
903
+ this.underwaterGodRays = value.bool[0];
393
904
  }
394
905
  },
395
906
  {
396
- name: 'Displace',
397
- description: 'Vertex displacement scale for water waves',
907
+ name: 'UnderwaterGodRayIntensity',
908
+ description: 'Strength of the light shafts, 1 for the value the medium implies',
398
909
  type: 'float',
399
- default: 16,
910
+ default: 1,
400
911
  options: {
401
- minValue: 1,
402
- maxValue: 256
912
+ animatable: true,
913
+ minValue: 0,
914
+ maxValue: 5
915
+ },
916
+ isHidden () {
917
+ return !this.underwaterEnabled || !this.underwaterGodRays;
918
+ },
919
+ get (value) {
920
+ value.num[0] = this.underwaterGodRayIntensity;
921
+ },
922
+ set (value) {
923
+ this.underwaterGodRayIntensity = value.num[0];
924
+ }
925
+ },
926
+ {
927
+ name: 'UnderwaterGodRaySteps',
928
+ description: 'Samples taken along each view ray for the light shafts. Raise it when the shafts read as grain rather than as beams.',
929
+ type: 'int',
930
+ default: 24,
931
+ options: {
932
+ minValue: 4,
933
+ maxValue: 96
934
+ },
935
+ isHidden () {
936
+ return !this.underwaterEnabled || !this.underwaterGodRays;
937
+ },
938
+ get (value) {
939
+ value.num[0] = this.underwaterGodRaySteps;
940
+ },
941
+ set (value) {
942
+ this.underwaterGodRaySteps = value.num[0];
943
+ }
944
+ },
945
+ {
946
+ name: 'UnderwaterGodRayShadow',
947
+ description: 'Whether geometry standing in the water breaks the light shafts. The shafts come from the caustic map, which knows only what the surface did to the sunlight, so without this a shaft runs straight through a piling. Costs a shadow map lookup per march step.',
948
+ type: 'bool',
949
+ default: false,
950
+ isHidden () {
951
+ return !this.underwaterEnabled || !this.underwaterGodRays;
952
+ },
953
+ get (value) {
954
+ value.bool[0] = this.underwaterGodRayShadow;
955
+ },
956
+ set (value) {
957
+ this.underwaterGodRayShadow = value.bool[0];
958
+ }
959
+ },
960
+ {
961
+ name: 'UnderwaterHysteresis',
962
+ description: 'Half-width in meters of the dead band around the surface the submerged test uses, so a camera at water level does not flip state every frame',
963
+ type: 'float',
964
+ default: 0.05,
965
+ options: {
966
+ minValue: 0,
967
+ maxValue: 2
968
+ },
969
+ isHidden () {
970
+ return !this.underwaterEnabled;
971
+ },
972
+ get (value) {
973
+ value.num[0] = this.underwaterHysteresis;
974
+ },
975
+ set (value) {
976
+ this.underwaterHysteresis = value.num[0];
977
+ }
978
+ },
979
+ {
980
+ name: 'MediumMode',
981
+ description: 'How the water medium attenuates light: physical coefficients, or the legacy ramp textures',
982
+ type: 'string',
983
+ default: 'physical',
984
+ options: {
985
+ enum: {
986
+ labels: [
987
+ 'Physical',
988
+ 'Ramp'
989
+ ],
990
+ values: [
991
+ 'physical',
992
+ 'ramp'
993
+ ]
994
+ }
995
+ },
996
+ get (value) {
997
+ value.str[0] = this.material.mediumMode;
998
+ },
999
+ set (value) {
1000
+ this.material.mediumMode = value.str[0];
1001
+ }
1002
+ },
1003
+ {
1004
+ name: 'RefractionMode',
1005
+ description: 'How the refracted view sample is located. March walks the refracted ray against the scene depth and samples where it lands, which keeps the sample on the object behind the water; Offset skips the search and displaces the screen UV by the wave normal, which costs no depth fetches but samples the wrong point. Use Offset on hardware that cannot afford the search.',
1006
+ type: 'string',
1007
+ default: 'march',
1008
+ options: {
1009
+ enum: {
1010
+ labels: [
1011
+ 'March (accurate)',
1012
+ 'Offset (cheap)'
1013
+ ],
1014
+ values: [
1015
+ 'march',
1016
+ 'offset'
1017
+ ]
1018
+ }
1019
+ },
1020
+ get (value) {
1021
+ value.str[0] = this.material.refractionMode;
1022
+ },
1023
+ set (value) {
1024
+ this.material.refractionMode = value.str[0];
1025
+ }
1026
+ },
1027
+ {
1028
+ name: 'DebugOutput',
1029
+ description: 'Debugging aid: replaces the water colour with one of the shading terms it is built from, so a broken term can be identified by eye',
1030
+ type: 'string',
1031
+ default: 'none',
1032
+ options: {
1033
+ enum: {
1034
+ labels: WATER_DEBUG_OUTPUTS.map((e)=>e.label),
1035
+ values: WATER_DEBUG_OUTPUTS.map((e)=>e.value)
1036
+ }
1037
+ },
1038
+ get (value) {
1039
+ value.str[0] = this.debugOutput;
1040
+ },
1041
+ set (value) {
1042
+ this.debugOutput = value.str[0];
1043
+ }
1044
+ },
1045
+ {
1046
+ name: 'Absorption',
1047
+ description: 'Absorption coefficient sigma_a of the water medium, per meter, per channel',
1048
+ type: 'rgb',
1049
+ default: [
1050
+ 1.0,
1051
+ 0.25,
1052
+ 0.15
1053
+ ],
1054
+ options: {
1055
+ animatable: true,
1056
+ minValue: 0,
1057
+ maxValue: 10
1058
+ },
1059
+ isHidden () {
1060
+ return this.material.mediumMode !== 'physical';
1061
+ },
1062
+ get (value) {
1063
+ value.num[0] = this.material.absorption.x;
1064
+ value.num[1] = this.material.absorption.y;
1065
+ value.num[2] = this.material.absorption.z;
1066
+ },
1067
+ set (value) {
1068
+ this.material.absorption = new Vector3(value.num[0], value.num[1], value.num[2]);
1069
+ }
1070
+ },
1071
+ {
1072
+ name: 'AbsorptionScale',
1073
+ description: 'Scale for the absorption coefficient',
1074
+ type: 'float',
1075
+ default: 1,
1076
+ options: {
1077
+ animatable: true,
1078
+ minValue: 0,
1079
+ maxValue: 10
1080
+ },
1081
+ isHidden () {
1082
+ return this.material.mediumMode !== 'physical';
1083
+ },
1084
+ get (value) {
1085
+ value.num[0] = this.material.absorptionScale;
1086
+ },
1087
+ set (value) {
1088
+ this.material.absorptionScale = value.num[0];
1089
+ }
1090
+ },
1091
+ {
1092
+ name: 'Scattering',
1093
+ description: 'Scattering coefficient sigma_s of the water medium, per meter, per channel',
1094
+ type: 'rgb',
1095
+ default: [
1096
+ 0.05,
1097
+ 0.12,
1098
+ 0.18
1099
+ ],
1100
+ options: {
1101
+ animatable: true,
1102
+ minValue: 0,
1103
+ maxValue: 10
1104
+ },
1105
+ isHidden () {
1106
+ return this.material.mediumMode !== 'physical';
1107
+ },
1108
+ get (value) {
1109
+ value.num[0] = this.material.scattering.x;
1110
+ value.num[1] = this.material.scattering.y;
1111
+ value.num[2] = this.material.scattering.z;
1112
+ },
1113
+ set (value) {
1114
+ this.material.scattering = new Vector3(value.num[0], value.num[1], value.num[2]);
1115
+ }
1116
+ },
1117
+ {
1118
+ name: 'ScatteringScale',
1119
+ description: 'Scale for the scattering coefficient',
1120
+ type: 'float',
1121
+ default: 1,
1122
+ options: {
1123
+ animatable: true,
1124
+ minValue: 0,
1125
+ maxValue: 10
1126
+ },
1127
+ isHidden () {
1128
+ return this.material.mediumMode !== 'physical';
1129
+ },
1130
+ get (value) {
1131
+ value.num[0] = this.material.scatteringScale;
1132
+ },
1133
+ set (value) {
1134
+ this.material.scatteringScale = value.num[0];
1135
+ }
1136
+ },
1137
+ {
1138
+ name: 'DepthScale',
1139
+ description: 'Depth attenuation scale for the water material (ramp medium only)',
1140
+ type: 'float',
1141
+ default: 10,
1142
+ options: {
1143
+ animatable: true,
1144
+ minValue: 0,
1145
+ maxValue: 100
1146
+ },
1147
+ isHidden () {
1148
+ return this.material.mediumMode !== 'ramp';
1149
+ },
1150
+ get (value) {
1151
+ value.num[0] = this.material.depthMulti;
1152
+ },
1153
+ set (value) {
1154
+ this.material.depthMulti = value.num[0];
1155
+ }
1156
+ },
1157
+ {
1158
+ name: 'ReflectionStrength',
1159
+ description: 'Scale on the Fresnel reflectance, 1 for the physical value. Lower it to trade the reflection away and show more of what is beneath the surface.',
1160
+ type: 'float',
1161
+ default: 1,
1162
+ options: {
1163
+ animatable: true,
1164
+ minValue: 0,
1165
+ maxValue: 1
1166
+ },
1167
+ get (value) {
1168
+ value.num[0] = this.material.reflectionStrength;
1169
+ },
1170
+ set (value) {
1171
+ this.material.reflectionStrength = value.num[0];
1172
+ }
1173
+ },
1174
+ {
1175
+ name: 'SubsurfaceIntensity',
1176
+ description: 'Strength of the sunlight scattered forward through a wave crest, which is what makes a backlit crest glow. Grazing views of a low sun show it; looking down at the water does not.',
1177
+ type: 'float',
1178
+ default: 1.5,
1179
+ options: {
1180
+ animatable: true,
1181
+ minValue: 0,
1182
+ maxValue: 10
1183
+ },
1184
+ get (value) {
1185
+ value.num[0] = this.material.subsurfaceIntensity;
1186
+ },
1187
+ set (value) {
1188
+ this.material.subsurfaceIntensity = value.num[0];
1189
+ }
1190
+ },
1191
+ {
1192
+ name: 'SubsurfaceSteepness',
1193
+ description: 'How sharply surface tilt gates the subsurface glow. Higher makes gentle swell glow too; lower restricts it to steep wave flanks.',
1194
+ type: 'float',
1195
+ default: 60,
1196
+ options: {
1197
+ animatable: true,
1198
+ minValue: 0,
1199
+ maxValue: 100
1200
+ },
1201
+ get (value) {
1202
+ value.num[0] = this.material.subsurfaceSteepness;
1203
+ },
1204
+ set (value) {
1205
+ this.material.subsurfaceSteepness = value.num[0];
1206
+ }
1207
+ },
1208
+ {
1209
+ name: 'SunScatteringIntensity',
1210
+ description: 'Strength of the sunlight scattered out of the water column towards the eye, 1 for the value the medium coefficients imply. This is what makes a shadow on the water darken the water itself and a low sun tint it; 0 leaves the body lit by the environment alone.',
1211
+ type: 'float',
1212
+ default: 1,
1213
+ options: {
1214
+ animatable: true,
1215
+ minValue: 0,
1216
+ maxValue: 4
1217
+ },
1218
+ get (value) {
1219
+ value.num[0] = this.material.sunScatteringIntensity;
1220
+ },
1221
+ set (value) {
1222
+ this.material.sunScatteringIntensity = value.num[0];
1223
+ }
1224
+ },
1225
+ {
1226
+ name: 'FoamAmount',
1227
+ description: 'Coverage of the foam on breaking wave crests, mapped from the folding the wave generator reports. 0 disables crest foam. Independent of ShoreFoamAmount.',
1228
+ type: 'float',
1229
+ default: 1,
1230
+ options: {
1231
+ animatable: true,
1232
+ minValue: 0,
1233
+ maxValue: 4
1234
+ },
1235
+ get (value) {
1236
+ value.num[0] = this.material.foamAmount;
1237
+ },
1238
+ set (value) {
1239
+ this.material.foamAmount = value.num[0];
1240
+ }
1241
+ },
1242
+ {
1243
+ name: 'FoamFalloff',
1244
+ description: 'Falloff applied to crest foam coverage. Above 1 pushes light folding towards no foam at all, so only a genuinely broken crest shows - which is what keeps a windy sea from turning uniformly white.',
1245
+ type: 'float',
1246
+ default: 1.5,
1247
+ options: {
1248
+ animatable: true,
1249
+ minValue: 0.01,
1250
+ maxValue: 8
1251
+ },
1252
+ isHidden () {
1253
+ return this.material.foamAmount <= 0;
1254
+ },
1255
+ get (value) {
1256
+ value.num[0] = this.material.foamFalloff;
1257
+ },
1258
+ set (value) {
1259
+ this.material.foamFalloff = value.num[0];
1260
+ }
1261
+ },
1262
+ {
1263
+ name: 'FoamColor',
1264
+ description: 'Diffuse albedo of the foam, shared by the crest foam and the shoreline foam. Slightly off-white and slightly blue - sea foam is water and air, and a pure white one reads as snow.',
1265
+ type: 'rgb',
1266
+ default: [
1267
+ 0.92,
1268
+ 0.95,
1269
+ 0.97
1270
+ ],
1271
+ options: {
1272
+ animatable: true,
1273
+ minValue: 0,
1274
+ maxValue: 1
1275
+ },
1276
+ get (value) {
1277
+ value.num[0] = this.material.foamColor.x;
1278
+ value.num[1] = this.material.foamColor.y;
1279
+ value.num[2] = this.material.foamColor.z;
1280
+ },
1281
+ set (value) {
1282
+ this.material.foamColor = new Vector3(value.num[0], value.num[1], value.num[2]);
1283
+ }
1284
+ },
1285
+ {
1286
+ name: 'ShoreFoamAmount',
1287
+ description: 'Coverage of the foam that collects where the water meets a surface - the waterline on a shelving bed, and the collar around a piling or a hull. 0 disables it, which also removes its cost. Independent of the crest foam the wave generator produces. Requires WebGL2 or WebGPU.',
1288
+ type: 'float',
1289
+ default: 0,
1290
+ // Deliberately not animatable: crossing zero switches the whole
1291
+ // feature in and out of the shader, so an animation curve driving this
1292
+ // through zero rebuilds the program on the way past.
1293
+ options: {
1294
+ minValue: 0,
1295
+ maxValue: 4
1296
+ },
1297
+ get (value) {
1298
+ value.num[0] = this.shoreFoamAmount;
1299
+ },
1300
+ set (value) {
1301
+ this.shoreFoamAmount = value.num[0];
1302
+ }
1303
+ },
1304
+ {
1305
+ name: 'ShoreFoamDepth',
1306
+ description: 'How far the foam band reaches from the surface behind it, in meters. Over a bed this is a depth of water; against something vertical it is the horizontal distance to its side, and one value serves both. How wide that is on screen depends on the geometry: a thin line on a steep drop-off, a broad stretch on a flat shelf.',
1307
+ type: 'float',
1308
+ default: 0.5,
1309
+ options: {
1310
+ animatable: true,
1311
+ minValue: 0.001,
1312
+ maxValue: 20
1313
+ },
1314
+ isHidden () {
1315
+ return this.shoreFoamAmount <= 0;
1316
+ },
1317
+ get (value) {
1318
+ value.num[0] = this.shoreFoamDepth;
1319
+ },
1320
+ set (value) {
1321
+ this.shoreFoamDepth = value.num[0];
1322
+ }
1323
+ },
1324
+ {
1325
+ name: 'ShoreFoamFalloff',
1326
+ description: 'Falloff across the foam band. Above 1 pushes the coverage towards the contact line and keeps the outer edge thin and broken.',
1327
+ type: 'float',
1328
+ default: 1.5,
1329
+ options: {
1330
+ animatable: true,
1331
+ minValue: 0.01,
1332
+ maxValue: 8
1333
+ },
1334
+ isHidden () {
1335
+ return this.shoreFoamAmount <= 0;
1336
+ },
1337
+ get (value) {
1338
+ value.num[0] = this.shoreFoamFalloff;
1339
+ },
1340
+ set (value) {
1341
+ this.shoreFoamFalloff = value.num[0];
1342
+ }
1343
+ },
1344
+ {
1345
+ name: 'ShoreFoamScale',
1346
+ description: 'Size of the clumps the band breaks into, as cycles across the band rather than cycles per meter. Being relative to the band width, one value reads the same on a shoreline metres across and on a collar a handspan wide.',
1347
+ type: 'float',
1348
+ default: 2.5,
1349
+ options: {
1350
+ animatable: true,
1351
+ minValue: 0,
1352
+ maxValue: 20
1353
+ },
1354
+ isHidden () {
1355
+ return this.shoreFoamAmount <= 0;
1356
+ },
1357
+ get (value) {
1358
+ value.num[0] = this.shoreFoamScale;
1359
+ },
1360
+ set (value) {
1361
+ this.shoreFoamScale = value.num[0];
1362
+ }
1363
+ },
1364
+ {
1365
+ name: 'ShoreFoamWashAmount',
1366
+ description: 'How far the waterline runs up and back, as a fraction of ShoreFoamDepth. This is what makes the band read as surf rather than as a painted rim; 0 leaves it static. Above 1 the band closes completely at the bottom of the cycle, which looks like the foam blinking out.',
1367
+ type: 'float',
1368
+ default: 0.5,
1369
+ options: {
1370
+ animatable: true,
1371
+ minValue: 0,
1372
+ maxValue: 2
1373
+ },
1374
+ isHidden () {
1375
+ return this.shoreFoamAmount <= 0;
1376
+ },
1377
+ get (value) {
1378
+ value.num[0] = this.shoreFoamWashAmount;
1379
+ },
1380
+ set (value) {
1381
+ this.shoreFoamWashAmount = value.num[0];
1382
+ }
1383
+ },
1384
+ {
1385
+ name: 'ShoreFoamWashSpeed',
1386
+ description: 'Run-up cycles per second. Swell rather than wind waves, so well under 1.',
1387
+ type: 'float',
1388
+ default: 0.12,
1389
+ options: {
1390
+ animatable: true,
1391
+ minValue: 0,
1392
+ maxValue: 2
1393
+ },
1394
+ isHidden () {
1395
+ return this.shoreFoamAmount <= 0;
1396
+ },
1397
+ get (value) {
1398
+ value.num[0] = this.shoreFoamWashSpeed;
1399
+ },
1400
+ set (value) {
1401
+ this.shoreFoamWashSpeed = value.num[0];
1402
+ }
1403
+ },
1404
+ {
1405
+ name: 'ShoreFoamWashScale',
1406
+ description: 'Spatial frequency of the run-up phase, in cycles per meter. At 0 the whole waterline rises and falls in lockstep, which reads as the water level itself changing; a cycle every few tens of meters breaks a long shoreline into sections that run out of step with one another.',
1407
+ type: 'float',
1408
+ default: 0.03,
1409
+ options: {
1410
+ animatable: true,
1411
+ minValue: 0,
1412
+ maxValue: 1
1413
+ },
1414
+ isHidden () {
1415
+ return this.shoreFoamAmount <= 0;
1416
+ },
1417
+ get (value) {
1418
+ value.num[0] = this.shoreFoamWashScale;
1419
+ },
1420
+ set (value) {
1421
+ this.shoreFoamWashScale = value.num[0];
1422
+ }
1423
+ },
1424
+ {
1425
+ name: 'CheapRefractionDepth',
1426
+ description: 'Depth in meters the cheap refraction mode assumes the water is. Sets how strong the distortion looks when RefractionMode is Offset; ignored by March. A constant rather than the measured distance to the bottom, because an offset scaled by that distance paints a second copy of any object breaking the surface.',
1427
+ type: 'float',
1428
+ default: 1,
1429
+ options: {
1430
+ animatable: true,
1431
+ minValue: 0,
1432
+ maxValue: 20
1433
+ },
1434
+ isHidden () {
1435
+ return this.material.refractionMode !== 'offset';
1436
+ },
1437
+ get (value) {
1438
+ value.num[0] = this.material.cheapRefractionDepth;
1439
+ },
1440
+ set (value) {
1441
+ this.material.cheapRefractionDepth = value.num[0];
1442
+ }
1443
+ },
1444
+ {
1445
+ name: 'RefractionBlur',
1446
+ description: 'Scale on how much the medium blurs what is seen through it, 1 for the width the scattering coefficient and the path length imply. Turbid or deep water smudges the bottom; 0 keeps it sharp at any depth.',
1447
+ type: 'float',
1448
+ default: 1,
1449
+ options: {
1450
+ animatable: true,
1451
+ minValue: 0,
1452
+ maxValue: 4
1453
+ },
1454
+ get (value) {
1455
+ value.num[0] = this.material.refractionBlur;
1456
+ },
1457
+ set (value) {
1458
+ this.material.refractionBlur = value.num[0];
1459
+ }
1460
+ },
1461
+ {
1462
+ name: 'ScatterAnisotropy',
1463
+ description: 'Mean cosine of a single scattering event. 0 scatters equally in all directions; higher brightens the water when looking towards the sun through it. Sea water measures near 0.9, but a turbid column blends towards isotropic on its own.',
1464
+ type: 'float',
1465
+ default: DEFAULT_SCATTER_ANISOTROPY,
1466
+ options: {
1467
+ animatable: true,
1468
+ minValue: 0,
1469
+ maxValue: 0.95
1470
+ },
1471
+ get (value) {
1472
+ value.num[0] = this.material.scatterAnisotropy;
1473
+ },
1474
+ set (value) {
1475
+ this.material.scatterAnisotropy = value.num[0];
1476
+ }
1477
+ },
1478
+ {
1479
+ name: 'RefractionScale',
1480
+ description: 'Artistic scale on the refracted view offset. 1 is physical: the view ray is bent by Snell’s law and followed to whatever is behind the water, so the incidence angle, the depth and the perspective are already accounted for. 0 disables refraction.',
1481
+ type: 'float',
1482
+ default: 1,
1483
+ options: {
1484
+ animatable: true,
1485
+ minValue: 0,
1486
+ maxValue: 4
403
1487
  },
404
1488
  get (value) {
405
- value.num[0] = this.material.displace;
1489
+ value.num[0] = this.material.refractionScale;
406
1490
  },
407
1491
  set (value) {
408
- this.material.displace = value.num[0];
1492
+ this.material.refractionScale = value.num[0];
409
1493
  }
410
1494
  },
411
1495
  {
@@ -495,5 +1579,5 @@ import '../../../scene/raycast_visitor.js';
495
1579
  };
496
1580
  }
497
1581
 
498
- export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getWaterClass };
1582
+ export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getGerstnerWaveClass, getGerstnerWaveGeneratorClass, getWaterClass };
499
1583
  //# sourceMappingURL=water.js.map