@zephyr3d/scene 0.9.27 → 0.10.0

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 (502) hide show
  1. package/README.md +60 -27
  2. package/dist/animation/animation_bank.js +634 -0
  3. package/dist/animation/animation_bank.js.map +1 -0
  4. package/dist/animation/animation_bank_gpu.js +256 -0
  5. package/dist/animation/animation_bank_gpu.js.map +1 -0
  6. package/dist/animation/animationset.js +54 -0
  7. package/dist/animation/animationset.js.map +1 -1
  8. package/dist/animation/cloth/gpu_cloth_component.js +406 -0
  9. package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
  10. package/dist/animation/cloth/gpu_cloth_system.js +332 -202
  11. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  12. package/dist/animation/gpu_animation_driver.js +289 -0
  13. package/dist/animation/gpu_animation_driver.js.map +1 -0
  14. package/dist/animation/joint_dynamics/collision.js +112 -1
  15. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  16. package/dist/animation/joint_dynamics/controller.js +6 -0
  17. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
  19. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  20. package/dist/animation/joint_dynamics/solver.js +50 -12
  21. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/skeleton.js +279 -55
  24. package/dist/animation/skeleton.js.map +1 -1
  25. package/dist/animation/skin_palette_atlas.js +252 -0
  26. package/dist/animation/skin_palette_atlas.js.map +1 -0
  27. package/dist/animation/spring/multi_chain_spring_system.js +298 -38
  28. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  29. package/dist/animation/spring/spring_chain.js +2 -0
  30. package/dist/animation/spring/spring_chain.js.map +1 -1
  31. package/dist/animation/spring/spring_collider.js +159 -21
  32. package/dist/animation/spring/spring_collider.js.map +1 -1
  33. package/dist/animation/spring/spring_particle.js +1 -0
  34. package/dist/animation/spring/spring_particle.js.map +1 -1
  35. package/dist/animation/spring/spring_solver.js +173 -0
  36. package/dist/animation/spring/spring_solver.js.map +1 -0
  37. package/dist/animation/spring/spring_system.js +249 -24
  38. package/dist/animation/spring/spring_system.js.map +1 -1
  39. package/dist/animation/spring_modifier.js +32 -1
  40. package/dist/animation/spring_modifier.js.map +1 -1
  41. package/dist/app/app.js +26 -0
  42. package/dist/app/app.js.map +1 -1
  43. package/dist/app/engine.js +86 -15
  44. package/dist/app/engine.js.map +1 -1
  45. package/dist/app/gamepad.js +191 -0
  46. package/dist/app/gamepad.js.map +1 -0
  47. package/dist/app/inputactions.js +271 -0
  48. package/dist/app/inputactions.js.map +1 -0
  49. package/dist/app/inputmgr.js +331 -22
  50. package/dist/app/inputmgr.js.map +1 -1
  51. package/dist/app/loading.js +138 -0
  52. package/dist/app/loading.js.map +1 -0
  53. package/dist/app/pipelinecache.js +209 -0
  54. package/dist/app/pipelinecache.js.map +1 -0
  55. package/dist/app/runtimescript.js +25 -0
  56. package/dist/app/runtimescript.js.map +1 -1
  57. package/dist/app/scriptingsystem.js +54 -0
  58. package/dist/app/scriptingsystem.js.map +1 -1
  59. package/dist/app/scriptregistry.js +7 -2
  60. package/dist/app/scriptregistry.js.map +1 -1
  61. package/dist/asset/asset_manifest.js +59 -0
  62. package/dist/asset/asset_manifest.js.map +1 -0
  63. package/dist/asset/asset_preload.js +258 -0
  64. package/dist/asset/asset_preload.js.map +1 -0
  65. package/dist/asset/assetmanager.js +117 -65
  66. package/dist/asset/assetmanager.js.map +1 -1
  67. package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
  68. package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  69. package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  70. package/dist/asset/loaders/ktx2/basis_location.js +17 -0
  71. package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
  72. package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
  73. package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
  74. package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
  75. package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
  76. package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
  77. package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
  78. package/dist/asset/mesh_lod_builder.js +104 -0
  79. package/dist/asset/mesh_lod_builder.js.map +1 -0
  80. package/dist/asset/mesh_settings.js +111 -0
  81. package/dist/asset/mesh_settings.js.map +1 -0
  82. package/dist/asset/meshopt_decoder.js +18 -0
  83. package/dist/asset/meshopt_decoder.js.map +1 -0
  84. package/dist/asset/meshopt_simplifier.js +26 -0
  85. package/dist/asset/meshopt_simplifier.js.map +1 -0
  86. package/dist/asset/model.js +171 -1
  87. package/dist/asset/model.js.map +1 -1
  88. package/dist/asset/texture_settings.js +231 -0
  89. package/dist/asset/texture_settings.js.map +1 -0
  90. package/dist/asset/zmsh_binary.js +131 -0
  91. package/dist/asset/zmsh_binary.js.map +1 -0
  92. package/dist/asset/zsdf_binary.js +111 -0
  93. package/dist/asset/zsdf_binary.js.map +1 -0
  94. package/dist/blitter/bilateralblur.js +1 -2
  95. package/dist/blitter/bilateralblur.js.map +1 -1
  96. package/dist/blitter/gaussianblur.js +1 -6
  97. package/dist/blitter/gaussianblur.js.map +1 -1
  98. package/dist/camera/base.js +31 -10
  99. package/dist/camera/base.js.map +1 -1
  100. package/dist/camera/camera.js +104 -178
  101. package/dist/camera/camera.js.map +1 -1
  102. package/dist/camera/follow.js +342 -0
  103. package/dist/camera/follow.js.map +1 -0
  104. package/dist/camera/fps.js +9 -7
  105. package/dist/camera/fps.js.map +1 -1
  106. package/dist/camera/orbit.js +46 -19
  107. package/dist/camera/orbit.js.map +1 -1
  108. package/dist/index.d.ts +25436 -15990
  109. package/dist/index.js +65 -11
  110. package/dist/index.js.map +1 -1
  111. package/dist/material/blinn.js +3 -0
  112. package/dist/material/blinn.js.map +1 -1
  113. package/dist/material/eye.js +1 -1
  114. package/dist/material/eye.js.map +1 -1
  115. package/dist/material/hair.js +2 -3
  116. package/dist/material/hair.js.map +1 -1
  117. package/dist/material/lambert.js +4 -1
  118. package/dist/material/lambert.js.map +1 -1
  119. package/dist/material/material.js +66 -4
  120. package/dist/material/material.js.map +1 -1
  121. package/dist/material/meshmaterial.js +118 -45
  122. package/dist/material/meshmaterial.js.map +1 -1
  123. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  124. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  126. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  128. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  130. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  132. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  133. package/dist/material/mixins/lit.js +191 -83
  134. package/dist/material/mixins/lit.js.map +1 -1
  135. package/dist/material/mixins/pbr/common.js +31 -206
  136. package/dist/material/mixins/pbr/common.js.map +1 -1
  137. package/dist/material/mtoon.js +1 -1
  138. package/dist/material/mtoon.js.map +1 -1
  139. package/dist/material/pbrmr.js +3 -0
  140. package/dist/material/pbrmr.js.map +1 -1
  141. package/dist/material/pbrsg.js +3 -0
  142. package/dist/material/pbrsg.js.map +1 -1
  143. package/dist/material/sdf_debug.js +78 -0
  144. package/dist/material/sdf_debug.js.map +1 -0
  145. package/dist/material/shader/helper.js +333 -191
  146. package/dist/material/shader/helper.js.map +1 -1
  147. package/dist/material/shader/terrain_blend.js +204 -43
  148. package/dist/material/shader/terrain_blend.js.map +1 -1
  149. package/dist/material/skin.js +331 -297
  150. package/dist/material/skin.js.map +1 -1
  151. package/dist/material/skinprofile.js +1058 -0
  152. package/dist/material/skinprofile.js.map +1 -0
  153. package/dist/material/sss.js +353 -0
  154. package/dist/material/sss.js.map +1 -0
  155. package/dist/material/sss_kernel.js +265 -0
  156. package/dist/material/sss_kernel.js.map +1 -0
  157. package/dist/material/sssprofile.js +879 -0
  158. package/dist/material/sssprofile.js.map +1 -0
  159. package/dist/material/subsurfaceprofile.js +4 -8
  160. package/dist/material/subsurfaceprofile.js.map +1 -1
  161. package/dist/material/terrain-cm.js +464 -188
  162. package/dist/material/terrain-cm.js.map +1 -1
  163. package/dist/material/unlit.js +3 -0
  164. package/dist/material/unlit.js.map +1 -1
  165. package/dist/material/water.js +1261 -1438
  166. package/dist/material/water.js.map +1 -1
  167. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  168. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  169. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  172. package/dist/physics/character.js +226 -0
  173. package/dist/physics/character.js.map +1 -0
  174. package/dist/physics/collider.js +209 -0
  175. package/dist/physics/collider.js.map +1 -0
  176. package/dist/physics/events.js +79 -0
  177. package/dist/physics/events.js.map +1 -0
  178. package/dist/physics/joint.js +272 -0
  179. package/dist/physics/joint.js.map +1 -0
  180. package/dist/physics/node_physics.js +234 -0
  181. package/dist/physics/node_physics.js.map +1 -0
  182. package/dist/physics/part.js +91 -0
  183. package/dist/physics/part.js.map +1 -0
  184. package/dist/physics/rigid_body.js +379 -0
  185. package/dist/physics/rigid_body.js.map +1 -0
  186. package/dist/physics/vehicle.js +335 -0
  187. package/dist/physics/vehicle.js.map +1 -0
  188. package/dist/physics/world.js +25 -0
  189. package/dist/physics/world.js.map +1 -0
  190. package/dist/posteffect/bloom.js +49 -14
  191. package/dist/posteffect/bloom.js.map +1 -1
  192. package/dist/posteffect/motionblur.js +106 -106
  193. package/dist/posteffect/motionblur.js.map +1 -1
  194. package/dist/posteffect/postsss.js +572 -0
  195. package/dist/posteffect/postsss.js.map +1 -0
  196. package/dist/posteffect/sao.js +2 -6
  197. package/dist/posteffect/sao.js.map +1 -1
  198. package/dist/posteffect/skinsss.js +605 -355
  199. package/dist/posteffect/skinsss.js.map +1 -1
  200. package/dist/posteffect/ssgi.js +91 -162
  201. package/dist/posteffect/ssgi.js.map +1 -1
  202. package/dist/posteffect/ssr.js +3 -11
  203. package/dist/posteffect/ssr.js.map +1 -1
  204. package/dist/posteffect/sss.js +4 -13
  205. package/dist/posteffect/sss.js.map +1 -1
  206. package/dist/posteffect/taa.js +1 -0
  207. package/dist/posteffect/taa.js.map +1 -1
  208. package/dist/render/abuffer_oit.js +3 -2
  209. package/dist/render/abuffer_oit.js.map +1 -1
  210. package/dist/render/clipmap.js +179 -64
  211. package/dist/render/clipmap.js.map +1 -1
  212. package/dist/render/cluster_light.js +958 -224
  213. package/dist/render/cluster_light.js.map +1 -1
  214. package/dist/render/cull_visitor.js +25 -5
  215. package/dist/render/cull_visitor.js.map +1 -1
  216. package/dist/render/debug_views.js +37 -0
  217. package/dist/render/debug_views.js.map +1 -0
  218. package/dist/render/depthpass.js +5 -1
  219. package/dist/render/depthpass.js.map +1 -1
  220. package/dist/render/drawable_mixin.js +53 -6
  221. package/dist/render/drawable_mixin.js.map +1 -1
  222. package/dist/render/dualdepthpeeling_oit.js +5 -5
  223. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  224. package/dist/render/envlight.js +196 -113
  225. package/dist/render/envlight.js.map +1 -1
  226. package/dist/render/fbm_wavegenerator.js +5 -10
  227. package/dist/render/fbm_wavegenerator.js.map +1 -1
  228. package/dist/render/fft_wavegenerator.js +247 -157
  229. package/dist/render/fft_wavegenerator.js.map +1 -1
  230. package/dist/render/gerstner_wavegenerator.js +16 -38
  231. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  232. package/dist/render/gi/probe_volume.js +1334 -0
  233. package/dist/render/gi/probe_volume.js.map +1 -0
  234. package/dist/render/gi/scene_gi.js +282 -0
  235. package/dist/render/gi/scene_gi.js.map +1 -0
  236. package/dist/render/gi/voxel_atlas.js +198 -0
  237. package/dist/render/gi/voxel_atlas.js.map +1 -0
  238. package/dist/render/gi/voxel_lighting.js +652 -0
  239. package/dist/render/gi/voxel_lighting.js.map +1 -0
  240. package/dist/render/gi/voxel_scene.js +642 -0
  241. package/dist/render/gi/voxel_scene.js.map +1 -0
  242. package/dist/render/gi/voxelize_pass.js +223 -0
  243. package/dist/render/gi/voxelize_pass.js.map +1 -0
  244. package/dist/render/globalbindgroup_allocator.js +3 -2
  245. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  246. package/dist/render/gpu_picking.js +9 -36
  247. package/dist/render/gpu_picking.js.map +1 -1
  248. package/dist/render/instance_culling.js +499 -0
  249. package/dist/render/instance_culling.js.map +1 -0
  250. package/dist/render/lightpass.js +19 -8
  251. package/dist/render/lightpass.js.map +1 -1
  252. package/dist/render/lod.js +46 -0
  253. package/dist/render/lod.js.map +1 -0
  254. package/dist/render/primitive.js +301 -9
  255. package/dist/render/primitive.js.map +1 -1
  256. package/dist/render/primitive_readback.js +209 -0
  257. package/dist/render/primitive_readback.js.map +1 -0
  258. package/dist/render/render_queue.js +162 -11
  259. package/dist/render/render_queue.js.map +1 -1
  260. package/dist/render/renderer.js +10 -7
  261. package/dist/render/renderer.js.map +1 -1
  262. package/dist/render/rendergraph/blackboard.js +14 -1
  263. package/dist/render/rendergraph/blackboard.js.map +1 -1
  264. package/dist/render/rendergraph/executor.js +136 -0
  265. package/dist/render/rendergraph/executor.js.map +1 -1
  266. package/dist/render/rendergraph/forward_plus_builder.js +272 -55
  267. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  268. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  269. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  270. package/dist/render/rendergraph/scene_render_context.js +31 -2
  271. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  272. package/dist/render/rendergraph/types.js.map +1 -1
  273. package/dist/render/renderpass.js +28 -5
  274. package/dist/render/renderpass.js.map +1 -1
  275. package/dist/render/sdf/box_allocator.js +98 -0
  276. package/dist/render/sdf/box_allocator.js.map +1 -0
  277. package/dist/render/sdf/global_sdf.js +865 -0
  278. package/dist/render/sdf/global_sdf.js.map +1 -0
  279. package/dist/render/sdf/scene_sdf.js +562 -0
  280. package/dist/render/sdf/scene_sdf.js.map +1 -0
  281. package/dist/render/sdf/sdf_atlas.js +227 -0
  282. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  283. package/dist/render/sdf/sdf_programs.js +42 -0
  284. package/dist/render/sdf/sdf_programs.js.map +1 -0
  285. package/dist/render/sdf/sdf_view.js +199 -0
  286. package/dist/render/sdf/sdf_view.js.map +1 -0
  287. package/dist/render/sdf/waterline.js +610 -0
  288. package/dist/render/sdf/waterline.js.map +1 -0
  289. package/dist/render/shadow_mask_pass.js +142 -25
  290. package/dist/render/shadow_mask_pass.js.map +1 -1
  291. package/dist/render/shore_wave_generator.js +1193 -0
  292. package/dist/render/shore_wave_generator.js.map +1 -0
  293. package/dist/render/sky.js +516 -86
  294. package/dist/render/sky.js.map +1 -1
  295. package/dist/render/transmission_thickness_pass.js +477 -0
  296. package/dist/render/transmission_thickness_pass.js.map +1 -0
  297. package/dist/render/underwater.js +58 -158
  298. package/dist/render/underwater.js.map +1 -1
  299. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  300. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  301. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  302. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  303. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  304. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  305. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  306. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  307. package/dist/render/volumetric_cloud/resources.js +380 -0
  308. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  309. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  310. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  311. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  312. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  313. package/dist/render/water_caustics.js +134 -319
  314. package/dist/render/water_caustics.js.map +1 -1
  315. package/dist/render/water_foam.js +627 -0
  316. package/dist/render/water_foam.js.map +1 -0
  317. package/dist/render/water_interaction.js +1795 -0
  318. package/dist/render/water_interaction.js.map +1 -0
  319. package/dist/render/weightedblended_oit.js +3 -3
  320. package/dist/render/weightedblended_oit.js.map +1 -1
  321. package/dist/scene/basesprite.js +9 -4
  322. package/dist/scene/basesprite.js.map +1 -1
  323. package/dist/scene/batchgroup.js +108 -12
  324. package/dist/scene/batchgroup.js.map +1 -1
  325. package/dist/scene/environment.js +28 -7
  326. package/dist/scene/environment.js.map +1 -1
  327. package/dist/scene/foliage.js +1020 -0
  328. package/dist/scene/foliage.js.map +1 -0
  329. package/dist/scene/foliage_buckets.js +147 -0
  330. package/dist/scene/foliage_buckets.js.map +1 -0
  331. package/dist/scene/foliage_mask.js +358 -0
  332. package/dist/scene/foliage_mask.js.map +1 -0
  333. package/dist/scene/hair.js +15 -4
  334. package/dist/scene/hair.js.map +1 -1
  335. package/dist/scene/light.js +179 -13
  336. package/dist/scene/light.js.map +1 -1
  337. package/dist/scene/mesh.js +327 -45
  338. package/dist/scene/mesh.js.map +1 -1
  339. package/dist/scene/meshdrawable.js +6 -0
  340. package/dist/scene/meshdrawable.js.map +1 -1
  341. package/dist/scene/msdftext.js +9 -3
  342. package/dist/scene/msdftext.js.map +1 -1
  343. package/dist/scene/msdftextsprite.js +9 -3
  344. package/dist/scene/msdftextsprite.js.map +1 -1
  345. package/dist/scene/particlesys.js +8 -2
  346. package/dist/scene/particlesys.js.map +1 -1
  347. package/dist/scene/physics_settings.js +157 -0
  348. package/dist/scene/physics_settings.js.map +1 -0
  349. package/dist/scene/scene.js +190 -44
  350. package/dist/scene/scene.js.map +1 -1
  351. package/dist/scene/scene_node.js +147 -6
  352. package/dist/scene/scene_node.js.map +1 -1
  353. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  354. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  355. package/dist/scene/terrain-cm/grass.js +881 -42
  356. package/dist/scene/terrain-cm/grass.js.map +1 -1
  357. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  358. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  359. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  360. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  361. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  362. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  363. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  364. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  365. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  366. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  367. package/dist/scene/update_queue.js +54 -0
  368. package/dist/scene/update_queue.js.map +1 -0
  369. package/dist/scene/water.js +633 -268
  370. package/dist/scene/water.js.map +1 -1
  371. package/dist/scene/water_surface_sampler.js +324 -0
  372. package/dist/scene/water_surface_sampler.js.map +1 -0
  373. package/dist/scene/wind.js +317 -0
  374. package/dist/scene/wind.js.map +1 -0
  375. package/dist/shaders/atmosphere.js +388 -166
  376. package/dist/shaders/atmosphere.js.map +1 -1
  377. package/dist/shaders/fog.js +100 -32
  378. package/dist/shaders/fog.js.map +1 -1
  379. package/dist/shaders/gi.js +365 -0
  380. package/dist/shaders/gi.js.map +1 -0
  381. package/dist/shaders/ltc_rect.js +202 -0
  382. package/dist/shaders/ltc_rect.js.map +1 -0
  383. package/dist/shaders/misc.js +1 -10
  384. package/dist/shaders/misc.js.map +1 -1
  385. package/dist/shaders/noise.js +5 -1
  386. package/dist/shaders/noise.js.map +1 -1
  387. package/dist/shaders/probes.js +309 -0
  388. package/dist/shaders/probes.js.map +1 -0
  389. package/dist/shaders/sdf.js +537 -0
  390. package/dist/shaders/sdf.js.map +1 -0
  391. package/dist/shaders/shadow.js +104 -70
  392. package/dist/shaders/shadow.js.map +1 -1
  393. package/dist/shaders/skin_brdf.js +243 -0
  394. package/dist/shaders/skin_brdf.js.map +1 -0
  395. package/dist/shaders/ssgi.js +63 -0
  396. package/dist/shaders/ssgi.js.map +1 -0
  397. package/dist/shaders/ssgi_reprojection.js +118 -0
  398. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  399. package/dist/shaders/ssr.js +6 -159
  400. package/dist/shaders/ssr.js.map +1 -1
  401. package/dist/shaders/temporal.js +38 -27
  402. package/dist/shaders/temporal.js.map +1 -1
  403. package/dist/shaders/water.js +32 -82
  404. package/dist/shaders/water.js.map +1 -1
  405. package/dist/shaders/water_medium.js +7 -21
  406. package/dist/shaders/water_medium.js.map +1 -1
  407. package/dist/shadow/dom.js +110 -19
  408. package/dist/shadow/dom.js.map +1 -1
  409. package/dist/shadow/esm.js +3 -3
  410. package/dist/shadow/esm.js.map +1 -1
  411. package/dist/shadow/pcf_opt.js +15 -48
  412. package/dist/shadow/pcf_opt.js.map +1 -1
  413. package/dist/shadow/pcf_pd.js +15 -53
  414. package/dist/shadow/pcf_pd.js.map +1 -1
  415. package/dist/shadow/pcss.js +34 -9
  416. package/dist/shadow/pcss.js.map +1 -1
  417. package/dist/shadow/shadow_impl.js +3 -8
  418. package/dist/shadow/shadow_impl.js.map +1 -1
  419. package/dist/shadow/shadow_region.js +40 -2
  420. package/dist/shadow/shadow_region.js.map +1 -1
  421. package/dist/shadow/shadowmapper.js +93 -53
  422. package/dist/shadow/shadowmapper.js.map +1 -1
  423. package/dist/shadow/ssm.js +18 -72
  424. package/dist/shadow/ssm.js.map +1 -1
  425. package/dist/shadow/vsm.js +3 -3
  426. package/dist/shadow/vsm.js.map +1 -1
  427. package/dist/shapes/shape.js +44 -1
  428. package/dist/shapes/shape.js.map +1 -1
  429. package/dist/utility/buoyancy.js +287 -0
  430. package/dist/utility/buoyancy.js.map +1 -0
  431. package/dist/utility/physical.js +10 -1
  432. package/dist/utility/physical.js.map +1 -1
  433. package/dist/utility/pmrem.js +17 -43
  434. package/dist/utility/pmrem.js.map +1 -1
  435. package/dist/utility/sdf/bake.js +435 -0
  436. package/dist/utility/sdf/bake.js.map +1 -0
  437. package/dist/utility/sdf/bvh.js +576 -0
  438. package/dist/utility/sdf/bvh.js.map +1 -0
  439. package/dist/utility/serialization/manager.js +34 -6
  440. package/dist/utility/serialization/manager.js.map +1 -1
  441. package/dist/utility/serialization/scene/animation.js +46 -5
  442. package/dist/utility/serialization/scene/animation.js.map +1 -1
  443. package/dist/utility/serialization/scene/batch.js +11 -4
  444. package/dist/utility/serialization/scene/batch.js.map +1 -1
  445. package/dist/utility/serialization/scene/camera.js +87 -254
  446. package/dist/utility/serialization/scene/camera.js.map +1 -1
  447. package/dist/utility/serialization/scene/cloth.js +25 -0
  448. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  449. package/dist/utility/serialization/scene/common.js +14 -6
  450. package/dist/utility/serialization/scene/common.js.map +1 -1
  451. package/dist/utility/serialization/scene/foliage.js +821 -0
  452. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  453. package/dist/utility/serialization/scene/hair.js +11 -4
  454. package/dist/utility/serialization/scene/hair.js.map +1 -1
  455. package/dist/utility/serialization/scene/light.js +115 -7
  456. package/dist/utility/serialization/scene/light.js.map +1 -1
  457. package/dist/utility/serialization/scene/material.js +388 -220
  458. package/dist/utility/serialization/scene/material.js.map +1 -1
  459. package/dist/utility/serialization/scene/mesh.js +69 -4
  460. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  461. package/dist/utility/serialization/scene/node.js +140 -5
  462. package/dist/utility/serialization/scene/node.js.map +1 -1
  463. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  464. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  465. package/dist/utility/serialization/scene/particle.js +11 -4
  466. package/dist/utility/serialization/scene/particle.js.map +1 -1
  467. package/dist/utility/serialization/scene/physics.js +120 -0
  468. package/dist/utility/serialization/scene/physics.js.map +1 -0
  469. package/dist/utility/serialization/scene/primitive.js +124 -10
  470. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  471. package/dist/utility/serialization/scene/scene.js +1687 -51
  472. package/dist/utility/serialization/scene/scene.js.map +1 -1
  473. package/dist/utility/serialization/scene/sprite.js +11 -4
  474. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  475. package/dist/utility/serialization/scene/terrain.js +163 -33
  476. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  477. package/dist/utility/serialization/scene/text.js +11 -4
  478. package/dist/utility/serialization/scene/text.js.map +1 -1
  479. package/dist/utility/serialization/scene/water.js +1543 -264
  480. package/dist/utility/serialization/scene/water.js.map +1 -1
  481. package/dist/utility/serialization/types.js.map +1 -1
  482. package/dist/utility/shprojector.js +10 -22
  483. package/dist/utility/shprojector.js.map +1 -1
  484. package/dist/utility/textures/foam.js +170 -0
  485. package/dist/utility/textures/foam.js.map +1 -0
  486. package/dist/utility/textures/ggxlut.js +17 -43
  487. package/dist/utility/textures/ggxlut.js.map +1 -1
  488. package/dist/utility/textures/ltcdata.js +4 -4
  489. package/dist/utility/textures/ltcdata.js.map +1 -1
  490. package/dist/utility/textures/ltclut.js +16 -6
  491. package/dist/utility/textures/ltclut.js.map +1 -1
  492. package/dist/utility/unsupported.js +24 -0
  493. package/dist/utility/unsupported.js.map +1 -0
  494. package/dist/values.js +13 -1
  495. package/dist/values.js.map +1 -1
  496. package/package.json +25 -12
  497. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  498. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  499. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  500. package/src/asset/meshoptimizer/LICENSE +21 -0
  501. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  502. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -1,18 +1,19 @@
1
1
  import { Vector2, Vector3 } from '@zephyr3d/base';
2
2
  import '../../../scene/scene.js';
3
- import { MAX_GERSTNER_WAVE_COUNT } from '../../../values.js';
4
- import '../../../render/render_queue.js';
5
3
  import '../../../render/primitive.js';
6
4
  import '@zephyr3d/device';
5
+ import { MAX_GERSTNER_WAVE_COUNT } from '../../../values.js';
6
+ import '../../../render/render_queue.js';
7
7
  import '../../../material/shader/helper.js';
8
8
  import '../../../material/lambert.js';
9
9
  import '../../../material/blinn.js';
10
10
  import '../../../material/unlit.js';
11
+ import '../../../material/meshmaterial.js';
11
12
  import '../../../material/particle.js';
12
13
  import '../../../material/subsurfaceprofile.js';
13
- import '../../../material/skin.js';
14
+ import '../../../material/sssprofile.js';
15
+ import '../../../material/sss.js';
14
16
  import '../../../material/eye.js';
15
- import '../../../material/meshmaterial.js';
16
17
  import '../../../material/hair.js';
17
18
  import '../../../material/hairstrand.js';
18
19
  import '../../../material/grassmaterial.js';
@@ -30,11 +31,16 @@ import '../../../render/lightpass.js';
30
31
  import '../../../render/sky.js';
31
32
  import '../../../render/clipmap.js';
32
33
  import '../../../render/envlight.js';
34
+ import '../../../render/lod.js';
33
35
  import '../../../render/dualdepthpeeling_oit.js';
34
36
  import { FFTWaveGenerator } from '../../../render/fft_wavegenerator.js';
35
37
  import { GerstnerWaveGenerator } from '../../../render/gerstner_wavegenerator.js';
36
38
  import { FBMWaveGenerator } from '../../../render/fbm_wavegenerator.js';
39
+ import { WaterInteraction, WaterDisturber } from '../../../render/water_interaction.js';
37
40
  import '../../../render/rendergraph/scene_render_context.js';
41
+ import '../../../render/sdf/scene_sdf.js';
42
+ import '../../../render/sdf/global_sdf.js';
43
+ import '../../../render/gi/voxelize_pass.js';
38
44
  import { GraphNode } from '../../../scene/graph_node.js';
39
45
  import '../../../shadow/shadowmapper.js';
40
46
  import '../../../scene/mesh.js';
@@ -49,6 +55,7 @@ import '../../../scene/batchgroup.js';
49
55
  import '../../../scene/terrain-cm/terrain-cm.js';
50
56
  import '../../../scene/terrain-cm/grass.js';
51
57
  import '../../../scene/raycast_visitor.js';
58
+ import '../../../scene/foliage.js';
52
59
  import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../material/water.js';
53
60
 
54
61
  /** @internal */ function getFBMWaveGeneratorClass() {
@@ -201,31 +208,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
201
208
  this.foamContrast = value.num[0];
202
209
  }
203
210
  },
204
- {
205
- name: 'WaveLengthCascades',
206
- description: 'Wavelength values for the three FFT wave cascades',
207
- type: 'vec3',
208
- default: [
209
- 400,
210
- 100,
211
- 15
212
- ],
213
- options: {
214
- animatable: true,
215
- minValue: 0,
216
- maxValue: 1000
217
- },
218
- get (value) {
219
- value.num[0] = this.getWaveLength(0);
220
- value.num[1] = this.getWaveLength(1);
221
- value.num[2] = this.getWaveLength(2);
222
- },
223
- set (value) {
224
- this.setWaveLength(0, value.num[0]);
225
- this.setWaveLength(1, value.num[1]);
226
- this.setWaveLength(2, value.num[2]);
227
- }
228
- },
229
211
  {
230
212
  name: 'WaveStrengthCascades',
231
213
  description: 'Strength values for the three FFT wave cascades',
@@ -233,7 +215,7 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
233
215
  default: [
234
216
  0.4,
235
217
  0.4,
236
- 0.2
218
+ 0.4
237
219
  ],
238
220
  options: {
239
221
  animatable: true,
@@ -381,17 +363,12 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
381
363
  * A single Gerstner wave, as the editor sees one entry of the
382
364
  * `Waves` object array on a {@link GerstnerWaveGenerator}.
383
365
  *
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.
366
+ * While bound it is a live view: the field setters write straight through to
367
+ * the generator's wave buffer, so a property panel edit takes effect at once.
389
368
  *
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.
369
+ * The binding is transient: `_owner` and `_index` are set when the `Waves`
370
+ * getter builds the entry, and the editor rebuilds the array from that getter
371
+ * after every add/delete, so the cached index never drifts onto another wave.
395
372
  */ class GerstnerWave {
396
373
  _owner;
397
374
  _index;
@@ -439,10 +416,8 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
439
416
  /**
440
417
  * Writes this object's values into slot `index` of `owner`, unconditionally.
441
418
  *
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.
419
+ * Used by the `Waves` setter for a deserialized array, whose entries have no
420
+ * owner, and by `add` for a freshly created one.
446
421
  * @internal
447
422
  */ applyTo(owner, index) {
448
423
  owner.setWaveDirection(index, this._direction);
@@ -619,6 +594,384 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
619
594
  }
620
595
  };
621
596
  }
597
+ /**
598
+ * Inspector layout of the water's properties: group (sub-groups after a
599
+ * slash) and label of each, in the order the groups are shown; the inspector
600
+ * opens the groups marked open. Presentation only; serialized names are unaffected.
601
+ */ const WATER_PROPERTY_LAYOUT = [
602
+ {
603
+ group: 'Surface',
604
+ open: true,
605
+ props: [
606
+ [
607
+ 'WaveGenerator',
608
+ 'Wave Generator'
609
+ ],
610
+ [
611
+ 'Interaction',
612
+ 'Interaction'
613
+ ],
614
+ [
615
+ 'AnimationSpeed',
616
+ 'Animation Speed'
617
+ ],
618
+ [
619
+ 'Infinite',
620
+ 'Infinite'
621
+ ]
622
+ ]
623
+ },
624
+ {
625
+ group: 'Water Color',
626
+ open: true,
627
+ props: [
628
+ [
629
+ 'Absorption',
630
+ 'Absorption'
631
+ ],
632
+ [
633
+ 'AbsorptionScale',
634
+ 'Absorption Scale'
635
+ ],
636
+ [
637
+ 'Scattering',
638
+ 'Scattering'
639
+ ],
640
+ [
641
+ 'ScatteringScale',
642
+ 'Scattering Scale'
643
+ ]
644
+ ]
645
+ },
646
+ {
647
+ group: 'Lighting',
648
+ props: [
649
+ [
650
+ 'ReflectionStrength',
651
+ 'Reflection'
652
+ ],
653
+ [
654
+ 'SunScatteringIntensity',
655
+ 'Sun Scattering'
656
+ ],
657
+ [
658
+ 'ScatterAnisotropy',
659
+ 'Sun Scattering Anisotropy'
660
+ ],
661
+ [
662
+ 'SubsurfaceIntensity',
663
+ 'Crest Glow'
664
+ ],
665
+ [
666
+ 'SubsurfaceCrestHeight',
667
+ 'Crest Glow Height'
668
+ ],
669
+ [
670
+ 'SubsurfaceTint',
671
+ 'Crest Glow Tint'
672
+ ]
673
+ ]
674
+ },
675
+ {
676
+ group: 'Refraction',
677
+ props: [
678
+ [
679
+ 'RefractionMode',
680
+ 'Mode'
681
+ ],
682
+ [
683
+ 'RefractionScale',
684
+ 'Strength'
685
+ ],
686
+ [
687
+ 'RefractionBlur',
688
+ 'Blur'
689
+ ],
690
+ [
691
+ 'CheapRefractionDepth',
692
+ 'Offset Depth'
693
+ ]
694
+ ]
695
+ },
696
+ {
697
+ group: 'Foam',
698
+ props: [
699
+ [
700
+ 'FoamAmount',
701
+ 'Wave Foam'
702
+ ],
703
+ [
704
+ 'FoamColor',
705
+ 'Color'
706
+ ],
707
+ [
708
+ 'FoamTexture',
709
+ 'Texture'
710
+ ],
711
+ [
712
+ 'FoamTextureSize',
713
+ 'Texture Size'
714
+ ],
715
+ [
716
+ 'FoamFeather',
717
+ 'Edge Softness'
718
+ ]
719
+ ]
720
+ },
721
+ {
722
+ group: 'Foam/Look',
723
+ props: [
724
+ [
725
+ 'FoamFalloff',
726
+ 'Wave Foam Falloff'
727
+ ],
728
+ [
729
+ 'FoamNormalStrength',
730
+ 'Relief'
731
+ ],
732
+ [
733
+ 'FoamBubbleColor',
734
+ 'Bubble Color'
735
+ ],
736
+ [
737
+ 'FoamBubbleCoverage',
738
+ 'Bubbles'
739
+ ],
740
+ [
741
+ 'FoamBubbleDepth',
742
+ 'Bubble Depth'
743
+ ]
744
+ ]
745
+ },
746
+ {
747
+ group: 'Foam/Trails',
748
+ props: [
749
+ [
750
+ 'FoamTrailStrength',
751
+ 'Strength'
752
+ ],
753
+ [
754
+ 'FoamFadeRate',
755
+ 'Fade Rate'
756
+ ],
757
+ [
758
+ 'FoamDrift',
759
+ 'Wind Drift'
760
+ ],
761
+ [
762
+ 'FoamFieldSize',
763
+ 'Range'
764
+ ]
765
+ ]
766
+ },
767
+ {
768
+ group: 'Shore',
769
+ props: [
770
+ [
771
+ 'EdgeFadeWidth',
772
+ 'Edge Fade'
773
+ ]
774
+ ]
775
+ },
776
+ {
777
+ group: 'Shore/Waves',
778
+ props: [
779
+ [
780
+ 'ShoreWaveHeight',
781
+ 'Height'
782
+ ],
783
+ [
784
+ 'ShoreWaveLength',
785
+ 'Wavelength'
786
+ ],
787
+ [
788
+ 'ShoreWavePeriod',
789
+ 'Period'
790
+ ],
791
+ [
792
+ 'ShoreWaveZone',
793
+ 'Zone'
794
+ ],
795
+ [
796
+ 'ShoreWaveSharpness',
797
+ 'Sharpness'
798
+ ],
799
+ [
800
+ 'ShoreWaveLean',
801
+ 'Lean'
802
+ ],
803
+ [
804
+ 'ShoreWaveIrregularity',
805
+ 'Irregularity'
806
+ ]
807
+ ]
808
+ },
809
+ {
810
+ group: 'Shore/Waves/Foam',
811
+ props: [
812
+ [
813
+ 'ShoreWaveFoamStrength',
814
+ 'Breaking Foam'
815
+ ],
816
+ [
817
+ 'ShoreWaveFoamCoverage',
818
+ 'Breaking Coverage'
819
+ ],
820
+ [
821
+ 'ShoreWaveShallowFoamStrength',
822
+ 'Shallow Foam'
823
+ ],
824
+ [
825
+ 'ShoreWaveShallowFoamDepth',
826
+ 'Shallow Depth'
827
+ ],
828
+ [
829
+ 'WallFoamStrength',
830
+ 'Wall Foam'
831
+ ],
832
+ [
833
+ 'WallFoamMinSpeed',
834
+ 'Wall Min Speed'
835
+ ],
836
+ [
837
+ 'WallFoamMaxSpeed',
838
+ 'Wall Max Speed'
839
+ ],
840
+ [
841
+ 'WallFoamDrift',
842
+ 'Wall Foam Spread'
843
+ ]
844
+ ]
845
+ },
846
+ {
847
+ group: 'Caustics',
848
+ props: [
849
+ [
850
+ 'CausticsEnabled',
851
+ 'Enabled'
852
+ ],
853
+ [
854
+ 'CausticsIntensity',
855
+ 'Intensity'
856
+ ],
857
+ [
858
+ 'CausticsDepth',
859
+ 'Depth'
860
+ ],
861
+ [
862
+ 'CausticsRange',
863
+ 'Range'
864
+ ],
865
+ [
866
+ 'CausticsFadeDistance',
867
+ 'Fade Distance'
868
+ ],
869
+ [
870
+ 'CausticsSceneDepth',
871
+ 'Scene Depth'
872
+ ],
873
+ [
874
+ 'CausticsWarp',
875
+ 'Warp'
876
+ ],
877
+ [
878
+ 'CausticsMinDepth',
879
+ 'Min Depth'
880
+ ]
881
+ ]
882
+ },
883
+ {
884
+ group: 'Underwater',
885
+ props: [
886
+ [
887
+ 'UnderwaterEnabled',
888
+ 'Enabled'
889
+ ],
890
+ [
891
+ 'UnderwaterAmbientIntensity',
892
+ 'Ambient'
893
+ ],
894
+ [
895
+ 'UnderwaterGodRays',
896
+ 'God Rays'
897
+ ],
898
+ [
899
+ 'UnderwaterGodRayIntensity',
900
+ 'God Ray Intensity'
901
+ ],
902
+ [
903
+ 'UnderwaterGodRaySteps',
904
+ 'God Ray Steps'
905
+ ],
906
+ [
907
+ 'UnderwaterGodRayShadow',
908
+ 'God Ray Shadow'
909
+ ],
910
+ [
911
+ 'UnderwaterHysteresis',
912
+ 'Surface Hysteresis'
913
+ ]
914
+ ]
915
+ },
916
+ {
917
+ group: 'Advanced',
918
+ props: [
919
+ [
920
+ 'ViewDistance',
921
+ 'View Distance'
922
+ ],
923
+ [
924
+ 'GridScale',
925
+ 'Grid Scale'
926
+ ],
927
+ [
928
+ 'TAAStrength',
929
+ 'TAA Strength'
930
+ ],
931
+ [
932
+ 'Wireframe',
933
+ 'Wireframe'
934
+ ],
935
+ [
936
+ 'DebugOutput',
937
+ 'Debug Output'
938
+ ]
939
+ ]
940
+ }
941
+ ];
942
+ /** Gives the water's properties their group and label, ordered as {@link WATER_PROPERTY_LAYOUT}. */ function layoutWaterProps(props) {
943
+ const placement = new Map();
944
+ let order = 0;
945
+ for (const entry of WATER_PROPERTY_LAYOUT){
946
+ for (const [name, label] of entry.props){
947
+ placement.set(name, {
948
+ order: order++,
949
+ group: entry.group,
950
+ label,
951
+ open: !!entry.open
952
+ });
953
+ }
954
+ }
955
+ for (const prop of props){
956
+ const place = placement.get(prop.name);
957
+ if (place) {
958
+ prop.options = {
959
+ ...prop.options,
960
+ group: place.group,
961
+ label: prop.options?.label ?? place.label,
962
+ ...place.open ? {
963
+ defaultOpen: true
964
+ } : {}
965
+ };
966
+ }
967
+ }
968
+ // Stable: anything left out of the layout keeps its place after the rest
969
+ return props.map((prop, index)=>({
970
+ prop,
971
+ index,
972
+ order: placement.get(prop.name)?.order ?? order + index
973
+ })).sort((a, b)=>a.order - b.order).map((e)=>e.prop);
974
+ }
622
975
  /** @internal */ function getWaterClass(manager) {
623
976
  return {
624
977
  ctor: Water,
@@ -632,7 +985,7 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
632
985
  };
633
986
  },
634
987
  getProps () {
635
- return defineProps([
988
+ return layoutWaterProps(defineProps([
636
989
  {
637
990
  name: 'WaveGenerator',
638
991
  description: 'Wave generator used to drive the water surface',
@@ -659,6 +1012,26 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
659
1012
  }
660
1013
  }
661
1014
  },
1015
+ {
1016
+ name: 'Interaction',
1017
+ description: 'Dynamic height field layered over the surface, driven by things moving through the water: ripples, wakes and a foam trail. Null for none.',
1018
+ type: 'object',
1019
+ default: null,
1020
+ options: {
1021
+ objectTypes: [
1022
+ WaterInteraction
1023
+ ]
1024
+ },
1025
+ isNullable () {
1026
+ return true;
1027
+ },
1028
+ get (value) {
1029
+ value.object[0] = this.interaction ?? null;
1030
+ },
1031
+ set (value) {
1032
+ this.interaction = value.object[0] ?? null;
1033
+ }
1034
+ },
662
1035
  {
663
1036
  name: 'GridScale',
664
1037
  description: 'Scale of the water simulation grid',
@@ -856,6 +1229,26 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
856
1229
  this.causticsWarp = value.num[0];
857
1230
  }
858
1231
  },
1232
+ {
1233
+ name: 'CausticsMinDepth',
1234
+ description: "Water shallower than this, in metres, shows no caustics, fading in around it: raise it if dark or jagged caustic patches appear where the water thins out on a beach, lower it to bring the light patterns closer to the water's edge.",
1235
+ type: 'float',
1236
+ default: 0.15,
1237
+ options: {
1238
+ animatable: true,
1239
+ minValue: 0,
1240
+ maxValue: 2
1241
+ },
1242
+ isHidden () {
1243
+ return !this.causticsEnabled;
1244
+ },
1245
+ get (value) {
1246
+ value.num[0] = this.causticsMinDepth;
1247
+ },
1248
+ set (value) {
1249
+ this.causticsMinDepth = value.num[0];
1250
+ }
1251
+ },
859
1252
  {
860
1253
  name: 'UnderwaterEnabled',
861
1254
  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.',
@@ -976,30 +1369,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
976
1369
  this.underwaterHysteresis = value.num[0];
977
1370
  }
978
1371
  },
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
1372
  {
1004
1373
  name: 'RefractionMode',
1005
1374
  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.',
@@ -1056,9 +1425,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1056
1425
  minValue: 0,
1057
1426
  maxValue: 10
1058
1427
  },
1059
- isHidden () {
1060
- return this.material.mediumMode !== 'physical';
1061
- },
1062
1428
  get (value) {
1063
1429
  value.num[0] = this.material.absorption.x;
1064
1430
  value.num[1] = this.material.absorption.y;
@@ -1078,9 +1444,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1078
1444
  minValue: 0,
1079
1445
  maxValue: 10
1080
1446
  },
1081
- isHidden () {
1082
- return this.material.mediumMode !== 'physical';
1083
- },
1084
1447
  get (value) {
1085
1448
  value.num[0] = this.material.absorptionScale;
1086
1449
  },
@@ -1102,9 +1465,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1102
1465
  minValue: 0,
1103
1466
  maxValue: 10
1104
1467
  },
1105
- isHidden () {
1106
- return this.material.mediumMode !== 'physical';
1107
- },
1108
1468
  get (value) {
1109
1469
  value.num[0] = this.material.scattering.x;
1110
1470
  value.num[1] = this.material.scattering.y;
@@ -1124,9 +1484,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1124
1484
  minValue: 0,
1125
1485
  maxValue: 10
1126
1486
  },
1127
- isHidden () {
1128
- return this.material.mediumMode !== 'physical';
1129
- },
1130
1487
  get (value) {
1131
1488
  value.num[0] = this.material.scatteringScale;
1132
1489
  },
@@ -1134,26 +1491,6 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1134
1491
  this.material.scatteringScale = value.num[0];
1135
1492
  }
1136
1493
  },
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
1494
  {
1158
1495
  name: 'ReflectionStrength',
1159
1496
  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.',
@@ -1175,7 +1512,7 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1175
1512
  name: 'SubsurfaceIntensity',
1176
1513
  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
1514
  type: 'float',
1178
- default: 1.5,
1515
+ default: 0.5,
1179
1516
  options: {
1180
1517
  animatable: true,
1181
1518
  minValue: 0,
@@ -1189,20 +1526,43 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1189
1526
  }
1190
1527
  },
1191
1528
  {
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.',
1529
+ name: 'SubsurfaceCrestHeight',
1530
+ description: 'Height above the still-water level, in meters, over which the lit wall of a crest thins by a factor of e. Crests are thin and glow; troughs see the full path through the medium and are absorbed, so they keep only a tinted trace. Lower it for a calm sea whose crests barely rise, raise it so only the tallest waves light up.',
1194
1531
  type: 'float',
1195
- default: 60,
1532
+ default: 1.5,
1533
+ options: {
1534
+ animatable: true,
1535
+ minValue: 0.05,
1536
+ maxValue: 10
1537
+ },
1538
+ get (value) {
1539
+ value.num[0] = this.material.subsurfaceCrestHeight;
1540
+ },
1541
+ set (value) {
1542
+ this.material.subsurfaceCrestHeight = value.num[0];
1543
+ }
1544
+ },
1545
+ {
1546
+ name: 'SubsurfaceTint',
1547
+ description: 'Colour of the crest glow, before the crest gate tints it with the medium extinction. A warm yellow-green keeps some red on the crests where the troughs have lost it.',
1548
+ type: 'rgb',
1549
+ default: [
1550
+ 0.86,
1551
+ 0.98,
1552
+ 0.71
1553
+ ],
1196
1554
  options: {
1197
1555
  animatable: true,
1198
1556
  minValue: 0,
1199
- maxValue: 100
1557
+ maxValue: 1
1200
1558
  },
1201
1559
  get (value) {
1202
- value.num[0] = this.material.subsurfaceSteepness;
1560
+ value.num[0] = this.material.subsurfaceTint.x;
1561
+ value.num[1] = this.material.subsurfaceTint.y;
1562
+ value.num[2] = this.material.subsurfaceTint.z;
1203
1563
  },
1204
1564
  set (value) {
1205
- this.material.subsurfaceSteepness = value.num[0];
1565
+ this.material.subsurfaceTint = new Vector3(value.num[0], value.num[1], value.num[2]);
1206
1566
  }
1207
1567
  },
1208
1568
  {
@@ -1224,7 +1584,7 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1224
1584
  },
1225
1585
  {
1226
1586
  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.',
1587
+ description: 'Coverage of the foam on breaking wave crests, mapped from the folding the wave generator reports. 0 disables crest foam.',
1228
1588
  type: 'float',
1229
1589
  default: 1,
1230
1590
  options: {
@@ -1283,295 +1643,1214 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1283
1643
  }
1284
1644
  },
1285
1645
  {
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.',
1646
+ name: 'FoamFeather',
1647
+ description: 'How the white foam ends at its edges: low values cut crisp, separate clumps with hard outlines; high values let the foam thin out gradually into the bubbles beneath. Shared by all foam.',
1288
1648
  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.
1649
+ default: 0.4,
1293
1650
  options: {
1294
- minValue: 0,
1295
- maxValue: 4
1651
+ animatable: true,
1652
+ minValue: 0.001,
1653
+ maxValue: 1
1296
1654
  },
1297
1655
  get (value) {
1298
- value.num[0] = this.shoreFoamAmount;
1656
+ value.num[0] = this.material.foamFeather;
1299
1657
  },
1300
1658
  set (value) {
1301
- this.shoreFoamAmount = value.num[0];
1659
+ this.material.foamFeather = value.num[0];
1302
1660
  }
1303
1661
  },
1304
1662
  {
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.',
1663
+ name: 'FoamNormalStrength',
1664
+ description: 'How lumpy the white foam looks: higher values light it as a heaped-up relief with bright rims towards the sun and shaded hollows; 0 lights it as a flat sheet.',
1307
1665
  type: 'float',
1308
- default: 0.5,
1666
+ default: 3.5,
1309
1667
  options: {
1310
1668
  animatable: true,
1311
- minValue: 0.001,
1312
- maxValue: 20
1313
- },
1314
- isHidden () {
1315
- return this.shoreFoamAmount <= 0;
1669
+ minValue: 0,
1670
+ maxValue: 30
1316
1671
  },
1317
1672
  get (value) {
1318
- value.num[0] = this.shoreFoamDepth;
1673
+ value.num[0] = this.material.foamNormalStrength;
1319
1674
  },
1320
1675
  set (value) {
1321
- this.shoreFoamDepth = value.num[0];
1676
+ this.material.foamNormalStrength = value.num[0];
1322
1677
  }
1323
1678
  },
1324
1679
  {
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,
1680
+ name: 'FoamBubbleColor',
1681
+ description: 'Tint of the cloud of bubbles under and around the white foam, which gives it a soft, milky halo in the water instead of a cut-out edge.',
1682
+ type: 'rgb',
1683
+ default: [
1684
+ 0.64,
1685
+ 0.83,
1686
+ 0.82
1687
+ ],
1329
1688
  options: {
1330
1689
  animatable: true,
1331
- minValue: 0.01,
1332
- maxValue: 8
1333
- },
1334
- isHidden () {
1335
- return this.shoreFoamAmount <= 0;
1690
+ minValue: 0,
1691
+ maxValue: 1
1336
1692
  },
1337
1693
  get (value) {
1338
- value.num[0] = this.shoreFoamFalloff;
1694
+ value.num[0] = this.material.foamBubbleColor.x;
1695
+ value.num[1] = this.material.foamBubbleColor.y;
1696
+ value.num[2] = this.material.foamBubbleColor.z;
1339
1697
  },
1340
1698
  set (value) {
1341
- this.shoreFoamFalloff = value.num[0];
1699
+ this.material.foamBubbleColor = new Vector3(value.num[0], value.num[1], value.num[2]);
1342
1700
  }
1343
1701
  },
1344
1702
  {
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.',
1703
+ name: 'FoamBubbleCoverage',
1704
+ description: 'How strongly the bubble cloud shows and how far it reaches past the white foam, lightening the water around it. 0 removes it, leaving only the white foam.',
1347
1705
  type: 'float',
1348
- default: 2.5,
1706
+ default: 1.68,
1349
1707
  options: {
1350
1708
  animatable: true,
1351
1709
  minValue: 0,
1352
- maxValue: 20
1353
- },
1354
- isHidden () {
1355
- return this.shoreFoamAmount <= 0;
1710
+ maxValue: 5
1356
1711
  },
1357
1712
  get (value) {
1358
- value.num[0] = this.shoreFoamScale;
1713
+ value.num[0] = this.material.foamBubbleCoverage;
1359
1714
  },
1360
1715
  set (value) {
1361
- this.shoreFoamScale = value.num[0];
1716
+ this.material.foamBubbleCoverage = value.num[0];
1362
1717
  }
1363
1718
  },
1364
1719
  {
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.',
1720
+ name: 'FoamBubbleDepth',
1721
+ description: 'How deep under the surface the bubble cloud seems to float, in metres: it slides against the white foam as the view moves, giving the foam depth. 0 keeps it on the surface.',
1367
1722
  type: 'float',
1368
- default: 0.5,
1723
+ default: 0.14,
1369
1724
  options: {
1370
1725
  animatable: true,
1371
1726
  minValue: 0,
1372
- maxValue: 2
1373
- },
1374
- isHidden () {
1375
- return this.shoreFoamAmount <= 0;
1727
+ maxValue: 1
1376
1728
  },
1377
1729
  get (value) {
1378
- value.num[0] = this.shoreFoamWashAmount;
1730
+ value.num[0] = this.material.foamBubbleDepth;
1379
1731
  },
1380
1732
  set (value) {
1381
- this.shoreFoamWashAmount = value.num[0];
1733
+ this.material.foamBubbleDepth = value.num[0];
1734
+ }
1735
+ },
1736
+ {
1737
+ name: 'FoamTexture',
1738
+ description: 'Pattern the foam is cut from (red channel): as the foam thickens it shows the bright parts of the texture first and fills the dark ones last, so bright clumps appear before dark holes close. Empty for the built-in bubble pattern, which thickens as any foam texture does, so the same settings look alike with or without one. Shared by all foam.',
1739
+ type: 'object',
1740
+ default: '',
1741
+ options: {
1742
+ mimeTypes: [
1743
+ 'image/jpeg',
1744
+ 'image/png',
1745
+ 'image/tga',
1746
+ 'image/vnd.radiance',
1747
+ 'image/x-dds',
1748
+ 'image/webp'
1749
+ ]
1750
+ },
1751
+ isNullable () {
1752
+ return true;
1753
+ },
1754
+ get (value) {
1755
+ value.str[0] = manager.getAssetId(this.material.foamTexture) ?? '';
1756
+ },
1757
+ async set (value) {
1758
+ if (!value) {
1759
+ this.material.foamTexture = null;
1760
+ } else if (value.str[0]) {
1761
+ const assetId = value.str[0];
1762
+ let tex;
1763
+ try {
1764
+ tex = await manager.fetchTexture(assetId);
1765
+ } catch (err) {
1766
+ console.error(`Load asset failed: ${value.str[0]}: ${err}`);
1767
+ tex = null;
1768
+ }
1769
+ if (tex?.isTexture2D()) {
1770
+ this.material.foamTexture = tex;
1771
+ } else {
1772
+ console.error('Invalid texture type');
1773
+ }
1774
+ }
1382
1775
  }
1383
1776
  },
1384
1777
  {
1385
- name: 'ShoreFoamWashSpeed',
1386
- description: 'Run-up cycles per second. Swell rather than wind waves, so well under 1.',
1778
+ name: 'FoamTextureSize',
1779
+ description: 'How large the foam pattern is on the water, in metres per repeat of the foam texture: larger values give bigger clumps and holes.',
1387
1780
  type: 'float',
1388
- default: 0.12,
1781
+ default: 4,
1389
1782
  options: {
1390
1783
  animatable: true,
1391
- minValue: 0,
1392
- maxValue: 2
1393
- },
1394
- isHidden () {
1395
- return this.shoreFoamAmount <= 0;
1784
+ minValue: 0.01,
1785
+ maxValue: 50
1396
1786
  },
1397
1787
  get (value) {
1398
- value.num[0] = this.shoreFoamWashSpeed;
1788
+ value.num[0] = this.material.foamTextureSize;
1399
1789
  },
1400
1790
  set (value) {
1401
- this.shoreFoamWashSpeed = value.num[0];
1791
+ this.material.foamTextureSize = value.num[0];
1402
1792
  }
1403
1793
  },
1404
1794
  {
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.',
1795
+ name: 'FoamTrailStrength',
1796
+ description: 'How much foam the breaking crests of the open water leave behind: the foam lingers after the crest has passed, drifts on the wind and fades into streaks and patches. 0 keeps foam only while a crest breaks.',
1407
1797
  type: 'float',
1408
- default: 0.03,
1798
+ default: 1,
1409
1799
  options: {
1410
1800
  animatable: true,
1411
1801
  minValue: 0,
1412
- maxValue: 1
1413
- },
1414
- isHidden () {
1415
- return this.shoreFoamAmount <= 0;
1802
+ maxValue: 5
1416
1803
  },
1417
1804
  get (value) {
1418
- value.num[0] = this.shoreFoamWashScale;
1805
+ value.num[0] = this.foamTrailStrength;
1419
1806
  },
1420
1807
  set (value) {
1421
- this.shoreFoamWashScale = value.num[0];
1808
+ this.foamTrailStrength = value.num[0];
1422
1809
  }
1423
1810
  },
1424
1811
  {
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.',
1812
+ name: 'FoamFadeRate',
1813
+ description: 'How quickly lingering foam dies away, behind breaking crests and shore waves alike: low values leave long-lasting trails and sheets of foam, high values keep only fresh foam at the breaking crests.',
1427
1814
  type: 'float',
1428
- default: 1,
1815
+ default: 0.8,
1429
1816
  options: {
1430
1817
  animatable: true,
1431
- minValue: 0,
1818
+ minValue: 0.01,
1432
1819
  maxValue: 20
1433
1820
  },
1434
- isHidden () {
1435
- return this.material.refractionMode !== 'offset';
1436
- },
1437
1821
  get (value) {
1438
- value.num[0] = this.material.cheapRefractionDepth;
1822
+ value.num[0] = this.foamFadeRate;
1439
1823
  },
1440
1824
  set (value) {
1441
- this.material.cheapRefractionDepth = value.num[0];
1825
+ this.foamFadeRate = value.num[0];
1442
1826
  }
1443
1827
  },
1444
1828
  {
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.',
1829
+ name: 'FoamDrift',
1830
+ description: 'How fast lingering foam drifts downwind, as a share of the wind speed: about 0.03 in nature. 0 leaves it where the crest broke.',
1447
1831
  type: 'float',
1448
- default: 1,
1832
+ default: 0.03,
1449
1833
  options: {
1450
1834
  animatable: true,
1451
1835
  minValue: 0,
1452
- maxValue: 4
1836
+ maxValue: 0.2
1453
1837
  },
1454
1838
  get (value) {
1455
- value.num[0] = this.material.refractionBlur;
1839
+ value.num[0] = this.foamDrift;
1456
1840
  },
1457
1841
  set (value) {
1458
- this.material.refractionBlur = value.num[0];
1842
+ this.foamDrift = value.num[0];
1459
1843
  }
1460
1844
  },
1461
1845
  {
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.',
1846
+ name: 'FoamFieldSize',
1847
+ description: 'Size in metres of the square of water around where the camera looks in which lingering foam keeps its finest detail. Coarser rings reach eight times as far before foam shows only on the breaking crests; larger values reach further at coarser detail throughout.',
1464
1848
  type: 'float',
1465
- default: DEFAULT_SCATTER_ANISOTROPY,
1849
+ default: 128,
1850
+ options: {
1851
+ animatable: false,
1852
+ minValue: 16,
1853
+ maxValue: 1024
1854
+ },
1855
+ get (value) {
1856
+ value.num[0] = this.foamFieldSize;
1857
+ },
1858
+ set (value) {
1859
+ this.foamFieldSize = value.num[0];
1860
+ }
1861
+ },
1862
+ {
1863
+ name: 'EdgeFadeWidth',
1864
+ description: 'Thickness in metres over which a thin sheet of water fades in from the ground under it, so swash running up the sand shows the sand through it. 0 disables it.',
1865
+ type: 'float',
1866
+ default: 0.05,
1466
1867
  options: {
1467
1868
  animatable: true,
1468
1869
  minValue: 0,
1469
- maxValue: 0.95
1870
+ maxValue: 1
1470
1871
  },
1471
1872
  get (value) {
1472
- value.num[0] = this.material.scatterAnisotropy;
1873
+ value.num[0] = this.edgeFadeWidth;
1473
1874
  },
1474
1875
  set (value) {
1475
- this.material.scatterAnisotropy = value.num[0];
1876
+ this.edgeFadeWidth = value.num[0];
1476
1877
  }
1477
1878
  },
1478
1879
  {
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.',
1880
+ name: 'ShoreWaveHeight',
1881
+ description: 'Crest to trough height in metres of the waves rolling in to the shore and washing up the beach, 0 for none. They come square on to the coast whatever its shape, bunch up as the water shallows, sharpen and lean as they near the shore, and each crest lifts the water up the sand and lets it drain back; boats ride them. Needs the scene signed distance field: WebGPU with the scene SDFEnabled on.',
1481
1882
  type: 'float',
1482
- default: 1,
1883
+ default: 0,
1483
1884
  options: {
1484
1885
  animatable: true,
1485
1886
  minValue: 0,
1486
- maxValue: 4
1887
+ maxValue: 3
1888
+ },
1889
+ isHidden () {
1890
+ return false;
1487
1891
  },
1488
1892
  get (value) {
1489
- value.num[0] = this.material.refractionScale;
1893
+ value.num[0] = this.shoreWaveHeight;
1490
1894
  },
1491
1895
  set (value) {
1492
- this.material.refractionScale = value.num[0];
1896
+ this.shoreWaveHeight = value.num[0];
1493
1897
  }
1494
1898
  },
1495
1899
  {
1496
- name: 'TAAStrength',
1497
- description: 'Temporal anti-aliasing strength for the water surface',
1900
+ name: 'ShoreWaveLength',
1901
+ description: 'Distance in metres between crests at the outer edge of the zone. They bunch up towards the shore as real waves do in shallowing water.',
1498
1902
  type: 'float',
1499
- default: 0.4,
1903
+ default: 8,
1500
1904
  options: {
1501
- minValue: 0,
1502
- maxValue: 1
1905
+ animatable: true,
1906
+ minValue: 0.5,
1907
+ maxValue: 100
1908
+ },
1909
+ isHidden () {
1910
+ return this.shoreWaveHeight <= 0;
1503
1911
  },
1504
1912
  get (value) {
1505
- value.num[0] = this.TAAStrength;
1913
+ value.num[0] = this.shoreWaveLength;
1506
1914
  },
1507
1915
  set (value) {
1508
- this.TAAStrength = value.num[0];
1916
+ this.shoreWaveLength = value.num[0];
1509
1917
  }
1510
1918
  },
1511
1919
  {
1512
- name: 'ScatterRampTexture',
1513
- description: 'Ramp texture used for water scatter lighting',
1514
- type: 'object',
1515
- default: null,
1516
- isNullable () {
1517
- return true;
1920
+ name: 'ShoreWavePeriod',
1921
+ description: 'Seconds between successive shore waves.',
1922
+ type: 'float',
1923
+ default: 6,
1924
+ options: {
1925
+ animatable: true,
1926
+ minValue: 0.5,
1927
+ maxValue: 30
1928
+ },
1929
+ isHidden () {
1930
+ return this.shoreWaveHeight <= 0;
1518
1931
  },
1519
1932
  get (value) {
1520
- value.str[0] = manager.getAssetId(this.material.scatterRampTexture) ?? '';
1933
+ value.num[0] = this.shoreWavePeriod;
1521
1934
  },
1522
- async set (value) {
1523
- if (!value) {
1524
- this.material.scatterRampTexture = null;
1525
- } else {
1526
- if (value.str[0]) {
1527
- const assetId = value.str[0];
1528
- let tex;
1529
- try {
1530
- tex = await manager.fetchTexture(assetId);
1531
- } catch (err) {
1532
- console.error(`Load asset failed: ${value.str[0]}: ${err}`);
1533
- tex = null;
1534
- }
1535
- if (tex?.isTexture2D()) {
1536
- this.material.scatterRampTexture = tex;
1537
- } else {
1538
- console.error('Invalid texture type');
1539
- }
1540
- }
1541
- }
1935
+ set (value) {
1936
+ this.shoreWavePeriod = value.num[0];
1542
1937
  }
1543
1938
  },
1544
1939
  {
1545
- name: 'AbsorptionRampTexture',
1546
- description: 'Ramp texture used for water absorption',
1547
- type: 'object',
1548
- default: null,
1549
- isNullable () {
1550
- return true;
1940
+ name: 'ShoreWaveZone',
1941
+ description: 'How far out from the waterline the shore waves rise, in metres. They grow over the zone and break near its inner end.',
1942
+ type: 'float',
1943
+ default: 20,
1944
+ options: {
1945
+ animatable: true,
1946
+ minValue: 1,
1947
+ maxValue: 200
1948
+ },
1949
+ isHidden () {
1950
+ return this.shoreWaveHeight <= 0;
1551
1951
  },
1552
1952
  get (value) {
1553
- value.str[0] = manager.getAssetId(this.material.absorptionRampTexture) ?? '';
1953
+ value.num[0] = this.shoreWaveZone;
1554
1954
  },
1555
- async set (value) {
1556
- if (!value) {
1557
- this.material.absorptionRampTexture = null;
1558
- } else {
1559
- if (value.str[0]) {
1560
- const assetId = value.str[0];
1561
- let tex;
1562
- try {
1563
- tex = await manager.fetchTexture(assetId);
1564
- } catch (err) {
1565
- console.error(`Load asset failed: ${value.str[0]}: ${err}`);
1566
- tex = null;
1567
- }
1568
- if (tex?.isTexture2D()) {
1569
- this.material.absorptionRampTexture = tex;
1570
- } else {
1571
- console.error('Invalid texture type');
1572
- }
1955
+ set (value) {
1956
+ this.shoreWaveZone = value.num[0];
1957
+ }
1958
+ },
1959
+ {
1960
+ name: 'ShoreWaveSharpness',
1961
+ description: 'How sharp the crests become at the shore: 0 keeps a rounded sine, towards 1 a pointed crest between long flat troughs.',
1962
+ type: 'float',
1963
+ default: 0.7,
1964
+ options: {
1965
+ animatable: true,
1966
+ minValue: 0,
1967
+ maxValue: 0.95
1968
+ },
1969
+ isHidden () {
1970
+ return this.shoreWaveHeight <= 0;
1971
+ },
1972
+ get (value) {
1973
+ value.num[0] = this.shoreWaveSharpness;
1974
+ },
1975
+ set (value) {
1976
+ this.shoreWaveSharpness = value.num[0];
1977
+ }
1978
+ },
1979
+ {
1980
+ name: 'ShoreWaveLean',
1981
+ description: 'How far the crests lean towards the shore there: 0 keeps them upright, 1 gives a steep front face and a long gentle back.',
1982
+ type: 'float',
1983
+ default: 0.5,
1984
+ options: {
1985
+ animatable: true,
1986
+ minValue: 0,
1987
+ maxValue: 1
1988
+ },
1989
+ isHidden () {
1990
+ return this.shoreWaveHeight <= 0;
1991
+ },
1992
+ get (value) {
1993
+ value.num[0] = this.shoreWaveLean;
1994
+ },
1995
+ set (value) {
1996
+ this.shoreWaveLean = value.num[0];
1997
+ }
1998
+ },
1999
+ {
2000
+ name: 'ShoreWaveIrregularity',
2001
+ description: 'How irregular the shore waves are: at 0 the crests roll in as parallel lines evenly spaced; higher, each wave comes with a spacing and a bend of its own, so crests close up and spread apart, curve differently along the shore and keep those shapes as they come in.',
2002
+ type: 'float',
2003
+ default: 0.6,
2004
+ options: {
2005
+ animatable: true,
2006
+ minValue: 0,
2007
+ maxValue: 1
2008
+ },
2009
+ isHidden () {
2010
+ return this.shoreWaveHeight <= 0;
2011
+ },
2012
+ get (value) {
2013
+ value.num[0] = this.shoreWaveIrregularity;
2014
+ },
2015
+ set (value) {
2016
+ this.shoreWaveIrregularity = value.num[0];
2017
+ }
2018
+ },
2019
+ {
2020
+ name: 'ShoreWaveFoamStrength',
2021
+ description: 'How much foam the breaking shore waves throw up: higher values give thicker, whiter foam on and behind the crests. Balance it against the fade rate.',
2022
+ type: 'float',
2023
+ default: 1,
2024
+ options: {
2025
+ animatable: true,
2026
+ minValue: 0,
2027
+ maxValue: 5
2028
+ },
2029
+ isHidden () {
2030
+ return this.shoreWaveHeight <= 0;
2031
+ },
2032
+ get (value) {
2033
+ value.num[0] = this.shoreWaveFoamStrength;
2034
+ },
2035
+ set (value) {
2036
+ this.shoreWaveFoamStrength = value.num[0];
2037
+ }
2038
+ },
2039
+ {
2040
+ name: 'ShoreWaveFoamCoverage',
2041
+ description: 'How much of each shore wave foams: low values foam only at the steepest breaking fronts, high values spread foam over more of the wave.',
2042
+ type: 'float',
2043
+ default: 0.55,
2044
+ options: {
2045
+ animatable: true,
2046
+ minValue: 0,
2047
+ maxValue: 1
2048
+ },
2049
+ isHidden () {
2050
+ return this.shoreWaveHeight <= 0;
2051
+ },
2052
+ get (value) {
2053
+ value.num[0] = this.shoreWaveFoamCoverage;
2054
+ },
2055
+ set (value) {
2056
+ this.shoreWaveFoamCoverage = value.num[0];
2057
+ }
2058
+ },
2059
+ {
2060
+ name: 'ShoreWaveShallowFoamDepth',
2061
+ description: 'How deep the water can be and still churn up foam as the waves run in, in metres: larger values widen the band of foam along the beach.',
2062
+ type: 'float',
2063
+ default: 0.65,
2064
+ options: {
2065
+ animatable: true,
2066
+ minValue: 0.01,
2067
+ maxValue: 3
2068
+ },
2069
+ isHidden () {
2070
+ return this.shoreWaveHeight <= 0;
2071
+ },
2072
+ get (value) {
2073
+ value.num[0] = this.shoreWaveShallowFoamDepth;
2074
+ },
2075
+ set (value) {
2076
+ this.shoreWaveShallowFoamDepth = value.num[0];
2077
+ }
2078
+ },
2079
+ {
2080
+ name: 'ShoreWaveShallowFoamStrength',
2081
+ description: "How much foam the shallow water at the beach makes as the waves wash over it: higher values give a denser white wash, 0 leaves only the breaking crests' foam.",
2082
+ type: 'float',
2083
+ default: 2,
2084
+ options: {
2085
+ animatable: true,
2086
+ minValue: 0,
2087
+ maxValue: 5
2088
+ },
2089
+ isHidden () {
2090
+ return this.shoreWaveHeight <= 0;
2091
+ },
2092
+ get (value) {
2093
+ value.num[0] = this.shoreWaveShallowFoamStrength;
2094
+ },
2095
+ set (value) {
2096
+ this.shoreWaveShallowFoamStrength = value.num[0];
2097
+ }
2098
+ },
2099
+ {
2100
+ name: 'WallFoamStrength',
2101
+ description: 'How solid the ring of foam is where the water dashes against rocks, walls and piers standing in it: 1 for a thick white fringe, lower for a thinner, more see-through one, 0 for none. The ring always goes all the way round; how far it spreads is Wall Foam Spread. Needs the shore waves on.',
2102
+ type: 'float',
2103
+ default: 1,
2104
+ options: {
2105
+ animatable: true,
2106
+ minValue: 0,
2107
+ maxValue: 1
2108
+ },
2109
+ isHidden () {
2110
+ return this.shoreWaveHeight <= 0;
2111
+ },
2112
+ get (value) {
2113
+ value.num[0] = this.wallFoamStrength;
2114
+ },
2115
+ set (value) {
2116
+ this.wallFoamStrength = value.num[0];
2117
+ }
2118
+ },
2119
+ {
2120
+ name: 'WallFoamMinSpeed',
2121
+ description: 'How hard the water has to hit a wall before it foams there, in metres per second: raise it to keep calm water clean against rocks, lower it to fringe them with foam in a gentle swell.',
2122
+ type: 'float',
2123
+ default: 0.2,
2124
+ options: {
2125
+ animatable: true,
2126
+ minValue: 0,
2127
+ maxValue: 5
2128
+ },
2129
+ isHidden () {
2130
+ return this.shoreWaveHeight <= 0;
2131
+ },
2132
+ get (value) {
2133
+ value.num[0] = this.wallFoamMinSpeed;
2134
+ },
2135
+ set (value) {
2136
+ this.wallFoamMinSpeed = value.num[0];
2137
+ }
2138
+ },
2139
+ {
2140
+ name: 'WallFoamMaxSpeed',
2141
+ description: 'How hard the water has to hit a wall for the thickest foam, in metres per second: lower it for full white water against rocks in a moderate sea, raise it to keep that for a heavy one.',
2142
+ type: 'float',
2143
+ default: 1.5,
2144
+ options: {
2145
+ animatable: true,
2146
+ minValue: 0.01,
2147
+ maxValue: 10
2148
+ },
2149
+ isHidden () {
2150
+ return this.shoreWaveHeight <= 0;
2151
+ },
2152
+ get (value) {
2153
+ value.num[0] = this.wallFoamMaxSpeed;
2154
+ },
2155
+ set (value) {
2156
+ this.wallFoamMaxSpeed = value.num[0];
2157
+ }
2158
+ },
2159
+ {
2160
+ name: 'WallFoamDrift',
2161
+ description: 'How fast the foam spreads out from rocks, walls and piers, in metres per second: higher for a wider ring of foam around them, lower to keep it close in. It spreads evenly on every side whichever way the wind blows.',
2162
+ type: 'float',
2163
+ default: 0.3,
2164
+ options: {
2165
+ animatable: true,
2166
+ minValue: 0,
2167
+ maxValue: 3
2168
+ },
2169
+ isHidden () {
2170
+ return this.shoreWaveHeight <= 0;
2171
+ },
2172
+ get (value) {
2173
+ value.num[0] = this.wallFoamDrift;
2174
+ },
2175
+ set (value) {
2176
+ this.wallFoamDrift = value.num[0];
2177
+ }
2178
+ },
2179
+ {
2180
+ name: 'SurfFoamDuration',
2181
+ description: 'How long, in seconds, the foam of each breaking wave lasts as the wave comes in and washes up the beach: higher for long white trails behind the crests and foam carried all the way up the sand, lower for brief flashes of white that clear before the wave has run up.',
2182
+ type: 'float',
2183
+ default: 1.5,
2184
+ options: {
2185
+ animatable: true,
2186
+ minValue: 0.05,
2187
+ maxValue: 6
2188
+ },
2189
+ isHidden () {
2190
+ return this.shoreWaveHeight <= 0;
2191
+ },
2192
+ get (value) {
2193
+ value.num[0] = this.surfFoamDuration;
2194
+ },
2195
+ set (value) {
2196
+ this.surfFoamDuration = value.num[0];
2197
+ }
2198
+ },
2199
+ {
2200
+ name: 'FoamSettleDepth',
2201
+ description: 'Water depth in metres at and below which foam stops drifting and stays where it is, on the thin wash and the wet sand alike, until it fades: higher to leave foam lying over a wider band of the shallows and the beach, lower to let it drift until the water is almost gone.',
2202
+ type: 'float',
2203
+ default: 0.02,
2204
+ options: {
2205
+ animatable: true,
2206
+ minValue: 0,
2207
+ maxValue: 1
2208
+ },
2209
+ isHidden () {
2210
+ return this.shoreWaveHeight <= 0;
2211
+ },
2212
+ get (value) {
2213
+ value.num[0] = this.foamSettleDepth;
2214
+ },
2215
+ set (value) {
2216
+ this.foamSettleDepth = value.num[0];
2217
+ }
2218
+ },
2219
+ {
2220
+ name: 'FoamDriftDepth',
2221
+ description: 'Water depth in metres at and beyond which foam drifts freely with the water; between this and FoamSettleDepth it slows down the shallower the water gets. Higher to calm the foam over a wider band of shallow water, lower to keep it moving until close in.',
2222
+ type: 'float',
2223
+ default: 0.3,
2224
+ options: {
2225
+ animatable: true,
2226
+ minValue: 0,
2227
+ maxValue: 3
2228
+ },
2229
+ isHidden () {
2230
+ return this.shoreWaveHeight <= 0;
2231
+ },
2232
+ get (value) {
2233
+ value.num[0] = this.foamDriftDepth;
2234
+ },
2235
+ set (value) {
2236
+ this.foamDriftDepth = value.num[0];
2237
+ }
2238
+ },
2239
+ {
2240
+ name: 'SettledFoamFade',
2241
+ description: 'How fast foam that has come to rest in shallow water and on the sand fades, compared with foam on open water: lower to leave the foam lying on the beach longer after each wave drains, 1 to let it vanish as quickly as foam out at sea.',
2242
+ type: 'float',
2243
+ default: 0.25,
2244
+ options: {
2245
+ animatable: true,
2246
+ minValue: 0.01,
2247
+ maxValue: 1
2248
+ },
2249
+ isHidden () {
2250
+ return this.shoreWaveHeight <= 0;
2251
+ },
2252
+ get (value) {
2253
+ value.num[0] = this.settledFoamFade;
2254
+ },
2255
+ set (value) {
2256
+ this.settledFoamFade = value.num[0];
2257
+ }
2258
+ },
2259
+ {
2260
+ name: 'CheapRefractionDepth',
2261
+ 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.',
2262
+ type: 'float',
2263
+ default: 1,
2264
+ options: {
2265
+ animatable: true,
2266
+ minValue: 0,
2267
+ maxValue: 20
2268
+ },
2269
+ isHidden () {
2270
+ return this.material.refractionMode !== 'offset';
2271
+ },
2272
+ get (value) {
2273
+ value.num[0] = this.material.cheapRefractionDepth;
2274
+ },
2275
+ set (value) {
2276
+ this.material.cheapRefractionDepth = value.num[0];
2277
+ }
2278
+ },
2279
+ {
2280
+ name: 'RefractionBlur',
2281
+ 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.',
2282
+ type: 'float',
2283
+ default: 1,
2284
+ options: {
2285
+ animatable: true,
2286
+ minValue: 0,
2287
+ maxValue: 4
2288
+ },
2289
+ get (value) {
2290
+ value.num[0] = this.material.refractionBlur;
2291
+ },
2292
+ set (value) {
2293
+ this.material.refractionBlur = value.num[0];
2294
+ }
2295
+ },
2296
+ {
2297
+ name: 'ScatterAnisotropy',
2298
+ 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.',
2299
+ type: 'float',
2300
+ default: DEFAULT_SCATTER_ANISOTROPY,
2301
+ options: {
2302
+ animatable: true,
2303
+ minValue: 0,
2304
+ maxValue: 0.95
2305
+ },
2306
+ get (value) {
2307
+ value.num[0] = this.material.scatterAnisotropy;
2308
+ },
2309
+ set (value) {
2310
+ this.material.scatterAnisotropy = value.num[0];
2311
+ }
2312
+ },
2313
+ {
2314
+ name: 'RefractionScale',
2315
+ 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.',
2316
+ type: 'float',
2317
+ default: 1,
2318
+ options: {
2319
+ animatable: true,
2320
+ minValue: 0,
2321
+ maxValue: 4
2322
+ },
2323
+ get (value) {
2324
+ value.num[0] = this.material.refractionScale;
2325
+ },
2326
+ set (value) {
2327
+ this.material.refractionScale = value.num[0];
2328
+ }
2329
+ },
2330
+ {
2331
+ name: 'TAAStrength',
2332
+ description: 'Share of the temporal anti-aliasing history kept on the water surface. Lower trades smoothing for less smearing of fast waves; much lower lets the sub-pixel camera jitter through, and the waterline visibly shakes. 0 keeps no history at all.',
2333
+ type: 'float',
2334
+ default: 0.9,
2335
+ options: {
2336
+ minValue: 0,
2337
+ maxValue: 1
2338
+ },
2339
+ get (value) {
2340
+ value.num[0] = this.TAAStrength;
2341
+ },
2342
+ set (value) {
2343
+ this.TAAStrength = value.num[0];
2344
+ }
2345
+ }
2346
+ ]));
2347
+ }
2348
+ };
2349
+ }
2350
+ const WATER_INTERACTION_FOLLOW_MODES = [
2351
+ {
2352
+ label: 'Camera',
2353
+ value: 'camera'
2354
+ },
2355
+ {
2356
+ label: 'Node',
2357
+ value: 'node'
2358
+ },
2359
+ {
2360
+ label: 'Fixed',
2361
+ value: 'fixed'
2362
+ }
2363
+ ];
2364
+ const WATER_DISTURBER_SHAPES = [
2365
+ {
2366
+ label: 'Sphere',
2367
+ value: 'sphere'
2368
+ },
2369
+ {
2370
+ label: 'Capsule',
2371
+ value: 'capsule'
2372
+ },
2373
+ {
2374
+ label: 'Box',
2375
+ value: 'box'
2376
+ }
2377
+ ];
2378
+ /** @internal */ function getWaterInteractionClass() {
2379
+ return {
2380
+ ctor: WaterInteraction,
2381
+ name: 'WaterInteraction',
2382
+ getProps () {
2383
+ return defineProps([
2384
+ {
2385
+ name: 'Resolution',
2386
+ description: 'Texels along each side of the simulation window. Changing it discards the field.',
2387
+ type: 'int',
2388
+ default: 512,
2389
+ options: {
2390
+ minValue: 64,
2391
+ maxValue: 2048
2392
+ },
2393
+ get (value) {
2394
+ value.num[0] = this.resolution;
2395
+ },
2396
+ set (value) {
2397
+ this.resolution = value.num[0];
2398
+ }
2399
+ },
2400
+ {
2401
+ name: 'WindowSize',
2402
+ description: 'Side of the simulation window in metres. Changing it discards the field.',
2403
+ type: 'float',
2404
+ default: 64,
2405
+ options: {
2406
+ minValue: 4,
2407
+ maxValue: 512
2408
+ },
2409
+ get (value) {
2410
+ value.num[0] = this.windowSize;
2411
+ },
2412
+ set (value) {
2413
+ this.windowSize = value.num[0];
2414
+ }
2415
+ },
2416
+ {
2417
+ name: 'WaveSpeed',
2418
+ description: 'Speed disturbances spread at, in metres per second. Clamped to what the window can integrate stably.',
2419
+ type: 'float',
2420
+ default: 1.5,
2421
+ options: {
2422
+ animatable: true,
2423
+ minValue: 0,
2424
+ maxValue: 10
2425
+ },
2426
+ get (value) {
2427
+ value.num[0] = this.waveSpeed;
2428
+ },
2429
+ set (value) {
2430
+ this.waveSpeed = value.num[0];
2431
+ }
2432
+ },
2433
+ {
2434
+ name: 'ShallowDepth',
2435
+ description: 'Depth in metres below which waves slow down as shallow water waves do: WaveSpeed in deeper water, falling with the square root of the depth below this. A wave running onto a beach then slows, shortens, grows and turns to meet the shore. 0 ignores the depth. The depth comes from the scene signed distance field where SDFEnabled is on, else from the terrain.',
2436
+ type: 'float',
2437
+ default: 2,
2438
+ options: {
2439
+ animatable: true,
2440
+ minValue: 0,
2441
+ maxValue: 50
2442
+ },
2443
+ get (value) {
2444
+ value.num[0] = this.shallowDepth;
2445
+ },
2446
+ set (value) {
2447
+ this.shallowDepth = value.num[0];
2448
+ }
2449
+ },
2450
+ {
2451
+ name: 'ShoreAbsorbDepth',
2452
+ description: 'Depth in metres over which the beach absorbs the waves reaching it, instead of reflecting them back out to sea.',
2453
+ type: 'float',
2454
+ default: 0.2,
2455
+ options: {
2456
+ animatable: true,
2457
+ minValue: 0,
2458
+ maxValue: 5
2459
+ },
2460
+ isHidden () {
2461
+ return this.shallowDepth <= 0;
2462
+ },
2463
+ get (value) {
2464
+ value.num[0] = this.shoreAbsorbDepth;
2465
+ },
2466
+ set (value) {
2467
+ this.shoreAbsorbDepth = value.num[0];
2468
+ }
2469
+ },
2470
+ {
2471
+ name: 'Damping',
2472
+ description: 'Rate the field loses energy at, in 1/s',
2473
+ type: 'float',
2474
+ default: 1,
2475
+ options: {
2476
+ animatable: true,
2477
+ minValue: 0,
2478
+ maxValue: 10
2479
+ },
2480
+ get (value) {
2481
+ value.num[0] = this.damping;
2482
+ },
2483
+ set (value) {
2484
+ this.damping = value.num[0];
2485
+ }
2486
+ },
2487
+ {
2488
+ name: 'MaxAmplitude',
2489
+ description: 'Height in metres the field is clamped to either side of the rest level',
2490
+ type: 'float',
2491
+ default: 0.5,
2492
+ options: {
2493
+ minValue: 0.01,
2494
+ maxValue: 5
2495
+ },
2496
+ get (value) {
2497
+ value.num[0] = this.maxAmplitude;
2498
+ },
2499
+ set (value) {
2500
+ this.maxAmplitude = value.num[0];
2501
+ }
2502
+ },
2503
+ {
2504
+ name: 'SpongeWidth',
2505
+ description: 'Width of the absorbing band inside the window edge, as a fraction of the window',
2506
+ type: 'float',
2507
+ default: 0.1,
2508
+ options: {
2509
+ minValue: 0.01,
2510
+ maxValue: 0.45
2511
+ },
2512
+ get (value) {
2513
+ value.num[0] = this.spongeWidth;
2514
+ },
2515
+ set (value) {
2516
+ this.spongeWidth = value.num[0];
2517
+ }
2518
+ },
2519
+ {
2520
+ name: 'FollowMode',
2521
+ description: 'How the window is positioned: on the water the camera looks at, on a node, or fixed',
2522
+ type: 'string',
2523
+ default: 'camera',
2524
+ options: {
2525
+ enum: {
2526
+ labels: WATER_INTERACTION_FOLLOW_MODES.map((e)=>e.label),
2527
+ values: WATER_INTERACTION_FOLLOW_MODES.map((e)=>e.value)
2528
+ }
2529
+ },
2530
+ get (value) {
2531
+ value.str[0] = this.followMode;
2532
+ },
2533
+ set (value) {
2534
+ this.followMode = value.str[0];
2535
+ }
2536
+ },
2537
+ {
2538
+ name: 'FollowNode',
2539
+ description: 'Node the window follows while FollowMode is Node',
2540
+ type: 'string',
2541
+ default: '',
2542
+ options: {
2543
+ sceneNode: {
2544
+ kind: 'node'
2545
+ }
2546
+ },
2547
+ get (value) {
2548
+ value.str[0] = this.followNode?.persistentId ?? this.followNodeId;
2549
+ },
2550
+ set (value) {
2551
+ this.followNodeId = value.str[0] ?? '';
2552
+ this.followNode = null;
2553
+ }
2554
+ },
2555
+ {
2556
+ name: 'Center',
2557
+ description: 'World XZ the window is centred on while FollowMode is Fixed',
2558
+ type: 'vec2',
2559
+ default: [
2560
+ 0,
2561
+ 0
2562
+ ],
2563
+ get (value) {
2564
+ value.num[0] = this.center.x;
2565
+ value.num[1] = this.center.y;
2566
+ },
2567
+ set (value) {
2568
+ this.center = new Vector2(value.num[0], value.num[1]);
2569
+ }
2570
+ },
2571
+ {
2572
+ name: 'FoamAmount',
2573
+ description: 'Rate foam is made at where the water is churned to the full, in coverage per second; 0 disables the foam',
2574
+ type: 'float',
2575
+ default: 3,
2576
+ options: {
2577
+ animatable: true,
2578
+ minValue: 0,
2579
+ maxValue: 30
2580
+ },
2581
+ get (value) {
2582
+ value.num[0] = this.foamAmount;
2583
+ },
2584
+ set (value) {
2585
+ this.foamAmount = value.num[0];
2586
+ }
2587
+ },
2588
+ {
2589
+ name: 'FoamDecay',
2590
+ description: 'Rate the foam trail fades at, in 1/s',
2591
+ type: 'float',
2592
+ default: 0.6,
2593
+ options: {
2594
+ animatable: true,
2595
+ minValue: 0,
2596
+ maxValue: 5
2597
+ },
2598
+ get (value) {
2599
+ value.num[0] = this.foamDecay;
2600
+ },
2601
+ set (value) {
2602
+ this.foamDecay = value.num[0];
2603
+ }
2604
+ },
2605
+ {
2606
+ name: 'FoamMinSpeed',
2607
+ description: 'Speed of the water in m/s below which it traps no air and makes no foam',
2608
+ type: 'float',
2609
+ default: 0.5,
2610
+ options: {
2611
+ minValue: 0,
2612
+ maxValue: 10
2613
+ },
2614
+ get (value) {
2615
+ value.num[0] = this.foamMinSpeed;
2616
+ },
2617
+ set (value) {
2618
+ this.foamMinSpeed = value.num[0];
2619
+ }
2620
+ },
2621
+ {
2622
+ name: 'FoamMaxSpeed',
2623
+ description: 'Speed of the water in m/s from which it foams to the full',
2624
+ type: 'float',
2625
+ default: 2,
2626
+ options: {
2627
+ minValue: 0,
2628
+ maxValue: 20
2629
+ },
2630
+ get (value) {
2631
+ value.num[0] = this.foamMaxSpeed;
2632
+ },
2633
+ set (value) {
2634
+ this.foamMaxSpeed = value.num[0];
2635
+ }
2636
+ },
2637
+ {
2638
+ name: 'BreakingAcceleration',
2639
+ description: "Downward acceleration of a crest, as a share of gravity, at which it breaks and foams; Longuet-Higgins' limit is 0.5",
2640
+ type: 'float',
2641
+ default: 0.5,
2642
+ options: {
2643
+ minValue: 0.01,
2644
+ maxValue: 4
2645
+ },
2646
+ get (value) {
2647
+ value.num[0] = this.breakingAcceleration;
2648
+ },
2649
+ set (value) {
2650
+ this.breakingAcceleration = value.num[0];
2651
+ }
2652
+ },
2653
+ {
2654
+ name: 'FoamDiffusion',
2655
+ description: 'Turbulent diffusivity the foam spreads by, in square metres per second',
2656
+ type: 'float',
2657
+ default: 0.1,
2658
+ options: {
2659
+ minValue: 0,
2660
+ maxValue: 2
2661
+ },
2662
+ get (value) {
2663
+ value.num[0] = this.foamDiffusion;
2664
+ },
2665
+ set (value) {
2666
+ this.foamDiffusion = value.num[0];
2667
+ }
2668
+ },
2669
+ {
2670
+ name: 'Disturbers',
2671
+ description: 'Things that disturb the water by moving through it, each following a scene node',
2672
+ type: 'object_array',
2673
+ options: {
2674
+ objectTypes: [
2675
+ WaterDisturber
2676
+ ]
2677
+ },
2678
+ get (value) {
2679
+ value.object = [
2680
+ ...this.disturbers
2681
+ ];
2682
+ },
2683
+ set (value) {
2684
+ const next = value.object.filter((d)=>d instanceof WaterDisturber);
2685
+ for (const d of [
2686
+ ...this.disturbers
2687
+ ]){
2688
+ if (!next.includes(d)) {
2689
+ this.removeDisturber(d);
1573
2690
  }
1574
2691
  }
2692
+ for (const d of next){
2693
+ this.addDisturber(d);
2694
+ }
2695
+ },
2696
+ add (value) {
2697
+ const d = value?.object?.[0];
2698
+ this.addDisturber(d instanceof WaterDisturber ? d : new WaterDisturber());
2699
+ },
2700
+ delete (index) {
2701
+ const d = this.disturbers[index];
2702
+ if (d) {
2703
+ this.removeDisturber(d);
2704
+ }
2705
+ }
2706
+ }
2707
+ ]);
2708
+ }
2709
+ };
2710
+ }
2711
+ /** @internal */ function getWaterDisturberClass() {
2712
+ return {
2713
+ ctor: WaterDisturber,
2714
+ name: 'WaterDisturber',
2715
+ getProps () {
2716
+ return defineProps([
2717
+ {
2718
+ name: 'Node',
2719
+ description: 'Scene node the shape follows',
2720
+ type: 'string',
2721
+ default: '',
2722
+ options: {
2723
+ sceneNode: {
2724
+ kind: 'node'
2725
+ }
2726
+ },
2727
+ get (value) {
2728
+ value.str[0] = this.node?.persistentId ?? this.nodeId;
2729
+ },
2730
+ set (value) {
2731
+ this.nodeId = value.str[0] ?? '';
2732
+ this.node = null;
2733
+ }
2734
+ },
2735
+ {
2736
+ name: 'Shape',
2737
+ description: 'Footprint shape: a sphere or a capsule of Radius, or a box of Size',
2738
+ type: 'string',
2739
+ default: 'sphere',
2740
+ options: {
2741
+ enum: {
2742
+ labels: WATER_DISTURBER_SHAPES.map((e)=>e.label),
2743
+ values: WATER_DISTURBER_SHAPES.map((e)=>e.value)
2744
+ }
2745
+ },
2746
+ get (value) {
2747
+ value.str[0] = this.shape;
2748
+ },
2749
+ set (value) {
2750
+ this.shape = value.str[0];
2751
+ }
2752
+ },
2753
+ {
2754
+ name: 'Radius',
2755
+ description: 'Radius in metres, for a sphere or a capsule',
2756
+ type: 'float',
2757
+ default: 0.5,
2758
+ options: {
2759
+ minValue: 0.01,
2760
+ maxValue: 50
2761
+ },
2762
+ get (value) {
2763
+ value.num[0] = this.radius;
2764
+ },
2765
+ set (value) {
2766
+ this.radius = value.num[0];
2767
+ }
2768
+ },
2769
+ {
2770
+ name: 'HalfLength',
2771
+ description: 'Half the segment length in metres, for a capsule, along the local Y axis',
2772
+ type: 'float',
2773
+ default: 0.5,
2774
+ options: {
2775
+ minValue: 0,
2776
+ maxValue: 50
2777
+ },
2778
+ get (value) {
2779
+ value.num[0] = this.halfLength;
2780
+ },
2781
+ set (value) {
2782
+ this.halfLength = value.num[0];
2783
+ }
2784
+ },
2785
+ {
2786
+ name: 'Size',
2787
+ description: 'Extents in metres along the local axes, for a box',
2788
+ type: 'vec3',
2789
+ default: [
2790
+ 1,
2791
+ 1,
2792
+ 1
2793
+ ],
2794
+ get (value) {
2795
+ value.num[0] = this.size.x;
2796
+ value.num[1] = this.size.y;
2797
+ value.num[2] = this.size.z;
2798
+ },
2799
+ set (value) {
2800
+ this.size = new Vector3(value.num[0], value.num[1], value.num[2]);
2801
+ }
2802
+ },
2803
+ {
2804
+ name: 'Strength',
2805
+ description: 'Water column the fully submerged shape displaces, in metres of surface height',
2806
+ type: 'float',
2807
+ default: 0.15,
2808
+ options: {
2809
+ animatable: true,
2810
+ minValue: 0,
2811
+ maxValue: 2
2812
+ },
2813
+ get (value) {
2814
+ value.num[0] = this.strength;
2815
+ },
2816
+ set (value) {
2817
+ this.strength = value.num[0];
2818
+ }
2819
+ },
2820
+ {
2821
+ name: 'Blocking',
2822
+ description: 'Whether waves stop at and reflect off the footprint',
2823
+ type: 'bool',
2824
+ default: false,
2825
+ get (value) {
2826
+ value.bool[0] = this.blocking;
2827
+ },
2828
+ set (value) {
2829
+ this.blocking = value.bool[0];
2830
+ }
2831
+ },
2832
+ {
2833
+ name: 'Floating',
2834
+ description: 'Whether the shape floats, as a boat hull does: it displaces its full strength however it bobs and leaves a wake only by moving',
2835
+ type: 'bool',
2836
+ default: false,
2837
+ get (value) {
2838
+ value.bool[0] = this.floating;
2839
+ },
2840
+ set (value) {
2841
+ this.floating = value.bool[0];
2842
+ }
2843
+ },
2844
+ {
2845
+ name: 'Enabled',
2846
+ description: 'Whether the disturber is taken into account',
2847
+ type: 'bool',
2848
+ default: true,
2849
+ get (value) {
2850
+ value.bool[0] = this.enabled;
2851
+ },
2852
+ set (value) {
2853
+ this.enabled = value.bool[0];
1575
2854
  }
1576
2855
  }
1577
2856
  ]);
@@ -1579,5 +2858,5 @@ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../materi
1579
2858
  };
1580
2859
  }
1581
2860
 
1582
- export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getGerstnerWaveClass, getGerstnerWaveGeneratorClass, getWaterClass };
2861
+ export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getGerstnerWaveClass, getGerstnerWaveGeneratorClass, getWaterClass, getWaterDisturberClass, getWaterInteractionClass };
1583
2862
  //# sourceMappingURL=water.js.map