@zephyr3d/scene 0.9.26 → 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 (506) 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 +146 -30
  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 +300 -56
  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 +177 -3
  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 +178 -200
  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 +30475 -19865
  109. package/dist/index.js +67 -12
  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/hairstrand.js +235 -235
  118. package/dist/material/hairstrand.js.map +1 -1
  119. package/dist/material/lambert.js +4 -1
  120. package/dist/material/lambert.js.map +1 -1
  121. package/dist/material/material.js +362 -300
  122. package/dist/material/material.js.map +1 -1
  123. package/dist/material/meshmaterial.js +118 -45
  124. package/dist/material/meshmaterial.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  126. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  128. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  130. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  132. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  133. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  134. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  135. package/dist/material/mixins/lit.js +223 -83
  136. package/dist/material/mixins/lit.js.map +1 -1
  137. package/dist/material/mixins/pbr/common.js +31 -206
  138. package/dist/material/mixins/pbr/common.js.map +1 -1
  139. package/dist/material/mtoon.js +1 -1
  140. package/dist/material/mtoon.js.map +1 -1
  141. package/dist/material/pbrmr.js +3 -0
  142. package/dist/material/pbrmr.js.map +1 -1
  143. package/dist/material/pbrsg.js +3 -0
  144. package/dist/material/pbrsg.js.map +1 -1
  145. package/dist/material/sdf_debug.js +78 -0
  146. package/dist/material/sdf_debug.js.map +1 -0
  147. package/dist/material/shader/helper.js +733 -190
  148. package/dist/material/shader/helper.js.map +1 -1
  149. package/dist/material/shader/terrain_blend.js +204 -43
  150. package/dist/material/shader/terrain_blend.js.map +1 -1
  151. package/dist/material/skin.js +331 -297
  152. package/dist/material/skin.js.map +1 -1
  153. package/dist/material/skinprofile.js +1058 -0
  154. package/dist/material/skinprofile.js.map +1 -0
  155. package/dist/material/sss.js +353 -0
  156. package/dist/material/sss.js.map +1 -0
  157. package/dist/material/sss_kernel.js +265 -0
  158. package/dist/material/sss_kernel.js.map +1 -0
  159. package/dist/material/sssprofile.js +879 -0
  160. package/dist/material/sssprofile.js.map +1 -0
  161. package/dist/material/subsurfaceprofile.js +4 -8
  162. package/dist/material/subsurfaceprofile.js.map +1 -1
  163. package/dist/material/terrain-cm.js +464 -188
  164. package/dist/material/terrain-cm.js.map +1 -1
  165. package/dist/material/unlit.js +3 -0
  166. package/dist/material/unlit.js.map +1 -1
  167. package/dist/material/water.js +2009 -201
  168. package/dist/material/water.js.map +1 -1
  169. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  172. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  173. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  174. package/dist/physics/character.js +226 -0
  175. package/dist/physics/character.js.map +1 -0
  176. package/dist/physics/collider.js +209 -0
  177. package/dist/physics/collider.js.map +1 -0
  178. package/dist/physics/events.js +79 -0
  179. package/dist/physics/events.js.map +1 -0
  180. package/dist/physics/joint.js +272 -0
  181. package/dist/physics/joint.js.map +1 -0
  182. package/dist/physics/node_physics.js +234 -0
  183. package/dist/physics/node_physics.js.map +1 -0
  184. package/dist/physics/part.js +91 -0
  185. package/dist/physics/part.js.map +1 -0
  186. package/dist/physics/rigid_body.js +379 -0
  187. package/dist/physics/rigid_body.js.map +1 -0
  188. package/dist/physics/vehicle.js +335 -0
  189. package/dist/physics/vehicle.js.map +1 -0
  190. package/dist/physics/world.js +25 -0
  191. package/dist/physics/world.js.map +1 -0
  192. package/dist/posteffect/bloom.js +49 -14
  193. package/dist/posteffect/bloom.js.map +1 -1
  194. package/dist/posteffect/motionblur.js +668 -63
  195. package/dist/posteffect/motionblur.js.map +1 -1
  196. package/dist/posteffect/posteffect.js +12 -1
  197. package/dist/posteffect/posteffect.js.map +1 -1
  198. package/dist/posteffect/postsss.js +572 -0
  199. package/dist/posteffect/postsss.js.map +1 -0
  200. package/dist/posteffect/sao.js +48 -50
  201. package/dist/posteffect/sao.js.map +1 -1
  202. package/dist/posteffect/skinsss.js +605 -355
  203. package/dist/posteffect/skinsss.js.map +1 -1
  204. package/dist/posteffect/ssgi.js +91 -162
  205. package/dist/posteffect/ssgi.js.map +1 -1
  206. package/dist/posteffect/ssr.js +3 -11
  207. package/dist/posteffect/ssr.js.map +1 -1
  208. package/dist/posteffect/sss.js +34 -15
  209. package/dist/posteffect/sss.js.map +1 -1
  210. package/dist/posteffect/taa.js +1 -0
  211. package/dist/posteffect/taa.js.map +1 -1
  212. package/dist/render/abuffer_oit.js +40 -39
  213. package/dist/render/abuffer_oit.js.map +1 -1
  214. package/dist/render/clipmap.js +328 -62
  215. package/dist/render/clipmap.js.map +1 -1
  216. package/dist/render/cluster_light.js +958 -224
  217. package/dist/render/cluster_light.js.map +1 -1
  218. package/dist/render/cull_visitor.js +26 -5
  219. package/dist/render/cull_visitor.js.map +1 -1
  220. package/dist/render/debug_views.js +37 -0
  221. package/dist/render/debug_views.js.map +1 -0
  222. package/dist/render/depthpass.js +5 -1
  223. package/dist/render/depthpass.js.map +1 -1
  224. package/dist/render/drawable_mixin.js +53 -6
  225. package/dist/render/drawable_mixin.js.map +1 -1
  226. package/dist/render/dualdepthpeeling_oit.js +53 -53
  227. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  228. package/dist/render/envlight.js +196 -113
  229. package/dist/render/envlight.js.map +1 -1
  230. package/dist/render/fbm_wavegenerator.js +8 -13
  231. package/dist/render/fbm_wavegenerator.js.map +1 -1
  232. package/dist/render/fft_wavegenerator.js +268 -136
  233. package/dist/render/fft_wavegenerator.js.map +1 -1
  234. package/dist/render/gerstner_wavegenerator.js +113 -28
  235. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  236. package/dist/render/gi/probe_volume.js +1334 -0
  237. package/dist/render/gi/probe_volume.js.map +1 -0
  238. package/dist/render/gi/scene_gi.js +282 -0
  239. package/dist/render/gi/scene_gi.js.map +1 -0
  240. package/dist/render/gi/voxel_atlas.js +198 -0
  241. package/dist/render/gi/voxel_atlas.js.map +1 -0
  242. package/dist/render/gi/voxel_lighting.js +652 -0
  243. package/dist/render/gi/voxel_lighting.js.map +1 -0
  244. package/dist/render/gi/voxel_scene.js +642 -0
  245. package/dist/render/gi/voxel_scene.js.map +1 -0
  246. package/dist/render/gi/voxelize_pass.js +223 -0
  247. package/dist/render/gi/voxelize_pass.js.map +1 -0
  248. package/dist/render/globalbindgroup_allocator.js +3 -2
  249. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  250. package/dist/render/gpu_picking.js +9 -36
  251. package/dist/render/gpu_picking.js.map +1 -1
  252. package/dist/render/hzb.js +80 -22
  253. package/dist/render/hzb.js.map +1 -1
  254. package/dist/render/instance_culling.js +499 -0
  255. package/dist/render/instance_culling.js.map +1 -0
  256. package/dist/render/lightpass.js +23 -9
  257. package/dist/render/lightpass.js.map +1 -1
  258. package/dist/render/lod.js +46 -0
  259. package/dist/render/lod.js.map +1 -0
  260. package/dist/render/oit.js +11 -11
  261. package/dist/render/oit.js.map +1 -1
  262. package/dist/render/primitive.js +301 -9
  263. package/dist/render/primitive.js.map +1 -1
  264. package/dist/render/primitive_readback.js +209 -0
  265. package/dist/render/primitive_readback.js.map +1 -0
  266. package/dist/render/render_queue.js +198 -11
  267. package/dist/render/render_queue.js.map +1 -1
  268. package/dist/render/renderer.js +14 -7
  269. package/dist/render/renderer.js.map +1 -1
  270. package/dist/render/rendergraph/blackboard.js +15 -1
  271. package/dist/render/rendergraph/blackboard.js.map +1 -1
  272. package/dist/render/rendergraph/executor.js +136 -0
  273. package/dist/render/rendergraph/executor.js.map +1 -1
  274. package/dist/render/rendergraph/forward_plus_builder.js +585 -59
  275. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  276. package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
  277. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
  278. package/dist/render/rendergraph/history_resources.js +8 -1
  279. package/dist/render/rendergraph/history_resources.js.map +1 -1
  280. package/dist/render/rendergraph/scene_render_context.js +31 -2
  281. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  282. package/dist/render/rendergraph/types.js.map +1 -1
  283. package/dist/render/renderpass.js +28 -5
  284. package/dist/render/renderpass.js.map +1 -1
  285. package/dist/render/sdf/box_allocator.js +98 -0
  286. package/dist/render/sdf/box_allocator.js.map +1 -0
  287. package/dist/render/sdf/global_sdf.js +865 -0
  288. package/dist/render/sdf/global_sdf.js.map +1 -0
  289. package/dist/render/sdf/scene_sdf.js +562 -0
  290. package/dist/render/sdf/scene_sdf.js.map +1 -0
  291. package/dist/render/sdf/sdf_atlas.js +227 -0
  292. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  293. package/dist/render/sdf/sdf_programs.js +42 -0
  294. package/dist/render/sdf/sdf_programs.js.map +1 -0
  295. package/dist/render/sdf/sdf_view.js +199 -0
  296. package/dist/render/sdf/sdf_view.js.map +1 -0
  297. package/dist/render/sdf/waterline.js +610 -0
  298. package/dist/render/sdf/waterline.js.map +1 -0
  299. package/dist/render/shadow_mask_pass.js +142 -25
  300. package/dist/render/shadow_mask_pass.js.map +1 -1
  301. package/dist/render/shore_wave_generator.js +1193 -0
  302. package/dist/render/shore_wave_generator.js.map +1 -0
  303. package/dist/render/sky.js +516 -86
  304. package/dist/render/sky.js.map +1 -1
  305. package/dist/render/transmission_thickness_pass.js +477 -0
  306. package/dist/render/transmission_thickness_pass.js.map +1 -0
  307. package/dist/render/underwater.js +524 -0
  308. package/dist/render/underwater.js.map +1 -0
  309. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  310. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  311. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  312. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  313. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  314. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  315. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  316. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  317. package/dist/render/volumetric_cloud/resources.js +380 -0
  318. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  319. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  320. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  321. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  322. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  323. package/dist/render/water_caustics.js +1195 -0
  324. package/dist/render/water_caustics.js.map +1 -0
  325. package/dist/render/water_foam.js +627 -0
  326. package/dist/render/water_foam.js.map +1 -0
  327. package/dist/render/water_interaction.js +1795 -0
  328. package/dist/render/water_interaction.js.map +1 -0
  329. package/dist/render/weightedblended_oit.js +36 -36
  330. package/dist/render/weightedblended_oit.js.map +1 -1
  331. package/dist/scene/basesprite.js +9 -4
  332. package/dist/scene/basesprite.js.map +1 -1
  333. package/dist/scene/batchgroup.js +108 -12
  334. package/dist/scene/batchgroup.js.map +1 -1
  335. package/dist/scene/environment.js +28 -7
  336. package/dist/scene/environment.js.map +1 -1
  337. package/dist/scene/foliage.js +1020 -0
  338. package/dist/scene/foliage.js.map +1 -0
  339. package/dist/scene/foliage_buckets.js +147 -0
  340. package/dist/scene/foliage_buckets.js.map +1 -0
  341. package/dist/scene/foliage_mask.js +358 -0
  342. package/dist/scene/foliage_mask.js.map +1 -0
  343. package/dist/scene/hair.js +15 -4
  344. package/dist/scene/hair.js.map +1 -1
  345. package/dist/scene/light.js +179 -13
  346. package/dist/scene/light.js.map +1 -1
  347. package/dist/scene/mesh.js +327 -45
  348. package/dist/scene/mesh.js.map +1 -1
  349. package/dist/scene/meshdrawable.js +6 -0
  350. package/dist/scene/meshdrawable.js.map +1 -1
  351. package/dist/scene/msdftext.js +9 -3
  352. package/dist/scene/msdftext.js.map +1 -1
  353. package/dist/scene/msdftextsprite.js +9 -3
  354. package/dist/scene/msdftextsprite.js.map +1 -1
  355. package/dist/scene/particlesys.js +8 -2
  356. package/dist/scene/particlesys.js.map +1 -1
  357. package/dist/scene/physics_settings.js +157 -0
  358. package/dist/scene/physics_settings.js.map +1 -0
  359. package/dist/scene/scene.js +190 -44
  360. package/dist/scene/scene.js.map +1 -1
  361. package/dist/scene/scene_node.js +147 -6
  362. package/dist/scene/scene_node.js.map +1 -1
  363. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  364. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  365. package/dist/scene/terrain-cm/grass.js +881 -42
  366. package/dist/scene/terrain-cm/grass.js.map +1 -1
  367. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  368. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  369. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  370. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  371. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  372. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  373. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  374. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  375. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  376. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  377. package/dist/scene/update_queue.js +54 -0
  378. package/dist/scene/update_queue.js.map +1 -0
  379. package/dist/scene/water.js +997 -96
  380. package/dist/scene/water.js.map +1 -1
  381. package/dist/scene/water_surface_sampler.js +324 -0
  382. package/dist/scene/water_surface_sampler.js.map +1 -0
  383. package/dist/scene/wind.js +317 -0
  384. package/dist/scene/wind.js.map +1 -0
  385. package/dist/shaders/atmosphere.js +388 -166
  386. package/dist/shaders/atmosphere.js.map +1 -1
  387. package/dist/shaders/fog.js +100 -32
  388. package/dist/shaders/fog.js.map +1 -1
  389. package/dist/shaders/gi.js +365 -0
  390. package/dist/shaders/gi.js.map +1 -0
  391. package/dist/shaders/ltc_rect.js +202 -0
  392. package/dist/shaders/ltc_rect.js.map +1 -0
  393. package/dist/shaders/misc.js +1 -10
  394. package/dist/shaders/misc.js.map +1 -1
  395. package/dist/shaders/noise.js +5 -1
  396. package/dist/shaders/noise.js.map +1 -1
  397. package/dist/shaders/probes.js +309 -0
  398. package/dist/shaders/probes.js.map +1 -0
  399. package/dist/shaders/sdf.js +537 -0
  400. package/dist/shaders/sdf.js.map +1 -0
  401. package/dist/shaders/shadow.js +104 -70
  402. package/dist/shaders/shadow.js.map +1 -1
  403. package/dist/shaders/skin_brdf.js +243 -0
  404. package/dist/shaders/skin_brdf.js.map +1 -0
  405. package/dist/shaders/ssr.js +6 -159
  406. package/dist/shaders/ssr.js.map +1 -1
  407. package/dist/shaders/temporal.js +38 -27
  408. package/dist/shaders/temporal.js.map +1 -1
  409. package/dist/shaders/water.js +40 -87
  410. package/dist/shaders/water.js.map +1 -1
  411. package/dist/shaders/water_medium.js +42 -0
  412. package/dist/shaders/water_medium.js.map +1 -0
  413. package/dist/shadow/dom.js +110 -19
  414. package/dist/shadow/dom.js.map +1 -1
  415. package/dist/shadow/esm.js +3 -3
  416. package/dist/shadow/esm.js.map +1 -1
  417. package/dist/shadow/pcf_opt.js +15 -48
  418. package/dist/shadow/pcf_opt.js.map +1 -1
  419. package/dist/shadow/pcf_pd.js +15 -53
  420. package/dist/shadow/pcf_pd.js.map +1 -1
  421. package/dist/shadow/pcss.js +34 -9
  422. package/dist/shadow/pcss.js.map +1 -1
  423. package/dist/shadow/shadow_impl.js +3 -8
  424. package/dist/shadow/shadow_impl.js.map +1 -1
  425. package/dist/shadow/shadow_region.js +87 -49
  426. package/dist/shadow/shadow_region.js.map +1 -1
  427. package/dist/shadow/shadowmapper.js +93 -53
  428. package/dist/shadow/shadowmapper.js.map +1 -1
  429. package/dist/shadow/ssm.js +18 -72
  430. package/dist/shadow/ssm.js.map +1 -1
  431. package/dist/shadow/vsm.js +3 -3
  432. package/dist/shadow/vsm.js.map +1 -1
  433. package/dist/shapes/shape.js +44 -1
  434. package/dist/shapes/shape.js.map +1 -1
  435. package/dist/utility/buoyancy.js +287 -0
  436. package/dist/utility/buoyancy.js.map +1 -0
  437. package/dist/utility/physical.js +10 -1
  438. package/dist/utility/physical.js.map +1 -1
  439. package/dist/utility/pmrem.js +17 -43
  440. package/dist/utility/pmrem.js.map +1 -1
  441. package/dist/utility/sdf/bake.js +435 -0
  442. package/dist/utility/sdf/bake.js.map +1 -0
  443. package/dist/utility/sdf/bvh.js +576 -0
  444. package/dist/utility/sdf/bvh.js.map +1 -0
  445. package/dist/utility/serialization/manager.js +36 -6
  446. package/dist/utility/serialization/manager.js.map +1 -1
  447. package/dist/utility/serialization/scene/animation.js +77 -7
  448. package/dist/utility/serialization/scene/animation.js.map +1 -1
  449. package/dist/utility/serialization/scene/batch.js +11 -4
  450. package/dist/utility/serialization/scene/batch.js.map +1 -1
  451. package/dist/utility/serialization/scene/camera.js +140 -279
  452. package/dist/utility/serialization/scene/camera.js.map +1 -1
  453. package/dist/utility/serialization/scene/cloth.js +25 -0
  454. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  455. package/dist/utility/serialization/scene/common.js +14 -6
  456. package/dist/utility/serialization/scene/common.js.map +1 -1
  457. package/dist/utility/serialization/scene/foliage.js +821 -0
  458. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  459. package/dist/utility/serialization/scene/hair.js +11 -4
  460. package/dist/utility/serialization/scene/hair.js.map +1 -1
  461. package/dist/utility/serialization/scene/light.js +115 -7
  462. package/dist/utility/serialization/scene/light.js.map +1 -1
  463. package/dist/utility/serialization/scene/material.js +388 -220
  464. package/dist/utility/serialization/scene/material.js.map +1 -1
  465. package/dist/utility/serialization/scene/mesh.js +69 -4
  466. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  467. package/dist/utility/serialization/scene/node.js +140 -5
  468. package/dist/utility/serialization/scene/node.js.map +1 -1
  469. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  470. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  471. package/dist/utility/serialization/scene/particle.js +11 -4
  472. package/dist/utility/serialization/scene/particle.js.map +1 -1
  473. package/dist/utility/serialization/scene/physics.js +120 -0
  474. package/dist/utility/serialization/scene/physics.js.map +1 -0
  475. package/dist/utility/serialization/scene/primitive.js +124 -10
  476. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  477. package/dist/utility/serialization/scene/scene.js +1687 -51
  478. package/dist/utility/serialization/scene/scene.js.map +1 -1
  479. package/dist/utility/serialization/scene/sprite.js +11 -4
  480. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  481. package/dist/utility/serialization/scene/terrain.js +163 -33
  482. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  483. package/dist/utility/serialization/scene/text.js +11 -4
  484. package/dist/utility/serialization/scene/text.js.map +1 -1
  485. package/dist/utility/serialization/scene/water.js +2473 -114
  486. package/dist/utility/serialization/scene/water.js.map +1 -1
  487. package/dist/utility/serialization/types.js.map +1 -1
  488. package/dist/utility/shprojector.js +97 -109
  489. package/dist/utility/shprojector.js.map +1 -1
  490. package/dist/utility/textures/foam.js +170 -0
  491. package/dist/utility/textures/foam.js.map +1 -0
  492. package/dist/utility/textures/ggxlut.js +17 -43
  493. package/dist/utility/textures/ggxlut.js.map +1 -1
  494. package/dist/utility/textures/ltcdata.js +4 -4
  495. package/dist/utility/textures/ltcdata.js.map +1 -1
  496. package/dist/utility/textures/ltclut.js +16 -6
  497. package/dist/utility/textures/ltclut.js.map +1 -1
  498. package/dist/utility/unsupported.js +24 -0
  499. package/dist/utility/unsupported.js.map +1 -0
  500. package/dist/values.js +13 -1
  501. package/dist/values.js.map +1 -1
  502. package/package.json +25 -12
  503. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  504. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  505. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  506. package/src/asset/meshoptimizer/LICENSE +21 -0
@@ -1,18 +1,19 @@
1
- import { Vector2 } from '@zephyr3d/base';
1
+ import { Vector2, Vector3 } from '@zephyr3d/base';
2
2
  import '../../../scene/scene.js';
3
- import '../../../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,10 +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';
37
+ import { GerstnerWaveGenerator } from '../../../render/gerstner_wavegenerator.js';
35
38
  import { FBMWaveGenerator } from '../../../render/fbm_wavegenerator.js';
39
+ import { WaterInteraction, WaterDisturber } from '../../../render/water_interaction.js';
36
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';
37
44
  import { GraphNode } from '../../../scene/graph_node.js';
38
45
  import '../../../shadow/shadowmapper.js';
39
46
  import '../../../scene/mesh.js';
@@ -48,6 +55,8 @@ import '../../../scene/batchgroup.js';
48
55
  import '../../../scene/terrain-cm/terrain-cm.js';
49
56
  import '../../../scene/terrain-cm/grass.js';
50
57
  import '../../../scene/raycast_visitor.js';
58
+ import '../../../scene/foliage.js';
59
+ import { WATER_DEBUG_OUTPUTS, DEFAULT_SCATTER_ANISOTROPY } from '../../../material/water.js';
51
60
 
52
61
  /** @internal */ function getFBMWaveGeneratorClass() {
53
62
  return {
@@ -199,31 +208,6 @@ import '../../../scene/raycast_visitor.js';
199
208
  this.foamContrast = value.num[0];
200
209
  }
201
210
  },
202
- {
203
- name: 'WaveLengthCascades',
204
- description: 'Wavelength values for the three FFT wave cascades',
205
- type: 'vec3',
206
- default: [
207
- 400,
208
- 100,
209
- 15
210
- ],
211
- options: {
212
- animatable: true,
213
- minValue: 0,
214
- maxValue: 1000
215
- },
216
- get (value) {
217
- value.num[0] = this.getWaveLength(0);
218
- value.num[1] = this.getWaveLength(1);
219
- value.num[2] = this.getWaveLength(2);
220
- },
221
- set (value) {
222
- this.setWaveLength(0, value.num[0]);
223
- this.setWaveLength(1, value.num[1]);
224
- this.setWaveLength(2, value.num[2]);
225
- }
226
- },
227
211
  {
228
212
  name: 'WaveStrengthCascades',
229
213
  description: 'Strength values for the three FFT wave cascades',
@@ -231,7 +215,7 @@ import '../../../scene/raycast_visitor.js';
231
215
  default: [
232
216
  0.4,
233
217
  0.4,
234
- 0.2
218
+ 0.4
235
219
  ],
236
220
  options: {
237
221
  animatable: true,
@@ -278,6 +262,716 @@ import '../../../scene/raycast_visitor.js';
278
262
  }
279
263
  };
280
264
  }
265
+ /** @internal */ function getGerstnerWaveGeneratorClass() {
266
+ return {
267
+ ctor: GerstnerWaveGenerator,
268
+ name: 'GerstnerWaveGenerator',
269
+ getProps () {
270
+ return defineProps([
271
+ {
272
+ name: 'NumWaves',
273
+ description: 'Number of independent Gerstner waves summed to form the surface',
274
+ type: 'int',
275
+ options: {
276
+ minValue: 1,
277
+ maxValue: MAX_GERSTNER_WAVE_COUNT
278
+ },
279
+ get (value) {
280
+ value.num[0] = this.numWaves;
281
+ },
282
+ set (value) {
283
+ this.numWaves = value.num[0];
284
+ }
285
+ },
286
+ {
287
+ name: 'Waves',
288
+ description: 'Per-wave parameters, one entry per wave in NumWaves order',
289
+ type: 'object_array',
290
+ options: {
291
+ objectTypes: [
292
+ GerstnerWave
293
+ ]
294
+ },
295
+ get (value) {
296
+ value.object = [];
297
+ for(let i = 0; i < this.numWaves; i++){
298
+ const wave = new GerstnerWave();
299
+ wave.bind(this, i);
300
+ value.object.push(wave);
301
+ }
302
+ },
303
+ set (value) {
304
+ const waves = value.object;
305
+ // The wave count is ground truth for how many slots the shader
306
+ // reads. NumWaves and Waves are applied concurrently during
307
+ // deserialization, so this setter must leave the generator in the
308
+ // state this array implies regardless of which one runs first.
309
+ this.numWaves = waves.length;
310
+ for(let i = 0; i < waves.length; i++){
311
+ waves[i].applyTo(this, i);
312
+ }
313
+ },
314
+ add (value, index) {
315
+ const wave = value?.object?.[0];
316
+ const insertAt = index ?? this.numWaves;
317
+ this.insertWave(insertAt);
318
+ wave?.applyTo(this, insertAt);
319
+ },
320
+ delete (index) {
321
+ this.deleteWave(index);
322
+ }
323
+ },
324
+ {
325
+ name: 'FoamWidth',
326
+ description: 'Width of foam bands generated on the wave crests',
327
+ type: 'float',
328
+ default: 1.2,
329
+ options: {
330
+ animatable: true,
331
+ minValue: 0,
332
+ maxValue: 10
333
+ },
334
+ get (value) {
335
+ value.num[0] = this.foamWidth;
336
+ },
337
+ set (value) {
338
+ this.foamWidth = value.num[0];
339
+ }
340
+ },
341
+ {
342
+ name: 'FoamContrast',
343
+ description: 'Contrast of the foam pattern on Gerstner waves',
344
+ type: 'float',
345
+ default: 7.2,
346
+ options: {
347
+ animatable: true,
348
+ minValue: 0,
349
+ maxValue: 10
350
+ },
351
+ get (value) {
352
+ value.num[0] = this.foamContrast;
353
+ },
354
+ set (value) {
355
+ this.foamContrast = value.num[0];
356
+ }
357
+ }
358
+ ]);
359
+ }
360
+ };
361
+ }
362
+ /**
363
+ * A single Gerstner wave, as the editor sees one entry of the
364
+ * `Waves` object array on a {@link GerstnerWaveGenerator}.
365
+ *
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.
368
+ *
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.
372
+ */ class GerstnerWave {
373
+ _owner;
374
+ _index;
375
+ _direction;
376
+ _steepness;
377
+ _amplitude;
378
+ _length;
379
+ _omni;
380
+ _originX;
381
+ _originZ;
382
+ constructor(){
383
+ this._owner = null;
384
+ this._index = -1;
385
+ this._direction = 0;
386
+ this._steepness = 0;
387
+ this._amplitude = 0;
388
+ this._length = 1;
389
+ this._omni = false;
390
+ this._originX = 0;
391
+ this._originZ = 0;
392
+ }
393
+ /**
394
+ * Binds this entry to a slot of `owner`, so the field setters write through
395
+ * to the generator. Called by the `Waves` getter and by `add`; the index is
396
+ * the slot the entry currently represents.
397
+ * @internal
398
+ */ bind(owner, index) {
399
+ this._owner = owner;
400
+ this._index = index;
401
+ this.loadFromOwner(owner, index);
402
+ }
403
+ /**
404
+ * Copies the values in slot `index` of `owner` into this object, refreshing
405
+ * the cached fields without writing back.
406
+ * @internal
407
+ */ loadFromOwner(owner, index) {
408
+ this._direction = owner.getWaveDirection(index);
409
+ this._steepness = owner.getWaveSteepness(index);
410
+ this._amplitude = owner.getWaveAmplitude(index);
411
+ this._length = owner.getWaveLength(index);
412
+ this._omni = owner.isOmniWave(index);
413
+ this._originX = owner.getOriginX(index);
414
+ this._originZ = owner.getOriginZ(index);
415
+ }
416
+ /**
417
+ * Writes this object's values into slot `index` of `owner`, unconditionally.
418
+ *
419
+ * Used by the `Waves` setter for a deserialized array, whose entries have no
420
+ * owner, and by `add` for a freshly created one.
421
+ * @internal
422
+ */ applyTo(owner, index) {
423
+ owner.setWaveDirection(index, this._direction);
424
+ owner.setWaveSteepness(index, this._steepness);
425
+ owner.setWaveAmplitude(index, this._amplitude);
426
+ owner.setWaveLength(index, this._length);
427
+ owner.setOmniWave(index, this._omni);
428
+ owner.setOrigin(index, this._originX, this._originZ);
429
+ this._owner = owner;
430
+ this._index = index;
431
+ }
432
+ /** @internal */ writethrough(setter, val) {
433
+ const owner = this._owner;
434
+ if (owner) {
435
+ setter(owner, this._index, val);
436
+ }
437
+ }
438
+ /** Gets the wave direction angle in radians. */ get direction() {
439
+ return this._direction;
440
+ }
441
+ set direction(val) {
442
+ this._direction = val;
443
+ this.writethrough((o, i, v)=>o.setWaveDirection(i, v), val);
444
+ }
445
+ /** Gets the wave steepness. */ get steepness() {
446
+ return this._steepness;
447
+ }
448
+ set steepness(val) {
449
+ this._steepness = val;
450
+ this.writethrough((o, i, v)=>o.setWaveSteepness(i, v), val);
451
+ }
452
+ /** Gets the wave amplitude. */ get amplitude() {
453
+ return this._amplitude;
454
+ }
455
+ set amplitude(val) {
456
+ this._amplitude = val;
457
+ this.writethrough((o, i, v)=>o.setWaveAmplitude(i, v), val);
458
+ }
459
+ /** Gets the wave length in meters. */ get length() {
460
+ return this._length;
461
+ }
462
+ set length(val) {
463
+ this._length = val;
464
+ this.writethrough((o, i, v)=>o.setWaveLength(i, v), val);
465
+ }
466
+ /** Gets whether the wave is omni-directional. */ get omni() {
467
+ return this._omni;
468
+ }
469
+ set omni(val) {
470
+ this._omni = val;
471
+ if (this._owner) {
472
+ this._owner.setOmniWave(this._index, val);
473
+ }
474
+ }
475
+ /** Gets the origin X of an omni-directional wave. */ get originX() {
476
+ return this._originX;
477
+ }
478
+ set originX(val) {
479
+ this._originX = val;
480
+ if (this._owner) {
481
+ this._owner.setOrigin(this._index, val, this._originZ);
482
+ }
483
+ }
484
+ /** Gets the origin Z of an omni-directional wave. */ get originZ() {
485
+ return this._originZ;
486
+ }
487
+ set originZ(val) {
488
+ this._originZ = val;
489
+ if (this._owner) {
490
+ this._owner.setOrigin(this._index, this._originX, val);
491
+ }
492
+ }
493
+ }
494
+ /** @internal */ function getGerstnerWaveClass() {
495
+ return {
496
+ ctor: GerstnerWave,
497
+ name: 'GerstnerWave',
498
+ getProps () {
499
+ return defineProps([
500
+ {
501
+ name: 'Direction',
502
+ description: 'Wave direction angle in radians',
503
+ type: 'float',
504
+ options: {
505
+ animatable: true,
506
+ minValue: -3.14,
507
+ maxValue: 3.14
508
+ },
509
+ get (value) {
510
+ value.num[0] = this.direction;
511
+ },
512
+ set (value) {
513
+ this.direction = value.num[0];
514
+ }
515
+ },
516
+ {
517
+ name: 'Steepness',
518
+ description: 'Wave steepness. The sum of steepness across waves sets how sharply crests fold',
519
+ type: 'float',
520
+ options: {
521
+ animatable: true,
522
+ minValue: 0,
523
+ maxValue: 2
524
+ },
525
+ get (value) {
526
+ value.num[0] = this.steepness;
527
+ },
528
+ set (value) {
529
+ this.steepness = value.num[0];
530
+ }
531
+ },
532
+ {
533
+ name: 'Amplitude',
534
+ description: 'Wave height amplitude',
535
+ type: 'float',
536
+ options: {
537
+ animatable: true,
538
+ minValue: 0,
539
+ maxValue: 5
540
+ },
541
+ get (value) {
542
+ value.num[0] = this.amplitude;
543
+ },
544
+ set (value) {
545
+ this.amplitude = value.num[0];
546
+ }
547
+ },
548
+ {
549
+ name: 'Length',
550
+ description: 'Wave length in meters',
551
+ type: 'float',
552
+ options: {
553
+ animatable: true,
554
+ minValue: 0,
555
+ maxValue: 100
556
+ },
557
+ get (value) {
558
+ value.num[0] = this.length;
559
+ },
560
+ set (value) {
561
+ this.length = value.num[0];
562
+ }
563
+ },
564
+ {
565
+ name: 'Omni',
566
+ description: 'If true, radiates outward from an origin rather than travelling in one direction',
567
+ type: 'bool',
568
+ get (value) {
569
+ value.bool[0] = this.omni;
570
+ },
571
+ set (value) {
572
+ this.omni = value.bool[0];
573
+ }
574
+ },
575
+ {
576
+ name: 'Origin',
577
+ description: 'Origin of an omni-directional wave, ignored by directional waves',
578
+ type: 'vec2',
579
+ options: {
580
+ animatable: true,
581
+ minValue: -1e3,
582
+ maxValue: 1000
583
+ },
584
+ get (value) {
585
+ value.num[0] = this.originX;
586
+ value.num[1] = this.originZ;
587
+ },
588
+ set (value) {
589
+ this.originX = value.num[0];
590
+ this.originZ = value.num[1];
591
+ }
592
+ }
593
+ ]);
594
+ }
595
+ };
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
+ }
281
975
  /** @internal */ function getWaterClass(manager) {
282
976
  return {
283
977
  ctor: Water,
@@ -291,7 +985,7 @@ import '../../../scene/raycast_visitor.js';
291
985
  };
292
986
  },
293
987
  getProps () {
294
- return defineProps([
988
+ return layoutWaterProps(defineProps([
295
989
  {
296
990
  name: 'WaveGenerator',
297
991
  description: 'Wave generator used to drive the water surface',
@@ -300,7 +994,8 @@ import '../../../scene/raycast_visitor.js';
300
994
  options: {
301
995
  objectTypes: [
302
996
  FFTWaveGenerator,
303
- FBMWaveGenerator
997
+ FBMWaveGenerator,
998
+ GerstnerWaveGenerator
304
999
  ]
305
1000
  },
306
1001
  isNullable () {
@@ -317,6 +1012,26 @@ import '../../../scene/raycast_visitor.js';
317
1012
  }
318
1013
  }
319
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
+ },
320
1035
  {
321
1036
  name: 'GridScale',
322
1037
  description: 'Scale of the water simulation grid',
@@ -363,135 +1078,1779 @@ import '../../../scene/raycast_visitor.js';
363
1078
  }
364
1079
  },
365
1080
  {
366
- name: 'DepthScale',
367
- description: 'Depth attenuation scale for the water material',
1081
+ name: 'Infinite',
1082
+ description: 'Draw the surface as an unbounded ocean reaching the horizon instead of a body of water ending at the node extent. Reaches the horizon without enlarging the camera far plane, so near-scene depth precision is unaffected. Leave off for ponds, lakes and pools, which have an edge.',
1083
+ type: 'bool',
1084
+ default: false,
1085
+ get (value) {
1086
+ value.bool[0] = this.infinite;
1087
+ },
1088
+ set (value) {
1089
+ this.infinite = value.bool[0];
1090
+ }
1091
+ },
1092
+ {
1093
+ name: 'ViewDistance',
1094
+ description: 'How far the surface is built out from the camera, in meters, or 0 to derive it from the true horizon distance for the camera height. Keep the sky AerialPerspectiveDistance at least this large, or the far water stops converging towards the sky colour and the hard band comes back.',
368
1095
  type: 'float',
369
- default: 10,
1096
+ default: 0,
370
1097
  options: {
371
- animatable: true,
372
1098
  minValue: 0,
373
- maxValue: 100
1099
+ maxValue: 100000
1100
+ },
1101
+ isHidden () {
1102
+ return !this.infinite;
374
1103
  },
375
1104
  get (value) {
376
- value.num[0] = this.material.depthMulti;
1105
+ value.num[0] = this.viewDistance;
377
1106
  },
378
1107
  set (value) {
379
- this.material.depthMulti = value.num[0];
1108
+ this.viewDistance = value.num[0];
380
1109
  }
381
1110
  },
382
1111
  {
383
- name: 'RefractionStrength',
384
- description: 'Strength of underwater refraction',
1112
+ name: 'CausticsEnabled',
1113
+ description: 'Whether the water projects caustics onto the geometry below it',
1114
+ type: 'bool',
1115
+ default: true,
1116
+ get (value) {
1117
+ value.bool[0] = this.causticsEnabled;
1118
+ },
1119
+ set (value) {
1120
+ this.causticsEnabled = value.bool[0];
1121
+ }
1122
+ },
1123
+ {
1124
+ name: 'CausticsIntensity',
1125
+ description: 'Strength of the caustic contrast',
385
1126
  type: 'float',
386
- default: 0,
1127
+ default: 1,
387
1128
  options: {
388
1129
  animatable: true,
389
1130
  minValue: 0,
390
- maxValue: 1
1131
+ maxValue: 5
1132
+ },
1133
+ isHidden () {
1134
+ return !this.causticsEnabled;
1135
+ },
1136
+ get (value) {
1137
+ value.num[0] = this.causticsIntensity;
1138
+ },
1139
+ set (value) {
1140
+ this.causticsIntensity = value.num[0];
1141
+ }
1142
+ },
1143
+ {
1144
+ name: 'CausticsDepth',
1145
+ description: 'Depth in meters below the surface where the caustics are in focus',
1146
+ type: 'float',
1147
+ default: 4,
1148
+ options: {
1149
+ animatable: true,
1150
+ minValue: 0.01,
1151
+ maxValue: 100
1152
+ },
1153
+ isHidden () {
1154
+ return !this.causticsEnabled;
391
1155
  },
392
1156
  get (value) {
393
- value.num[0] = this.material.refractionStrength;
1157
+ value.num[0] = this.causticsDepth;
394
1158
  },
395
1159
  set (value) {
396
- this.material.refractionStrength = value.num[0];
1160
+ this.causticsDepth = value.num[0];
397
1161
  }
398
1162
  },
399
1163
  {
400
- name: 'Displace',
401
- description: 'Vertex displacement scale for water waves',
1164
+ name: 'CausticsRange',
1165
+ description: 'Furthest distance in meters from the camera the caustic map reaches',
402
1166
  type: 'float',
403
- default: 16,
1167
+ default: 4,
404
1168
  options: {
405
1169
  minValue: 1,
406
- maxValue: 256
1170
+ maxValue: 1000
1171
+ },
1172
+ isHidden () {
1173
+ return !this.causticsEnabled;
407
1174
  },
408
1175
  get (value) {
409
- value.num[0] = this.material.displace;
1176
+ value.num[0] = this.causticsRange;
410
1177
  },
411
1178
  set (value) {
412
- this.material.displace = value.num[0];
1179
+ this.causticsRange = value.num[0];
413
1180
  }
414
1181
  },
415
1182
  {
416
- name: 'TAAStrength',
417
- description: 'Temporal anti-aliasing strength for the water surface',
1183
+ name: 'CausticsFadeDistance',
1184
+ description: 'Width in meters the caustics fade out over at the edge of the map, or 0 to derive it from the range',
418
1185
  type: 'float',
419
- default: 0.4,
1186
+ default: 0,
420
1187
  options: {
421
1188
  minValue: 0,
422
- maxValue: 1
1189
+ maxValue: 100
1190
+ },
1191
+ isHidden () {
1192
+ return !this.causticsEnabled;
423
1193
  },
424
1194
  get (value) {
425
- value.num[0] = this.TAAStrength;
1195
+ value.num[0] = this.causticsFadeDistance;
426
1196
  },
427
1197
  set (value) {
428
- this.TAAStrength = value.num[0];
1198
+ this.causticsFadeDistance = value.num[0];
429
1199
  }
430
1200
  },
431
1201
  {
432
- name: 'ScatterRampTexture',
433
- description: 'Ramp texture used for water scatter lighting',
434
- type: 'object',
435
- default: null,
436
- isNullable () {
437
- return true;
438
- },
1202
+ name: 'CausticsSceneDepth',
1203
+ description: 'Land caustics on the scene instead of on a plane at CausticsDepth. Reuses the sun shadow cascade, so it costs no extra geometry pass; WebGL2 keeps the plane, which its shadow map format cannot avoid.',
1204
+ type: 'bool',
1205
+ default: true,
439
1206
  get (value) {
440
- value.str[0] = manager.getAssetId(this.material.scatterRampTexture) ?? '';
1207
+ value.bool[0] = this.causticsSceneDepth;
441
1208
  },
442
- async set (value) {
443
- if (!value) {
444
- this.material.scatterRampTexture = null;
445
- } else {
446
- if (value.str[0]) {
447
- const assetId = value.str[0];
448
- let tex;
449
- try {
450
- tex = await manager.fetchTexture(assetId);
451
- } catch (err) {
452
- console.error(`Load asset failed: ${value.str[0]}: ${err}`);
453
- tex = null;
454
- }
455
- if (tex?.isTexture2D()) {
456
- this.material.scatterRampTexture = tex;
457
- } else {
458
- console.error('Invalid texture type');
459
- }
460
- }
461
- }
1209
+ set (value) {
1210
+ this.causticsSceneDepth = value.bool[0];
462
1211
  }
463
1212
  },
464
1213
  {
465
- name: 'AbsorptionRampTexture',
466
- description: 'Ramp texture used for water absorption',
467
- type: 'object',
468
- default: null,
469
- isNullable () {
470
- return true;
1214
+ name: 'CausticsWarp',
1215
+ description: 'How strongly caustic map texels are concentrated near the camera; ignored while the map already fits the water within range',
1216
+ type: 'float',
1217
+ default: 1.5,
1218
+ options: {
1219
+ minValue: 0,
1220
+ maxValue: 8
1221
+ },
1222
+ isHidden () {
1223
+ return !this.causticsEnabled;
471
1224
  },
472
1225
  get (value) {
473
- value.str[0] = manager.getAssetId(this.material.absorptionRampTexture) ?? '';
1226
+ value.num[0] = this.causticsWarp;
474
1227
  },
475
- async set (value) {
476
- if (!value) {
477
- this.material.absorptionRampTexture = null;
478
- } else {
479
- if (value.str[0]) {
480
- const assetId = value.str[0];
481
- let tex;
482
- try {
483
- tex = await manager.fetchTexture(assetId);
484
- } catch (err) {
485
- console.error(`Load asset failed: ${value.str[0]}: ${err}`);
486
- tex = null;
487
- }
488
- if (tex?.isTexture2D()) {
489
- this.material.absorptionRampTexture = tex;
490
- } else {
491
- console.error('Invalid texture type');
492
- }
493
- }
494
- }
1228
+ set (value) {
1229
+ this.causticsWarp = value.num[0];
1230
+ }
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
+ },
1252
+ {
1253
+ name: 'UnderwaterEnabled',
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.',
1255
+ type: 'bool',
1256
+ default: true,
1257
+ get (value) {
1258
+ value.bool[0] = this.underwaterEnabled;
1259
+ },
1260
+ set (value) {
1261
+ this.underwaterEnabled = value.bool[0];
1262
+ }
1263
+ },
1264
+ {
1265
+ name: 'UnderwaterAmbientIntensity',
1266
+ description: 'Scale on the downwelling sky light filling the water column. This is what the water fades to in the distance, so it sets how bright the underwater haze reads.',
1267
+ type: 'float',
1268
+ default: 1,
1269
+ options: {
1270
+ animatable: true,
1271
+ minValue: 0,
1272
+ maxValue: 5
1273
+ },
1274
+ isHidden () {
1275
+ return !this.underwaterEnabled;
1276
+ },
1277
+ get (value) {
1278
+ value.num[0] = this.underwaterAmbientIntensity;
1279
+ },
1280
+ set (value) {
1281
+ this.underwaterAmbientIntensity = value.num[0];
1282
+ }
1283
+ },
1284
+ {
1285
+ name: 'UnderwaterGodRays',
1286
+ description: 'Whether shafts of sunlight are marched through the water column. Reads the caustic map as the surface transmittance, so the shafts carry the pattern that lands on the sea bed; needs CausticsEnabled.',
1287
+ type: 'bool',
1288
+ default: true,
1289
+ isHidden () {
1290
+ return !this.underwaterEnabled;
1291
+ },
1292
+ get (value) {
1293
+ value.bool[0] = this.underwaterGodRays;
1294
+ },
1295
+ set (value) {
1296
+ this.underwaterGodRays = value.bool[0];
1297
+ }
1298
+ },
1299
+ {
1300
+ name: 'UnderwaterGodRayIntensity',
1301
+ description: 'Strength of the light shafts, 1 for the value the medium implies',
1302
+ type: 'float',
1303
+ default: 1,
1304
+ options: {
1305
+ animatable: true,
1306
+ minValue: 0,
1307
+ maxValue: 5
1308
+ },
1309
+ isHidden () {
1310
+ return !this.underwaterEnabled || !this.underwaterGodRays;
1311
+ },
1312
+ get (value) {
1313
+ value.num[0] = this.underwaterGodRayIntensity;
1314
+ },
1315
+ set (value) {
1316
+ this.underwaterGodRayIntensity = value.num[0];
1317
+ }
1318
+ },
1319
+ {
1320
+ name: 'UnderwaterGodRaySteps',
1321
+ description: 'Samples taken along each view ray for the light shafts. Raise it when the shafts read as grain rather than as beams.',
1322
+ type: 'int',
1323
+ default: 24,
1324
+ options: {
1325
+ minValue: 4,
1326
+ maxValue: 96
1327
+ },
1328
+ isHidden () {
1329
+ return !this.underwaterEnabled || !this.underwaterGodRays;
1330
+ },
1331
+ get (value) {
1332
+ value.num[0] = this.underwaterGodRaySteps;
1333
+ },
1334
+ set (value) {
1335
+ this.underwaterGodRaySteps = value.num[0];
1336
+ }
1337
+ },
1338
+ {
1339
+ name: 'UnderwaterGodRayShadow',
1340
+ description: 'Whether geometry standing in the water breaks the light shafts. The shafts come from the caustic map, which knows only what the surface did to the sunlight, so without this a shaft runs straight through a piling. Costs a shadow map lookup per march step.',
1341
+ type: 'bool',
1342
+ default: false,
1343
+ isHidden () {
1344
+ return !this.underwaterEnabled || !this.underwaterGodRays;
1345
+ },
1346
+ get (value) {
1347
+ value.bool[0] = this.underwaterGodRayShadow;
1348
+ },
1349
+ set (value) {
1350
+ this.underwaterGodRayShadow = value.bool[0];
1351
+ }
1352
+ },
1353
+ {
1354
+ name: 'UnderwaterHysteresis',
1355
+ description: 'Half-width in meters of the dead band around the surface the submerged test uses, so a camera at water level does not flip state every frame',
1356
+ type: 'float',
1357
+ default: 0.05,
1358
+ options: {
1359
+ minValue: 0,
1360
+ maxValue: 2
1361
+ },
1362
+ isHidden () {
1363
+ return !this.underwaterEnabled;
1364
+ },
1365
+ get (value) {
1366
+ value.num[0] = this.underwaterHysteresis;
1367
+ },
1368
+ set (value) {
1369
+ this.underwaterHysteresis = value.num[0];
1370
+ }
1371
+ },
1372
+ {
1373
+ name: 'RefractionMode',
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.',
1375
+ type: 'string',
1376
+ default: 'march',
1377
+ options: {
1378
+ enum: {
1379
+ labels: [
1380
+ 'March (accurate)',
1381
+ 'Offset (cheap)'
1382
+ ],
1383
+ values: [
1384
+ 'march',
1385
+ 'offset'
1386
+ ]
1387
+ }
1388
+ },
1389
+ get (value) {
1390
+ value.str[0] = this.material.refractionMode;
1391
+ },
1392
+ set (value) {
1393
+ this.material.refractionMode = value.str[0];
1394
+ }
1395
+ },
1396
+ {
1397
+ name: 'DebugOutput',
1398
+ description: 'Debugging aid: replaces the water colour with one of the shading terms it is built from, so a broken term can be identified by eye',
1399
+ type: 'string',
1400
+ default: 'none',
1401
+ options: {
1402
+ enum: {
1403
+ labels: WATER_DEBUG_OUTPUTS.map((e)=>e.label),
1404
+ values: WATER_DEBUG_OUTPUTS.map((e)=>e.value)
1405
+ }
1406
+ },
1407
+ get (value) {
1408
+ value.str[0] = this.debugOutput;
1409
+ },
1410
+ set (value) {
1411
+ this.debugOutput = value.str[0];
1412
+ }
1413
+ },
1414
+ {
1415
+ name: 'Absorption',
1416
+ description: 'Absorption coefficient sigma_a of the water medium, per meter, per channel',
1417
+ type: 'rgb',
1418
+ default: [
1419
+ 1.0,
1420
+ 0.25,
1421
+ 0.15
1422
+ ],
1423
+ options: {
1424
+ animatable: true,
1425
+ minValue: 0,
1426
+ maxValue: 10
1427
+ },
1428
+ get (value) {
1429
+ value.num[0] = this.material.absorption.x;
1430
+ value.num[1] = this.material.absorption.y;
1431
+ value.num[2] = this.material.absorption.z;
1432
+ },
1433
+ set (value) {
1434
+ this.material.absorption = new Vector3(value.num[0], value.num[1], value.num[2]);
1435
+ }
1436
+ },
1437
+ {
1438
+ name: 'AbsorptionScale',
1439
+ description: 'Scale for the absorption coefficient',
1440
+ type: 'float',
1441
+ default: 1,
1442
+ options: {
1443
+ animatable: true,
1444
+ minValue: 0,
1445
+ maxValue: 10
1446
+ },
1447
+ get (value) {
1448
+ value.num[0] = this.material.absorptionScale;
1449
+ },
1450
+ set (value) {
1451
+ this.material.absorptionScale = value.num[0];
1452
+ }
1453
+ },
1454
+ {
1455
+ name: 'Scattering',
1456
+ description: 'Scattering coefficient sigma_s of the water medium, per meter, per channel',
1457
+ type: 'rgb',
1458
+ default: [
1459
+ 0.05,
1460
+ 0.12,
1461
+ 0.18
1462
+ ],
1463
+ options: {
1464
+ animatable: true,
1465
+ minValue: 0,
1466
+ maxValue: 10
1467
+ },
1468
+ get (value) {
1469
+ value.num[0] = this.material.scattering.x;
1470
+ value.num[1] = this.material.scattering.y;
1471
+ value.num[2] = this.material.scattering.z;
1472
+ },
1473
+ set (value) {
1474
+ this.material.scattering = new Vector3(value.num[0], value.num[1], value.num[2]);
1475
+ }
1476
+ },
1477
+ {
1478
+ name: 'ScatteringScale',
1479
+ description: 'Scale for the scattering coefficient',
1480
+ type: 'float',
1481
+ default: 1,
1482
+ options: {
1483
+ animatable: true,
1484
+ minValue: 0,
1485
+ maxValue: 10
1486
+ },
1487
+ get (value) {
1488
+ value.num[0] = this.material.scatteringScale;
1489
+ },
1490
+ set (value) {
1491
+ this.material.scatteringScale = value.num[0];
1492
+ }
1493
+ },
1494
+ {
1495
+ name: 'ReflectionStrength',
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.',
1497
+ type: 'float',
1498
+ default: 1,
1499
+ options: {
1500
+ animatable: true,
1501
+ minValue: 0,
1502
+ maxValue: 1
1503
+ },
1504
+ get (value) {
1505
+ value.num[0] = this.material.reflectionStrength;
1506
+ },
1507
+ set (value) {
1508
+ this.material.reflectionStrength = value.num[0];
1509
+ }
1510
+ },
1511
+ {
1512
+ name: 'SubsurfaceIntensity',
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.',
1514
+ type: 'float',
1515
+ default: 0.5,
1516
+ options: {
1517
+ animatable: true,
1518
+ minValue: 0,
1519
+ maxValue: 10
1520
+ },
1521
+ get (value) {
1522
+ value.num[0] = this.material.subsurfaceIntensity;
1523
+ },
1524
+ set (value) {
1525
+ this.material.subsurfaceIntensity = value.num[0];
1526
+ }
1527
+ },
1528
+ {
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.',
1531
+ type: 'float',
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
+ ],
1554
+ options: {
1555
+ animatable: true,
1556
+ minValue: 0,
1557
+ maxValue: 1
1558
+ },
1559
+ get (value) {
1560
+ value.num[0] = this.material.subsurfaceTint.x;
1561
+ value.num[1] = this.material.subsurfaceTint.y;
1562
+ value.num[2] = this.material.subsurfaceTint.z;
1563
+ },
1564
+ set (value) {
1565
+ this.material.subsurfaceTint = new Vector3(value.num[0], value.num[1], value.num[2]);
1566
+ }
1567
+ },
1568
+ {
1569
+ name: 'SunScatteringIntensity',
1570
+ description: 'Strength of the sunlight scattered out of the water column towards the eye, 1 for the value the medium coefficients imply. This is what makes a shadow on the water darken the water itself and a low sun tint it; 0 leaves the body lit by the environment alone.',
1571
+ type: 'float',
1572
+ default: 1,
1573
+ options: {
1574
+ animatable: true,
1575
+ minValue: 0,
1576
+ maxValue: 4
1577
+ },
1578
+ get (value) {
1579
+ value.num[0] = this.material.sunScatteringIntensity;
1580
+ },
1581
+ set (value) {
1582
+ this.material.sunScatteringIntensity = value.num[0];
1583
+ }
1584
+ },
1585
+ {
1586
+ name: 'FoamAmount',
1587
+ description: 'Coverage of the foam on breaking wave crests, mapped from the folding the wave generator reports. 0 disables crest foam.',
1588
+ type: 'float',
1589
+ default: 1,
1590
+ options: {
1591
+ animatable: true,
1592
+ minValue: 0,
1593
+ maxValue: 4
1594
+ },
1595
+ get (value) {
1596
+ value.num[0] = this.material.foamAmount;
1597
+ },
1598
+ set (value) {
1599
+ this.material.foamAmount = value.num[0];
1600
+ }
1601
+ },
1602
+ {
1603
+ name: 'FoamFalloff',
1604
+ description: 'Falloff applied to crest foam coverage. Above 1 pushes light folding towards no foam at all, so only a genuinely broken crest shows - which is what keeps a windy sea from turning uniformly white.',
1605
+ type: 'float',
1606
+ default: 1.5,
1607
+ options: {
1608
+ animatable: true,
1609
+ minValue: 0.01,
1610
+ maxValue: 8
1611
+ },
1612
+ isHidden () {
1613
+ return this.material.foamAmount <= 0;
1614
+ },
1615
+ get (value) {
1616
+ value.num[0] = this.material.foamFalloff;
1617
+ },
1618
+ set (value) {
1619
+ this.material.foamFalloff = value.num[0];
1620
+ }
1621
+ },
1622
+ {
1623
+ name: 'FoamColor',
1624
+ description: 'Diffuse albedo of the foam, shared by the crest foam and the shoreline foam. Slightly off-white and slightly blue - sea foam is water and air, and a pure white one reads as snow.',
1625
+ type: 'rgb',
1626
+ default: [
1627
+ 0.92,
1628
+ 0.95,
1629
+ 0.97
1630
+ ],
1631
+ options: {
1632
+ animatable: true,
1633
+ minValue: 0,
1634
+ maxValue: 1
1635
+ },
1636
+ get (value) {
1637
+ value.num[0] = this.material.foamColor.x;
1638
+ value.num[1] = this.material.foamColor.y;
1639
+ value.num[2] = this.material.foamColor.z;
1640
+ },
1641
+ set (value) {
1642
+ this.material.foamColor = new Vector3(value.num[0], value.num[1], value.num[2]);
1643
+ }
1644
+ },
1645
+ {
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.',
1648
+ type: 'float',
1649
+ default: 0.4,
1650
+ options: {
1651
+ animatable: true,
1652
+ minValue: 0.001,
1653
+ maxValue: 1
1654
+ },
1655
+ get (value) {
1656
+ value.num[0] = this.material.foamFeather;
1657
+ },
1658
+ set (value) {
1659
+ this.material.foamFeather = value.num[0];
1660
+ }
1661
+ },
1662
+ {
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.',
1665
+ type: 'float',
1666
+ default: 3.5,
1667
+ options: {
1668
+ animatable: true,
1669
+ minValue: 0,
1670
+ maxValue: 30
1671
+ },
1672
+ get (value) {
1673
+ value.num[0] = this.material.foamNormalStrength;
1674
+ },
1675
+ set (value) {
1676
+ this.material.foamNormalStrength = value.num[0];
1677
+ }
1678
+ },
1679
+ {
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
+ ],
1688
+ options: {
1689
+ animatable: true,
1690
+ minValue: 0,
1691
+ maxValue: 1
1692
+ },
1693
+ get (value) {
1694
+ value.num[0] = this.material.foamBubbleColor.x;
1695
+ value.num[1] = this.material.foamBubbleColor.y;
1696
+ value.num[2] = this.material.foamBubbleColor.z;
1697
+ },
1698
+ set (value) {
1699
+ this.material.foamBubbleColor = new Vector3(value.num[0], value.num[1], value.num[2]);
1700
+ }
1701
+ },
1702
+ {
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.',
1705
+ type: 'float',
1706
+ default: 1.68,
1707
+ options: {
1708
+ animatable: true,
1709
+ minValue: 0,
1710
+ maxValue: 5
1711
+ },
1712
+ get (value) {
1713
+ value.num[0] = this.material.foamBubbleCoverage;
1714
+ },
1715
+ set (value) {
1716
+ this.material.foamBubbleCoverage = value.num[0];
1717
+ }
1718
+ },
1719
+ {
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.',
1722
+ type: 'float',
1723
+ default: 0.14,
1724
+ options: {
1725
+ animatable: true,
1726
+ minValue: 0,
1727
+ maxValue: 1
1728
+ },
1729
+ get (value) {
1730
+ value.num[0] = this.material.foamBubbleDepth;
1731
+ },
1732
+ set (value) {
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
+ }
1775
+ }
1776
+ },
1777
+ {
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.',
1780
+ type: 'float',
1781
+ default: 4,
1782
+ options: {
1783
+ animatable: true,
1784
+ minValue: 0.01,
1785
+ maxValue: 50
1786
+ },
1787
+ get (value) {
1788
+ value.num[0] = this.material.foamTextureSize;
1789
+ },
1790
+ set (value) {
1791
+ this.material.foamTextureSize = value.num[0];
1792
+ }
1793
+ },
1794
+ {
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.',
1797
+ type: 'float',
1798
+ default: 1,
1799
+ options: {
1800
+ animatable: true,
1801
+ minValue: 0,
1802
+ maxValue: 5
1803
+ },
1804
+ get (value) {
1805
+ value.num[0] = this.foamTrailStrength;
1806
+ },
1807
+ set (value) {
1808
+ this.foamTrailStrength = value.num[0];
1809
+ }
1810
+ },
1811
+ {
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.',
1814
+ type: 'float',
1815
+ default: 0.8,
1816
+ options: {
1817
+ animatable: true,
1818
+ minValue: 0.01,
1819
+ maxValue: 20
1820
+ },
1821
+ get (value) {
1822
+ value.num[0] = this.foamFadeRate;
1823
+ },
1824
+ set (value) {
1825
+ this.foamFadeRate = value.num[0];
1826
+ }
1827
+ },
1828
+ {
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.',
1831
+ type: 'float',
1832
+ default: 0.03,
1833
+ options: {
1834
+ animatable: true,
1835
+ minValue: 0,
1836
+ maxValue: 0.2
1837
+ },
1838
+ get (value) {
1839
+ value.num[0] = this.foamDrift;
1840
+ },
1841
+ set (value) {
1842
+ this.foamDrift = value.num[0];
1843
+ }
1844
+ },
1845
+ {
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.',
1848
+ type: 'float',
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,
1867
+ options: {
1868
+ animatable: true,
1869
+ minValue: 0,
1870
+ maxValue: 1
1871
+ },
1872
+ get (value) {
1873
+ value.num[0] = this.edgeFadeWidth;
1874
+ },
1875
+ set (value) {
1876
+ this.edgeFadeWidth = value.num[0];
1877
+ }
1878
+ },
1879
+ {
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.',
1882
+ type: 'float',
1883
+ default: 0,
1884
+ options: {
1885
+ animatable: true,
1886
+ minValue: 0,
1887
+ maxValue: 3
1888
+ },
1889
+ isHidden () {
1890
+ return false;
1891
+ },
1892
+ get (value) {
1893
+ value.num[0] = this.shoreWaveHeight;
1894
+ },
1895
+ set (value) {
1896
+ this.shoreWaveHeight = value.num[0];
1897
+ }
1898
+ },
1899
+ {
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.',
1902
+ type: 'float',
1903
+ default: 8,
1904
+ options: {
1905
+ animatable: true,
1906
+ minValue: 0.5,
1907
+ maxValue: 100
1908
+ },
1909
+ isHidden () {
1910
+ return this.shoreWaveHeight <= 0;
1911
+ },
1912
+ get (value) {
1913
+ value.num[0] = this.shoreWaveLength;
1914
+ },
1915
+ set (value) {
1916
+ this.shoreWaveLength = value.num[0];
1917
+ }
1918
+ },
1919
+ {
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;
1931
+ },
1932
+ get (value) {
1933
+ value.num[0] = this.shoreWavePeriod;
1934
+ },
1935
+ set (value) {
1936
+ this.shoreWavePeriod = value.num[0];
1937
+ }
1938
+ },
1939
+ {
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;
1951
+ },
1952
+ get (value) {
1953
+ value.num[0] = this.shoreWaveZone;
1954
+ },
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);
2690
+ }
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];
495
2854
  }
496
2855
  }
497
2856
  ]);
@@ -499,5 +2858,5 @@ import '../../../scene/raycast_visitor.js';
499
2858
  };
500
2859
  }
501
2860
 
502
- export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getWaterClass };
2861
+ export { getFBMWaveGeneratorClass, getFFTWaveGeneratorClass, getGerstnerWaveClass, getGerstnerWaveGeneratorClass, getWaterClass, getWaterDisturberClass, getWaterInteractionClass };
503
2862
  //# sourceMappingURL=water.js.map