@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,8 +1,9 @@
1
1
  import { Scene } from '../../../scene/scene.js';
2
2
  import { defineProps } from '../types.js';
3
- import { Vector3, Vector4 } from '@zephyr3d/base';
3
+ import { Vector3, Vector4, Vector2 } from '@zephyr3d/base';
4
4
  import { JSONData, JSONArray } from '../json.js';
5
5
  import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scene/script_attachment.js';
6
+ import { ScenePhysicsSettings } from '../../../scene/physics_settings.js';
6
7
 
7
8
  /** @internal */ function getSceneClass(manager) {
8
9
  return {
@@ -41,6 +42,293 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
41
42
  this.lightingMode = value.str[0];
42
43
  }
43
44
  },
45
+ {
46
+ name: 'SDFEnabled',
47
+ description: 'Track the meshes with a baked signed distance field and stream their fields in around the camera, for the effects and simulations that read the scene SDF.',
48
+ type: 'bool',
49
+ default: false,
50
+ options: {
51
+ group: 'SDF'
52
+ },
53
+ get (value) {
54
+ value.bool[0] = this.sdf.enabled;
55
+ },
56
+ set (value) {
57
+ this.sdf.enabled = value.bool[0];
58
+ }
59
+ },
60
+ {
61
+ name: 'SDFStreamRadius',
62
+ description: 'Distance from the camera within which mesh fields are kept loaded.',
63
+ type: 'float',
64
+ default: 256,
65
+ options: {
66
+ group: 'SDF',
67
+ minValue: 1,
68
+ maxValue: 100000
69
+ },
70
+ isHidden () {
71
+ return !this.sdf.enabled;
72
+ },
73
+ get (value) {
74
+ value.num[0] = this.sdf.streamRadius;
75
+ },
76
+ set (value) {
77
+ this.sdf.streamRadius = Math.max(1, value.num[0]);
78
+ }
79
+ },
80
+ {
81
+ name: 'SDFAtlasSize',
82
+ description: 'Voxels per axis of the texture that holds the loaded mesh fields. When meshes near the camera are missing from the distance field view and the console warns that the atlas is full, raise it; each axis costs memory, 512×256×256 is 64 MB.',
83
+ type: 'int3',
84
+ default: [
85
+ 512,
86
+ 256,
87
+ 256
88
+ ],
89
+ options: {
90
+ group: 'SDF',
91
+ minValue: 64,
92
+ maxValue: 2048
93
+ },
94
+ isHidden () {
95
+ return !this.sdf.enabled;
96
+ },
97
+ get (value) {
98
+ const size = this.sdf.atlasSize;
99
+ value.num[0] = size[0];
100
+ value.num[1] = size[1];
101
+ value.num[2] = size[2];
102
+ },
103
+ set (value) {
104
+ this.sdf.atlasSize = [
105
+ value.num[0],
106
+ value.num[1],
107
+ value.num[2]
108
+ ];
109
+ }
110
+ },
111
+ {
112
+ name: 'GIEnabled',
113
+ description: 'Build the voxel scene the global illumination reads: the static meshes with a baked distance field are rasterized into a material atlas around the camera, giving the field surfaces their colour and glow. Turns SDFEnabled on. WebGPU only; nothing changes on WebGL2.',
114
+ type: 'bool',
115
+ default: false,
116
+ options: {
117
+ group: 'Global Illumination'
118
+ },
119
+ get (value) {
120
+ value.bool[0] = this.gi.enabled;
121
+ },
122
+ set (value) {
123
+ this.gi.enabled = value.bool[0];
124
+ }
125
+ },
126
+ {
127
+ name: 'GIVoxelizeBudget',
128
+ description: 'Meshes voxelized per frame. Higher fills the voxel scene sooner after loading or moving far, at the cost of a longer frame while it does.',
129
+ type: 'int',
130
+ default: 8,
131
+ options: {
132
+ group: 'Global Illumination',
133
+ minValue: 1,
134
+ maxValue: 64
135
+ },
136
+ isHidden () {
137
+ return !this.gi.enabled;
138
+ },
139
+ get (value) {
140
+ value.num[0] = this.gi.voxelizeBudget;
141
+ },
142
+ set (value) {
143
+ this.gi.voxelizeBudget = value.num[0];
144
+ }
145
+ },
146
+ {
147
+ name: 'GISunShadowConeAngle',
148
+ description: 'Softness of the sun shadow in the bounced light, as the half angle in degrees of the cone traced through the distance field; the default is the size of the sun. Wider blurs the shadow edges in the indirect light but darkens floors lit through narrow openings; narrower sharpens them.',
149
+ type: 'float',
150
+ default: 0.5357,
151
+ options: {
152
+ group: 'Global Illumination',
153
+ minValue: 0.1,
154
+ maxValue: 45
155
+ },
156
+ isHidden () {
157
+ return !this.gi.enabled;
158
+ },
159
+ get (value) {
160
+ value.num[0] = this.gi.sunShadowConeAngle;
161
+ },
162
+ set (value) {
163
+ this.gi.sunShadowConeAngle = value.num[0];
164
+ }
165
+ },
166
+ {
167
+ name: 'GILocalLightShadows',
168
+ description: 'Let point, spot and rect lights that cast shadows also cast them in the bounced light, so objects block the light they bounce. Applies to the eight lights nearest the camera; turn off to save GPU time in scenes with many shadowed lights.',
169
+ type: 'bool',
170
+ default: true,
171
+ options: {
172
+ group: 'Global Illumination'
173
+ },
174
+ isHidden () {
175
+ return !this.gi.enabled;
176
+ },
177
+ get (value) {
178
+ value.bool[0] = this.gi.localLightShadows;
179
+ },
180
+ set (value) {
181
+ this.gi.localLightShadows = value.bool[0];
182
+ }
183
+ },
184
+ {
185
+ name: 'GIIntensity',
186
+ description: 'Strength of the bounced light the probes add. 1 is physically consistent with the direct lighting; raise to exaggerate colour bleeding, lower to tone it down.',
187
+ type: 'float',
188
+ default: 1,
189
+ options: {
190
+ group: 'Global Illumination',
191
+ minValue: 0,
192
+ maxValue: 10
193
+ },
194
+ isHidden () {
195
+ return !this.gi.enabled;
196
+ },
197
+ get (value) {
198
+ value.num[0] = this.gi.intensity;
199
+ },
200
+ set (value) {
201
+ this.gi.intensity = value.num[0];
202
+ }
203
+ },
204
+ {
205
+ name: 'GIProbeSpacing',
206
+ description: 'Distance in world units between light probes. Smaller resolves indirect light in tighter spaces and leaks less through thin walls, but the volume covers less distance around the camera and takes longer to refresh.',
207
+ type: 'float',
208
+ default: 1,
209
+ options: {
210
+ group: 'Global Illumination',
211
+ minValue: 0.25,
212
+ maxValue: 16
213
+ },
214
+ isHidden () {
215
+ return !this.gi.enabled;
216
+ },
217
+ get (value) {
218
+ value.num[0] = this.gi.probeSpacing;
219
+ },
220
+ set (value) {
221
+ this.gi.probeSpacing = value.num[0];
222
+ }
223
+ },
224
+ {
225
+ name: 'GIProbeBudget',
226
+ description: 'Light probes updated per frame. Higher makes bounced light follow moving lights and the camera sooner, at more GPU time per frame.',
227
+ type: 'int',
228
+ default: 4096,
229
+ options: {
230
+ group: 'Global Illumination',
231
+ minValue: 64,
232
+ maxValue: 16384
233
+ },
234
+ isHidden () {
235
+ return !this.gi.enabled;
236
+ },
237
+ get (value) {
238
+ value.num[0] = this.gi.probeBudget;
239
+ },
240
+ set (value) {
241
+ this.gi.probeBudget = value.num[0];
242
+ }
243
+ },
244
+ {
245
+ name: 'GIProbeRays',
246
+ description: 'Rays each probe traces per update. More gives smoother, less flickering bounced light at more GPU time per frame.',
247
+ type: 'int',
248
+ default: 128,
249
+ options: {
250
+ group: 'Global Illumination',
251
+ minValue: 16,
252
+ maxValue: 512
253
+ },
254
+ isHidden () {
255
+ return !this.gi.enabled;
256
+ },
257
+ get (value) {
258
+ value.num[0] = this.gi.probeRays;
259
+ },
260
+ set (value) {
261
+ this.gi.probeRays = value.num[0];
262
+ }
263
+ },
264
+ {
265
+ name: 'GIProbeHysteresis',
266
+ description: 'How long bounced light holds on to what it showed before. Higher keeps it steadier in a still view but slower to follow a light or camera change; lower follows sooner with more flicker.',
267
+ type: 'float',
268
+ default: 0.97,
269
+ options: {
270
+ group: 'Global Illumination',
271
+ minValue: 0.5,
272
+ maxValue: 0.99
273
+ },
274
+ isHidden () {
275
+ return !this.gi.enabled;
276
+ },
277
+ get (value) {
278
+ value.num[0] = this.gi.probeHysteresis;
279
+ },
280
+ set (value) {
281
+ this.gi.probeHysteresis = value.num[0];
282
+ }
283
+ },
284
+ {
285
+ name: 'GIProbeLevels',
286
+ description: 'Nested probe volumes around the camera, each twice as coarse and as wide as the one inside it. More levels carry bounced light farther out, each adding as many probes as the finest, so every probe is refreshed less often; one level covers only the finest volume.',
287
+ type: 'int',
288
+ default: 4,
289
+ options: {
290
+ group: 'Global Illumination',
291
+ minValue: 1,
292
+ maxValue: 4
293
+ },
294
+ isHidden () {
295
+ return !this.gi.enabled;
296
+ },
297
+ get (value) {
298
+ value.num[0] = this.gi.probeLevels;
299
+ },
300
+ set (value) {
301
+ this.gi.probeLevels = value.num[0];
302
+ }
303
+ },
304
+ {
305
+ name: 'GIUpdateMode',
306
+ description: 'Continuous keeps the bounced light following the sun, the lights and the camera. Frozen stops it where it is: cheaper, and right for a scene whose lighting does not change, but the volume no longer follows the camera.',
307
+ type: 'string',
308
+ default: 'continuous',
309
+ options: {
310
+ group: 'Global Illumination',
311
+ enum: {
312
+ labels: [
313
+ 'Continuous',
314
+ 'Frozen'
315
+ ],
316
+ values: [
317
+ 'continuous',
318
+ 'frozen'
319
+ ]
320
+ }
321
+ },
322
+ isHidden () {
323
+ return !this.gi.enabled;
324
+ },
325
+ get (value) {
326
+ value.str[0] = this.gi.updateMode;
327
+ },
328
+ set (value) {
329
+ this.gi.updateMode = value.str[0];
330
+ }
331
+ },
44
332
  {
45
333
  name: 'MetersPerUnit',
46
334
  description: 'Physical meters represented by one scene unit',
@@ -538,7 +826,7 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
538
826
  },
539
827
  {
540
828
  name: 'HeightFogEndDistance',
541
- description: 'Distance from the camera where height fog reaches full effect',
829
+ description: 'Horizontal distance beyond which height fog stops getting thicker. 0 lets it keep accumulating to any distance',
542
830
  type: 'float',
543
831
  default: 10000,
544
832
  options: {
@@ -641,17 +929,59 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
641
929
  this.env.sky.heightFogDirColor = new Vector3(value.num[0], value.num[1], value.num[2]);
642
930
  }
643
931
  },
932
+ {
933
+ name: 'HeightFogSkyLightStrength',
934
+ description: 'Makes distant fog take the color of the environment behind it instead of one flat color, removing the dark band at the horizon. Needs an IBL environment light',
935
+ type: 'float',
936
+ options: {
937
+ group: 'HeightFog',
938
+ label: 'SkyLightStrength',
939
+ minValue: 0,
940
+ maxValue: 1
941
+ },
942
+ default: 0,
943
+ isValid () {
944
+ return this.env.sky.fogType === 'height_fog';
945
+ },
946
+ get (value) {
947
+ value.num[0] = this.env.sky.heightFogSkyLightStrength;
948
+ },
949
+ set (value) {
950
+ this.env.sky.heightFogSkyLightStrength = value.num[0];
951
+ }
952
+ },
953
+ {
954
+ name: 'HeightFogSkyLightRoughness',
955
+ description: 'Blurriness of the environment seen through the fog. Higher values give a softer, more uniform fog color',
956
+ type: 'float',
957
+ options: {
958
+ group: 'HeightFog',
959
+ label: 'SkyLightRoughness',
960
+ minValue: 0,
961
+ maxValue: 1
962
+ },
963
+ default: 0.15,
964
+ isValid () {
965
+ return this.env.sky.fogType === 'height_fog';
966
+ },
967
+ get (value) {
968
+ value.num[0] = this.env.sky.heightFogSkyLightRoughness;
969
+ },
970
+ set (value) {
971
+ this.env.sky.heightFogSkyLightRoughness = value.num[0];
972
+ }
973
+ },
644
974
  {
645
975
  name: 'AerialPerspectiveDistance',
646
- description: 'Distance scale for aerial perspective in the scattering sky model',
976
+ description: 'How far the atmosphere keeps hazing distant objects toward the sky color. Beyond this distance the haze stops getting thicker',
647
977
  type: 'float',
648
978
  phase: 1,
649
979
  options: {
650
980
  animatable: true,
651
981
  minValue: 1,
652
- maxValue: 50000
982
+ maxValue: 200000
653
983
  },
654
- default: 1,
984
+ default: 96000,
655
985
  get (value) {
656
986
  value.num[0] = this.env.sky.aerialPerspectiveDistance;
657
987
  },
@@ -663,123 +993,1275 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
663
993
  }
664
994
  },
665
995
  {
666
- name: 'CameraHeightScale',
667
- description: 'Scale factor applied to camera height in atmospheric scattering',
996
+ name: 'AerialPerspectiveViewDistanceScale',
997
+ description: 'Strength of the atmospheric haze on distant objects. Higher values make them fade into the sky color sooner; the sky itself does not change',
668
998
  type: 'float',
669
999
  phase: 1,
670
1000
  options: {
671
1001
  animatable: true,
672
- minValue: 1,
673
- maxValue: 1000
1002
+ minValue: 0,
1003
+ maxValue: 10
674
1004
  },
675
1005
  default: 1,
676
1006
  get (value) {
677
- value.num[0] = this.env.sky.cameraHeightScale;
1007
+ value.num[0] = this.env.sky.aerialPerspectiveViewDistanceScale;
678
1008
  },
679
1009
  set (value) {
680
- this.env.sky.cameraHeightScale = value.num[0];
1010
+ this.env.sky.aerialPerspectiveViewDistanceScale = value.num[0];
681
1011
  },
682
1012
  isValid () {
683
1013
  return this.env.sky.skyType === 'scatter';
684
1014
  }
685
1015
  },
686
1016
  {
687
- name: 'AtmosphereExposure',
688
- description: 'Exposure multiplier for atmospheric scattering and sky rendering',
1017
+ name: 'AerialPerspectiveStartDepth',
1018
+ description: 'Distance from the camera, in meters, where the atmospheric haze starts. Anything nearer stays completely clear',
689
1019
  type: 'float',
1020
+ phase: 1,
690
1021
  options: {
691
1022
  animatable: true,
692
1023
  minValue: 0,
693
- maxValue: 8
1024
+ maxValue: 10000
694
1025
  },
695
- default: 1,
1026
+ default: 100,
696
1027
  get (value) {
697
- value.num[0] = this.env.sky.atmosphereExposure;
1028
+ value.num[0] = this.env.sky.aerialPerspectiveStartDepth;
698
1029
  },
699
1030
  set (value) {
700
- this.env.sky.atmosphereExposure = value.num[0];
1031
+ this.env.sky.aerialPerspectiveStartDepth = value.num[0];
701
1032
  },
702
1033
  isValid () {
703
1034
  return this.env.sky.skyType === 'scatter';
704
1035
  }
705
1036
  },
706
1037
  {
707
- name: 'Cloudy',
708
- description: 'Cloud coverage amount for the procedural sky',
1038
+ name: 'CameraHeightScale',
1039
+ description: 'How many meters of atmosphere one world unit stands for. Larger values make the camera climb faster through the sky and distant objects haze sooner',
709
1040
  type: 'float',
710
- default: 0.6,
711
1041
  phase: 1,
712
1042
  options: {
713
1043
  animatable: true,
714
- minValue: 0,
715
- maxValue: 1
1044
+ minValue: 0.001,
1045
+ maxValue: 1000
716
1046
  },
1047
+ default: 1,
717
1048
  get (value) {
718
- value.num[0] = this.env.sky.cloudy;
1049
+ value.num[0] = this.env.sky.cameraHeightScale;
719
1050
  },
720
1051
  set (value) {
721
- this.env.sky.cloudy = value.num[0];
1052
+ this.env.sky.cameraHeightScale = value.num[0];
722
1053
  },
723
1054
  isValid () {
724
1055
  return this.env.sky.skyType === 'scatter';
725
1056
  }
726
1057
  },
727
1058
  {
728
- name: 'CloudIntensity',
729
- description: 'Brightness of procedural clouds',
1059
+ name: 'AtmosphereRebakeAltitudeRatio',
1060
+ description: 'How much the camera must climb or descend, as a fraction of its altitude, before the environment lighting from the sky is updated. Smaller values follow the sky more closely while flying but cost more',
730
1061
  type: 'float',
731
- default: 40,
732
1062
  phase: 1,
733
1063
  options: {
734
- animatable: true,
735
1064
  minValue: 0,
736
- maxValue: 200
1065
+ maxValue: 1
737
1066
  },
1067
+ default: 0.05,
738
1068
  get (value) {
739
- value.num[0] = this.env.sky.cloudIntensity;
1069
+ value.num[0] = this.env.sky.atmosphereRebakeAltitudeRatio;
740
1070
  },
741
1071
  set (value) {
742
- this.env.sky.cloudIntensity = value.num[0];
1072
+ this.env.sky.atmosphereRebakeAltitudeRatio = value.num[0];
743
1073
  },
744
1074
  isValid () {
745
1075
  return this.env.sky.skyType === 'scatter';
746
1076
  }
747
1077
  },
748
1078
  {
749
- name: 'Wind',
750
- description: 'Wind direction and speed used by the procedural sky',
751
- type: 'vec2',
752
- default: [
753
- 0,
754
- 0
755
- ],
1079
+ name: 'AtmosphereRebakeAngle',
1080
+ description: 'How far, in degrees of planet curvature, the camera must travel before the environment lighting from the sky is updated. 0.5 degrees is about 55 km on Earth',
1081
+ type: 'float',
756
1082
  phase: 1,
757
1083
  options: {
758
- animatable: true,
759
- minValue: -100,
760
- maxValue: 100
1084
+ minValue: 0,
1085
+ maxValue: 10
761
1086
  },
1087
+ default: 0.5,
762
1088
  get (value) {
763
- value.num[0] = this.env.sky.wind.x;
764
- value.num[1] = this.env.sky.wind.y;
1089
+ value.num[0] = this.env.sky.atmosphereRebakeAngle;
765
1090
  },
766
1091
  set (value) {
767
- this.env.sky.wind.setXY(value.num[0], value.num[1]);
1092
+ this.env.sky.atmosphereRebakeAngle = value.num[0];
768
1093
  },
769
1094
  isValid () {
770
1095
  return this.env.sky.skyType === 'scatter';
771
1096
  }
772
1097
  },
773
1098
  {
774
- name: 'SkyBoxRotation',
775
- description: 'Euler rotation of the skybox',
776
- type: 'vec3',
1099
+ name: 'GroundAlbedo',
1100
+ description: 'Color of the ground seen below the horizon where no geometry covers the sky. It also reflects light back up and brightens the sky slightly',
1101
+ type: 'rgb',
1102
+ phase: 1,
777
1103
  default: [
778
- 0,
779
- 0,
780
- 0
1104
+ 0.401978,
1105
+ 0.401978,
1106
+ 0.401978
781
1107
  ],
782
- phase: 1,
1108
+ get (value) {
1109
+ value.num[0] = this.env.sky.groundAlbedo.x;
1110
+ value.num[1] = this.env.sky.groundAlbedo.y;
1111
+ value.num[2] = this.env.sky.groundAlbedo.z;
1112
+ },
1113
+ set (value) {
1114
+ this.env.sky.groundAlbedo = new Vector3(value.num[0], value.num[1], value.num[2]);
1115
+ },
1116
+ isValid () {
1117
+ return this.env.sky.skyType === 'scatter';
1118
+ }
1119
+ },
1120
+ {
1121
+ name: 'LowerHemisphereIsBlack',
1122
+ description: 'Keeps the ground below the horizon out of the environment lighting, so objects are not lit from below as if standing on an endless plain. The ground stays visible in the sky itself',
1123
+ type: 'bool',
1124
+ phase: 1,
1125
+ default: true,
1126
+ get (value) {
1127
+ value.bool[0] = this.env.sky.lowerHemisphereIsBlack;
1128
+ },
1129
+ set (value) {
1130
+ this.env.sky.lowerHemisphereIsBlack = value.bool[0];
1131
+ },
1132
+ isValid () {
1133
+ return this.env.sky.skyType === 'scatter';
1134
+ }
1135
+ },
1136
+ {
1137
+ name: 'AtmosphereExposure',
1138
+ description: 'Exposure multiplier for atmospheric scattering and sky rendering',
1139
+ type: 'float',
1140
+ options: {
1141
+ animatable: true,
1142
+ minValue: 0,
1143
+ maxValue: 8
1144
+ },
1145
+ default: 1,
1146
+ get (value) {
1147
+ value.num[0] = this.env.sky.atmosphereExposure;
1148
+ },
1149
+ set (value) {
1150
+ this.env.sky.atmosphereExposure = value.num[0];
1151
+ },
1152
+ isValid () {
1153
+ return this.env.sky.skyType === 'scatter';
1154
+ }
1155
+ },
1156
+ {
1157
+ name: 'Cloudy',
1158
+ description: 'Cloud coverage amount for the procedural sky',
1159
+ type: 'float',
1160
+ default: 0.6,
1161
+ phase: 1,
1162
+ options: {
1163
+ animatable: true,
1164
+ minValue: 0,
1165
+ maxValue: 1
1166
+ },
1167
+ get (value) {
1168
+ value.num[0] = this.env.sky.cloudy;
1169
+ },
1170
+ set (value) {
1171
+ this.env.sky.cloudy = value.num[0];
1172
+ },
1173
+ isValid () {
1174
+ return this.env.sky.skyType === 'scatter';
1175
+ }
1176
+ },
1177
+ {
1178
+ name: 'CloudIntensity',
1179
+ description: 'Brightness of procedural clouds',
1180
+ type: 'float',
1181
+ default: 40,
1182
+ phase: 1,
1183
+ options: {
1184
+ animatable: true,
1185
+ minValue: 0,
1186
+ maxValue: 200
1187
+ },
1188
+ get (value) {
1189
+ value.num[0] = this.env.sky.cloudIntensity;
1190
+ },
1191
+ set (value) {
1192
+ this.env.sky.cloudIntensity = value.num[0];
1193
+ },
1194
+ isValid () {
1195
+ return this.env.sky.skyType === 'scatter';
1196
+ }
1197
+ },
1198
+ {
1199
+ name: 'CloudMode',
1200
+ description: 'Procedural draws a flat cloud layer; Volumetric draws lit 3D clouds (WebGPU only, falls back to Procedural elsewhere)',
1201
+ type: 'string',
1202
+ phase: 1,
1203
+ options: {
1204
+ enum: {
1205
+ labels: [
1206
+ 'Procedural',
1207
+ 'Volumetric'
1208
+ ],
1209
+ values: [
1210
+ 'procedural',
1211
+ 'volumetric'
1212
+ ]
1213
+ }
1214
+ },
1215
+ default: 'procedural',
1216
+ get (value) {
1217
+ value.str[0] = this.env.sky.cloudMode;
1218
+ },
1219
+ set (value) {
1220
+ this.env.sky.cloudMode = value.str[0];
1221
+ },
1222
+ isValid () {
1223
+ return this.env.sky.skyType === 'scatter';
1224
+ }
1225
+ },
1226
+ {
1227
+ name: 'VolumetricCloudLayerBottomAltitude',
1228
+ description: 'Raises the cloud base: higher clouds look smaller and farther away',
1229
+ type: 'float',
1230
+ default: 1500,
1231
+ phase: 2,
1232
+ options: {
1233
+ group: 'VolumetricClouds',
1234
+ label: 'LayerBottomAltitude',
1235
+ animatable: true,
1236
+ minValue: 0,
1237
+ maxValue: 20000
1238
+ },
1239
+ get (value) {
1240
+ value.num[0] = this.env.sky.volumetricCloud.layerBottomAltitude;
1241
+ },
1242
+ set (value) {
1243
+ this.env.sky.volumetricCloud.layerBottomAltitude = value.num[0];
1244
+ },
1245
+ isValid () {
1246
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1247
+ }
1248
+ },
1249
+ {
1250
+ name: 'VolumetricCloudLayerHeight',
1251
+ description: 'Lets clouds tower higher above their base',
1252
+ type: 'float',
1253
+ default: 4000,
1254
+ phase: 2,
1255
+ options: {
1256
+ group: 'VolumetricClouds',
1257
+ label: 'LayerHeight',
1258
+ animatable: true,
1259
+ minValue: 100,
1260
+ maxValue: 20000
1261
+ },
1262
+ get (value) {
1263
+ value.num[0] = this.env.sky.volumetricCloud.layerHeight;
1264
+ },
1265
+ set (value) {
1266
+ this.env.sky.volumetricCloud.layerHeight = value.num[0];
1267
+ },
1268
+ isValid () {
1269
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1270
+ }
1271
+ },
1272
+ {
1273
+ name: 'VolumetricCloudBaseHeightVariation',
1274
+ description: 'Maximum local rise of cloud undersides above the layer base, in meters',
1275
+ type: 'float',
1276
+ default: 700,
1277
+ phase: 2,
1278
+ options: {
1279
+ group: 'VolumetricClouds',
1280
+ label: 'BaseHeightVariation',
1281
+ animatable: true,
1282
+ minValue: 0,
1283
+ maxValue: 2000
1284
+ },
1285
+ get (value) {
1286
+ value.num[0] = this.env.sky.volumetricCloud.baseHeightVariation;
1287
+ },
1288
+ set (value) {
1289
+ this.env.sky.volumetricCloud.baseHeightVariation = value.num[0];
1290
+ },
1291
+ isValid () {
1292
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1293
+ }
1294
+ },
1295
+ {
1296
+ name: 'VolumetricCloudCoverage',
1297
+ description: 'Weather coverage: higher grows cloud fields; zero removes all clouds',
1298
+ type: 'float',
1299
+ default: 0.55,
1300
+ phase: 2,
1301
+ options: {
1302
+ group: 'VolumetricClouds',
1303
+ label: 'Coverage',
1304
+ animatable: true,
1305
+ minValue: 0,
1306
+ maxValue: 1
1307
+ },
1308
+ get (value) {
1309
+ value.num[0] = this.env.sky.volumetricCloud.coverage;
1310
+ },
1311
+ set (value) {
1312
+ this.env.sky.volumetricCloud.coverage = value.num[0];
1313
+ },
1314
+ isValid () {
1315
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1316
+ }
1317
+ },
1318
+ {
1319
+ name: 'VolumetricCloudDensity',
1320
+ description: 'Makes clouds more opaque and their shadowed sides darker',
1321
+ type: 'float',
1322
+ default: 0.03,
1323
+ phase: 2,
1324
+ options: {
1325
+ group: 'VolumetricClouds',
1326
+ label: 'Density',
1327
+ animatable: true,
1328
+ minValue: 0,
1329
+ maxValue: 0.5
1330
+ },
1331
+ get (value) {
1332
+ value.num[0] = this.env.sky.volumetricCloud.density;
1333
+ },
1334
+ set (value) {
1335
+ this.env.sky.volumetricCloud.density = value.num[0];
1336
+ },
1337
+ isValid () {
1338
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1339
+ }
1340
+ },
1341
+ {
1342
+ name: 'VolumetricCloudWeatherMapScale',
1343
+ description: 'Spreads cloud fields wider apart; lower packs more, smaller cloud fields into the sky',
1344
+ type: 'float',
1345
+ default: 64000,
1346
+ phase: 2,
1347
+ options: {
1348
+ group: 'VolumetricClouds',
1349
+ label: 'WeatherMapScale',
1350
+ animatable: true,
1351
+ minValue: 1000,
1352
+ maxValue: 500000
1353
+ },
1354
+ get (value) {
1355
+ value.num[0] = this.env.sky.volumetricCloud.weatherMapScale;
1356
+ },
1357
+ set (value) {
1358
+ this.env.sky.volumetricCloud.weatherMapScale = value.num[0];
1359
+ },
1360
+ isValid () {
1361
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1362
+ }
1363
+ },
1364
+ {
1365
+ name: 'VolumetricCloudBaseNoiseScale',
1366
+ description: 'Size of the large billows that shape each cloud',
1367
+ type: 'float',
1368
+ default: 8000,
1369
+ phase: 2,
1370
+ options: {
1371
+ group: 'VolumetricClouds',
1372
+ label: 'BaseNoiseScale',
1373
+ animatable: true,
1374
+ minValue: 100,
1375
+ maxValue: 100000
1376
+ },
1377
+ get (value) {
1378
+ value.num[0] = this.env.sky.volumetricCloud.baseNoiseScale;
1379
+ },
1380
+ set (value) {
1381
+ this.env.sky.volumetricCloud.baseNoiseScale = value.num[0];
1382
+ },
1383
+ isValid () {
1384
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1385
+ }
1386
+ },
1387
+ {
1388
+ name: 'VolumetricCloudShapeStrength',
1389
+ description: 'Strength of the large noise billows; lower keeps cloud bodies fuller and more connected',
1390
+ type: 'float',
1391
+ default: 1,
1392
+ phase: 2,
1393
+ options: {
1394
+ group: 'VolumetricClouds',
1395
+ label: 'ShapeStrength',
1396
+ animatable: true,
1397
+ minValue: 0,
1398
+ maxValue: 1
1399
+ },
1400
+ get (value) {
1401
+ value.num[0] = this.env.sky.volumetricCloud.shapeStrength;
1402
+ },
1403
+ set (value) {
1404
+ this.env.sky.volumetricCloud.shapeStrength = value.num[0];
1405
+ },
1406
+ isValid () {
1407
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1408
+ }
1409
+ },
1410
+ {
1411
+ name: 'VolumetricCloudDetailNoiseScale',
1412
+ description: 'Size of the small wisps along cloud edges',
1413
+ type: 'float',
1414
+ default: 600,
1415
+ phase: 2,
1416
+ options: {
1417
+ group: 'VolumetricClouds',
1418
+ label: 'DetailNoiseScale',
1419
+ animatable: true,
1420
+ minValue: 10,
1421
+ maxValue: 10000
1422
+ },
1423
+ get (value) {
1424
+ value.num[0] = this.env.sky.volumetricCloud.detailNoiseScale;
1425
+ },
1426
+ set (value) {
1427
+ this.env.sky.volumetricCloud.detailNoiseScale = value.num[0];
1428
+ },
1429
+ isValid () {
1430
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1431
+ }
1432
+ },
1433
+ {
1434
+ name: 'VolumetricCloudFormation',
1435
+ description: 'Isolated: separate island-like clouds with persistent gaps. Connected: cloud fields that merge as Coverage rises',
1436
+ type: 'string',
1437
+ default: 'isolated',
1438
+ phase: 2,
1439
+ options: {
1440
+ group: 'VolumetricClouds',
1441
+ label: 'Formation',
1442
+ enum: {
1443
+ labels: [
1444
+ 'Isolated',
1445
+ 'Connected'
1446
+ ],
1447
+ values: [
1448
+ 'isolated',
1449
+ 'connected'
1450
+ ]
1451
+ }
1452
+ },
1453
+ get (value) {
1454
+ value.str[0] = this.env.sky.volumetricCloud.formation;
1455
+ },
1456
+ set (value) {
1457
+ this.env.sky.volumetricCloud.formation = value.str[0];
1458
+ },
1459
+ isValid () {
1460
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1461
+ }
1462
+ },
1463
+ {
1464
+ name: 'VolumetricCloudAnvilBias',
1465
+ description: 'Spreads the tops of tall clouds out into anvils',
1466
+ type: 'float',
1467
+ default: 0,
1468
+ phase: 2,
1469
+ options: {
1470
+ group: 'VolumetricClouds',
1471
+ label: 'AnvilBias',
1472
+ animatable: true,
1473
+ minValue: 0,
1474
+ maxValue: 1
1475
+ },
1476
+ get (value) {
1477
+ value.num[0] = this.env.sky.volumetricCloud.anvilBias;
1478
+ },
1479
+ set (value) {
1480
+ this.env.sky.volumetricCloud.anvilBias = value.num[0];
1481
+ },
1482
+ isValid () {
1483
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1484
+ }
1485
+ },
1486
+ {
1487
+ name: 'VolumetricCloudDetailErosion',
1488
+ description: 'Higher gives raggeder, wispier cloud edges',
1489
+ type: 'float',
1490
+ default: 0.35,
1491
+ phase: 2,
1492
+ options: {
1493
+ group: 'VolumetricClouds',
1494
+ label: 'DetailErosion',
1495
+ animatable: true,
1496
+ minValue: 0,
1497
+ maxValue: 1
1498
+ },
1499
+ get (value) {
1500
+ value.num[0] = this.env.sky.volumetricCloud.detailErosion;
1501
+ },
1502
+ set (value) {
1503
+ this.env.sky.volumetricCloud.detailErosion = value.num[0];
1504
+ },
1505
+ isValid () {
1506
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1507
+ }
1508
+ },
1509
+ {
1510
+ name: 'VolumetricCloudDetailBottomErosion',
1511
+ description: 'Detail erosion at the cloud base relative to the full amount; lower keeps the base flatter',
1512
+ type: 'float',
1513
+ default: 0.1,
1514
+ phase: 2,
1515
+ options: {
1516
+ group: 'VolumetricClouds',
1517
+ label: 'DetailBottomErosion',
1518
+ animatable: true,
1519
+ minValue: 0,
1520
+ maxValue: 1
1521
+ },
1522
+ get (value) {
1523
+ value.num[0] = this.env.sky.volumetricCloud.detailBottomErosion;
1524
+ },
1525
+ set (value) {
1526
+ this.env.sky.volumetricCloud.detailBottomErosion = value.num[0];
1527
+ },
1528
+ isValid () {
1529
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1530
+ }
1531
+ },
1532
+ {
1533
+ name: 'VolumetricCloudPhaseG',
1534
+ description: 'Tightens and brightens the silver lining around the sun',
1535
+ type: 'float',
1536
+ default: 0.8,
1537
+ phase: 2,
1538
+ options: {
1539
+ group: 'VolumetricClouds',
1540
+ label: 'PhaseG',
1541
+ animatable: true,
1542
+ minValue: -0.999,
1543
+ maxValue: 0.999
1544
+ },
1545
+ get (value) {
1546
+ value.num[0] = this.env.sky.volumetricCloud.phaseG;
1547
+ },
1548
+ set (value) {
1549
+ this.env.sky.volumetricCloud.phaseG = value.num[0];
1550
+ },
1551
+ isValid () {
1552
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1553
+ }
1554
+ },
1555
+ {
1556
+ name: 'VolumetricCloudPhaseG2',
1557
+ description: 'Negative values brighten clouds when looking away from the sun',
1558
+ type: 'float',
1559
+ default: -0.3,
1560
+ phase: 2,
1561
+ options: {
1562
+ group: 'VolumetricClouds',
1563
+ label: 'PhaseG2',
1564
+ animatable: true,
1565
+ minValue: -0.999,
1566
+ maxValue: 0.999
1567
+ },
1568
+ get (value) {
1569
+ value.num[0] = this.env.sky.volumetricCloud.phaseG2;
1570
+ },
1571
+ set (value) {
1572
+ this.env.sky.volumetricCloud.phaseG2 = value.num[0];
1573
+ },
1574
+ isValid () {
1575
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1576
+ }
1577
+ },
1578
+ {
1579
+ name: 'VolumetricCloudPhaseBlend',
1580
+ description: 'Moves the look from the sun-facing lobe (0) to the second lobe (1)',
1581
+ type: 'float',
1582
+ default: 0.5,
1583
+ phase: 2,
1584
+ options: {
1585
+ group: 'VolumetricClouds',
1586
+ label: 'PhaseBlend',
1587
+ animatable: true,
1588
+ minValue: 0,
1589
+ maxValue: 1
1590
+ },
1591
+ get (value) {
1592
+ value.num[0] = this.env.sky.volumetricCloud.phaseBlend;
1593
+ },
1594
+ set (value) {
1595
+ this.env.sky.volumetricCloud.phaseBlend = value.num[0];
1596
+ },
1597
+ isValid () {
1598
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1599
+ }
1600
+ },
1601
+ {
1602
+ name: 'VolumetricCloudMultiScatteringOctaves',
1603
+ description: 'More bounces make thick clouds glow brighter and softer',
1604
+ type: 'int',
1605
+ default: 2,
1606
+ phase: 2,
1607
+ options: {
1608
+ group: 'VolumetricClouds',
1609
+ label: 'MultiScatteringOctaves',
1610
+ animatable: true,
1611
+ minValue: 0,
1612
+ maxValue: 2
1613
+ },
1614
+ get (value) {
1615
+ value.num[0] = this.env.sky.volumetricCloud.msOctaves;
1616
+ },
1617
+ set (value) {
1618
+ this.env.sky.volumetricCloud.msOctaves = value.num[0];
1619
+ },
1620
+ isValid () {
1621
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1622
+ }
1623
+ },
1624
+ {
1625
+ name: 'VolumetricCloudMultiScatteringContribution',
1626
+ description: 'Brightness of the bounced light inside clouds',
1627
+ type: 'float',
1628
+ default: 0.5,
1629
+ phase: 2,
1630
+ options: {
1631
+ group: 'VolumetricClouds',
1632
+ label: 'MultiScatteringContribution',
1633
+ animatable: true,
1634
+ minValue: 0,
1635
+ maxValue: 1
1636
+ },
1637
+ get (value) {
1638
+ value.num[0] = this.env.sky.volumetricCloud.msContribution;
1639
+ },
1640
+ set (value) {
1641
+ this.env.sky.volumetricCloud.msContribution = value.num[0];
1642
+ },
1643
+ isValid () {
1644
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1645
+ }
1646
+ },
1647
+ {
1648
+ name: 'VolumetricCloudMultiScatteringOcclusion',
1649
+ description: 'Lower lets bounced light reach deeper into thick clouds',
1650
+ type: 'float',
1651
+ default: 0.5,
1652
+ phase: 2,
1653
+ options: {
1654
+ group: 'VolumetricClouds',
1655
+ label: 'MultiScatteringOcclusion',
1656
+ animatable: true,
1657
+ minValue: 0,
1658
+ maxValue: 1
1659
+ },
1660
+ get (value) {
1661
+ value.num[0] = this.env.sky.volumetricCloud.msOcclusion;
1662
+ },
1663
+ set (value) {
1664
+ this.env.sky.volumetricCloud.msOcclusion = value.num[0];
1665
+ },
1666
+ isValid () {
1667
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1668
+ }
1669
+ },
1670
+ {
1671
+ name: 'VolumetricCloudMultiScatteringEccentricity',
1672
+ description: 'Lower spreads bounced light evenly instead of around the sun',
1673
+ type: 'float',
1674
+ default: 0.5,
1675
+ phase: 2,
1676
+ options: {
1677
+ group: 'VolumetricClouds',
1678
+ label: 'MultiScatteringEccentricity',
1679
+ animatable: true,
1680
+ minValue: 0,
1681
+ maxValue: 1
1682
+ },
1683
+ get (value) {
1684
+ value.num[0] = this.env.sky.volumetricCloud.msEccentricity;
1685
+ },
1686
+ set (value) {
1687
+ this.env.sky.volumetricCloud.msEccentricity = value.num[0];
1688
+ },
1689
+ isValid () {
1690
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1691
+ }
1692
+ },
1693
+ {
1694
+ name: 'VolumetricCloudGroundAlbedo',
1695
+ description: 'Brightens cloud undersides with light bounced off the ground',
1696
+ type: 'float',
1697
+ default: 0.4,
1698
+ phase: 2,
1699
+ options: {
1700
+ group: 'VolumetricClouds',
1701
+ label: 'GroundAlbedo',
1702
+ animatable: true,
1703
+ minValue: 0,
1704
+ maxValue: 1
1705
+ },
1706
+ get (value) {
1707
+ value.num[0] = this.env.sky.volumetricCloud.groundAlbedo;
1708
+ },
1709
+ set (value) {
1710
+ this.env.sky.volumetricCloud.groundAlbedo = value.num[0];
1711
+ },
1712
+ isValid () {
1713
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1714
+ }
1715
+ },
1716
+ {
1717
+ name: 'VolumetricCloudSkyLightBottomOcclusion',
1718
+ description: 'Darkens the sky light on cloud undersides',
1719
+ type: 'float',
1720
+ default: 0.5,
1721
+ phase: 2,
1722
+ options: {
1723
+ group: 'VolumetricClouds',
1724
+ label: 'SkyLightBottomOcclusion',
1725
+ animatable: true,
1726
+ minValue: 0,
1727
+ maxValue: 1
1728
+ },
1729
+ get (value) {
1730
+ value.num[0] = this.env.sky.volumetricCloud.skyLightCloudBottomOcclusion;
1731
+ },
1732
+ set (value) {
1733
+ this.env.sky.volumetricCloud.skyLightCloudBottomOcclusion = value.num[0];
1734
+ },
1735
+ isValid () {
1736
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1737
+ }
1738
+ },
1739
+ {
1740
+ name: 'VolumetricCloudTracingMaxDistance',
1741
+ description: 'How far into the layer clouds are still drawn; lower drops distant clouds',
1742
+ type: 'float',
1743
+ default: 50000,
1744
+ phase: 2,
1745
+ options: {
1746
+ group: 'VolumetricClouds',
1747
+ label: 'TracingMaxDistance',
1748
+ animatable: true,
1749
+ minValue: 1000,
1750
+ maxValue: 500000
1751
+ },
1752
+ get (value) {
1753
+ value.num[0] = this.env.sky.volumetricCloud.tracingMaxDistance;
1754
+ },
1755
+ set (value) {
1756
+ this.env.sky.volumetricCloud.tracingMaxDistance = value.num[0];
1757
+ },
1758
+ isValid () {
1759
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1760
+ }
1761
+ },
1762
+ {
1763
+ name: 'VolumetricCloudViewSampleCountScale',
1764
+ description: 'Finer cloud detail at a higher cost',
1765
+ type: 'float',
1766
+ default: 2,
1767
+ phase: 2,
1768
+ options: {
1769
+ group: 'VolumetricClouds',
1770
+ label: 'ViewSampleCountScale',
1771
+ animatable: true,
1772
+ minValue: 0.05,
1773
+ maxValue: 8
1774
+ },
1775
+ get (value) {
1776
+ value.num[0] = this.env.sky.volumetricCloud.viewSampleCountScale;
1777
+ },
1778
+ set (value) {
1779
+ this.env.sky.volumetricCloud.viewSampleCountScale = value.num[0];
1780
+ },
1781
+ isValid () {
1782
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1783
+ }
1784
+ },
1785
+ {
1786
+ name: 'VolumetricCloudShadowSampleCountScale',
1787
+ description: 'Smoother self-shadowing inside clouds at a higher cost',
1788
+ type: 'float',
1789
+ default: 1,
1790
+ phase: 2,
1791
+ options: {
1792
+ group: 'VolumetricClouds',
1793
+ label: 'ShadowSampleCountScale',
1794
+ animatable: true,
1795
+ minValue: 0.05,
1796
+ maxValue: 8
1797
+ },
1798
+ get (value) {
1799
+ value.num[0] = this.env.sky.volumetricCloud.shadowSampleCountScale;
1800
+ },
1801
+ set (value) {
1802
+ this.env.sky.volumetricCloud.shadowSampleCountScale = value.num[0];
1803
+ },
1804
+ isValid () {
1805
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1806
+ }
1807
+ },
1808
+ {
1809
+ name: 'VolumetricCloudShadowTracingDistance',
1810
+ description: 'How far towards the sun clouds look for cloud that shades them',
1811
+ type: 'float',
1812
+ default: 8000,
1813
+ phase: 2,
1814
+ options: {
1815
+ group: 'VolumetricClouds',
1816
+ label: 'ShadowTracingDistance',
1817
+ animatable: true,
1818
+ minValue: 100,
1819
+ maxValue: 50000
1820
+ },
1821
+ get (value) {
1822
+ value.num[0] = this.env.sky.volumetricCloud.shadowTracingDistance;
1823
+ },
1824
+ set (value) {
1825
+ this.env.sky.volumetricCloud.shadowTracingDistance = value.num[0];
1826
+ },
1827
+ isValid () {
1828
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1829
+ }
1830
+ },
1831
+ {
1832
+ name: 'VolumetricCloudStopTracingTransmittance',
1833
+ description: 'Lower is slightly more exact behind dense clouds but slower',
1834
+ type: 'float',
1835
+ default: 0.005,
1836
+ phase: 2,
1837
+ options: {
1838
+ group: 'VolumetricClouds',
1839
+ label: 'StopTracingTransmittance',
1840
+ animatable: true,
1841
+ minValue: 0,
1842
+ maxValue: 1
1843
+ },
1844
+ get (value) {
1845
+ value.num[0] = this.env.sky.volumetricCloud.stopTracingTransmittanceThreshold;
1846
+ },
1847
+ set (value) {
1848
+ this.env.sky.volumetricCloud.stopTracingTransmittanceThreshold = value.num[0];
1849
+ },
1850
+ isValid () {
1851
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1852
+ }
1853
+ },
1854
+ {
1855
+ name: 'VolumetricCloudNoiseSeed',
1856
+ description: 'Picks a different generated cloud pattern',
1857
+ type: 'int',
1858
+ default: 0,
1859
+ phase: 2,
1860
+ options: {
1861
+ group: 'VolumetricClouds',
1862
+ label: 'NoiseSeed',
1863
+ animatable: true,
1864
+ minValue: 0,
1865
+ maxValue: 1000
1866
+ },
1867
+ get (value) {
1868
+ value.num[0] = this.env.sky.volumetricCloud.noiseSeed;
1869
+ },
1870
+ set (value) {
1871
+ this.env.sky.volumetricCloud.noiseSeed = value.num[0];
1872
+ },
1873
+ isValid () {
1874
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1875
+ }
1876
+ },
1877
+ {
1878
+ name: 'VolumetricCloudFramesPerUpdate',
1879
+ description: 'Fewer frames let clouds and sunlight change faster but cost more per frame',
1880
+ type: 'int',
1881
+ default: 64,
1882
+ phase: 2,
1883
+ options: {
1884
+ group: 'VolumetricClouds',
1885
+ label: 'FramesPerUpdate',
1886
+ animatable: true,
1887
+ minValue: 4,
1888
+ maxValue: 256
1889
+ },
1890
+ get (value) {
1891
+ value.num[0] = this.env.sky.volumetricCloud.framesPerUpdate;
1892
+ },
1893
+ set (value) {
1894
+ this.env.sky.volumetricCloud.framesPerUpdate = value.num[0];
1895
+ },
1896
+ isValid () {
1897
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1898
+ }
1899
+ },
1900
+ {
1901
+ name: 'VolumetricCloudCacheResolution',
1902
+ description: 'Keeps clouds sharp at narrow fields of view at a higher memory cost',
1903
+ type: 'int',
1904
+ default: 768,
1905
+ phase: 2,
1906
+ options: {
1907
+ group: 'VolumetricClouds',
1908
+ label: 'CacheResolution',
1909
+ animatable: true,
1910
+ minValue: 128,
1911
+ maxValue: 2048
1912
+ },
1913
+ get (value) {
1914
+ value.num[0] = this.env.sky.volumetricCloud.cacheResolution;
1915
+ },
1916
+ set (value) {
1917
+ this.env.sky.volumetricCloud.cacheResolution = value.num[0];
1918
+ },
1919
+ isValid () {
1920
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1921
+ }
1922
+ },
1923
+ {
1924
+ name: 'VolumetricCloudPerSampleSunTransmittance',
1925
+ description: 'Reddens the sunlight inside clouds by the air between each point and the sun; matters most at sunrise and sunset',
1926
+ type: 'bool',
1927
+ default: false,
1928
+ phase: 2,
1929
+ options: {
1930
+ group: 'VolumetricClouds',
1931
+ label: 'PerSampleSunTransmittance'
1932
+ },
1933
+ get (value) {
1934
+ value.bool[0] = this.env.sky.volumetricCloud.perSampleAtmosphericLightTransmittance;
1935
+ },
1936
+ set (value) {
1937
+ this.env.sky.volumetricCloud.perSampleAtmosphericLightTransmittance = value.bool[0];
1938
+ },
1939
+ isValid () {
1940
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1941
+ }
1942
+ },
1943
+ {
1944
+ name: 'VolumetricCloudAlbedo',
1945
+ description: 'Tint of the light clouds scatter; lower values make clouds greyer',
1946
+ type: 'rgb',
1947
+ default: [
1948
+ 1,
1949
+ 1,
1950
+ 1
1951
+ ],
1952
+ phase: 2,
1953
+ options: {
1954
+ group: 'VolumetricClouds',
1955
+ label: 'Albedo',
1956
+ animatable: true
1957
+ },
1958
+ get (value) {
1959
+ const c = this.env.sky.volumetricCloud.albedo;
1960
+ value.num[0] = c.x;
1961
+ value.num[1] = c.y;
1962
+ value.num[2] = c.z;
1963
+ },
1964
+ set (value) {
1965
+ this.env.sky.volumetricCloud.albedo = new Vector3(value.num[0], value.num[1], value.num[2]);
1966
+ },
1967
+ isValid () {
1968
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1969
+ }
1970
+ },
1971
+ {
1972
+ name: 'VolumetricCloudWind',
1973
+ description: 'Direction and speed the clouds drift with, in meters per second',
1974
+ type: 'vec2',
1975
+ default: [
1976
+ 10,
1977
+ 0
1978
+ ],
1979
+ phase: 2,
1980
+ options: {
1981
+ group: 'VolumetricClouds',
1982
+ label: 'Wind',
1983
+ animatable: true,
1984
+ minValue: -100,
1985
+ maxValue: 100
1986
+ },
1987
+ get (value) {
1988
+ const w = this.env.sky.volumetricCloud.wind;
1989
+ value.num[0] = w.x;
1990
+ value.num[1] = w.y;
1991
+ },
1992
+ set (value) {
1993
+ this.env.sky.volumetricCloud.wind = new Vector2(value.num[0], value.num[1]);
1994
+ },
1995
+ isValid () {
1996
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
1997
+ }
1998
+ },
1999
+ {
2000
+ name: 'VolumetricCloudWeatherMap',
2001
+ description: 'Where clouds form: R Connected footprints, G Isolated footprints (higher values fill first as Coverage rises), B cloud type (0 stratus to 1 cumulus). Empty generates one',
2002
+ type: 'object',
2003
+ default: null,
2004
+ phase: 2,
2005
+ options: {
2006
+ group: 'VolumetricClouds',
2007
+ label: 'WeatherMap',
2008
+ mimeTypes: [
2009
+ 'image/png',
2010
+ 'image/tga',
2011
+ 'image/webp',
2012
+ 'image/ktx2',
2013
+ 'image/x-dds'
2014
+ ]
2015
+ },
2016
+ isNullable () {
2017
+ return true;
2018
+ },
2019
+ get (value) {
2020
+ value.str[0] = manager.getAssetId(this.env.sky.cloudWeatherMap) ?? '';
2021
+ },
2022
+ async set (value) {
2023
+ if (!value || !value.str[0]) {
2024
+ this.env.sky.cloudWeatherMap = null;
2025
+ return;
2026
+ }
2027
+ let tex = null;
2028
+ try {
2029
+ // Data, not color: no sRGB decoding
2030
+ tex = await manager.fetchTexture(value.str[0], {
2031
+ linearColorSpace: true
2032
+ });
2033
+ } catch (err) {
2034
+ console.error(`Load asset failed: ${value.str[0]}: ${err}`);
2035
+ }
2036
+ if (tex?.isTexture2D()) {
2037
+ this.env.sky.cloudWeatherMap = tex;
2038
+ } else {
2039
+ console.error('Invalid texture type');
2040
+ }
2041
+ },
2042
+ isValid () {
2043
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2044
+ }
2045
+ },
2046
+ {
2047
+ name: 'VolumetricCloudBaseNoise',
2048
+ description: 'Shape of the large billows, as a 2D atlas of the slices of a cubic volume (e.g. 128^3 as 2048x1024). Empty generates one',
2049
+ type: 'object',
2050
+ default: null,
2051
+ phase: 2,
2052
+ options: {
2053
+ group: 'VolumetricClouds',
2054
+ label: 'BaseNoise',
2055
+ mimeTypes: [
2056
+ 'image/png',
2057
+ 'image/tga',
2058
+ 'image/webp',
2059
+ 'image/ktx2',
2060
+ 'image/x-dds'
2061
+ ]
2062
+ },
2063
+ isNullable () {
2064
+ return true;
2065
+ },
2066
+ get (value) {
2067
+ value.str[0] = manager.getAssetId(this.env.sky.cloudBaseNoise) ?? '';
2068
+ },
2069
+ async set (value) {
2070
+ if (!value || !value.str[0]) {
2071
+ this.env.sky.cloudBaseNoise = null;
2072
+ return;
2073
+ }
2074
+ let tex = null;
2075
+ try {
2076
+ // Data, not color: no sRGB decoding
2077
+ tex = await manager.fetchTexture(value.str[0], {
2078
+ linearColorSpace: true
2079
+ });
2080
+ } catch (err) {
2081
+ console.error(`Load asset failed: ${value.str[0]}: ${err}`);
2082
+ }
2083
+ if (tex?.isTexture2D()) {
2084
+ this.env.sky.cloudBaseNoise = tex;
2085
+ } else {
2086
+ console.error('Invalid texture type');
2087
+ }
2088
+ },
2089
+ isValid () {
2090
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2091
+ }
2092
+ },
2093
+ {
2094
+ name: 'VolumetricCloudDetailNoise',
2095
+ description: 'Shape of the small edge wisps, as a 2D atlas of the slices of a cubic volume (e.g. 32^3 as 256x128). Empty generates one',
2096
+ type: 'object',
2097
+ default: null,
2098
+ phase: 2,
2099
+ options: {
2100
+ group: 'VolumetricClouds',
2101
+ label: 'DetailNoise',
2102
+ mimeTypes: [
2103
+ 'image/png',
2104
+ 'image/tga',
2105
+ 'image/webp',
2106
+ 'image/ktx2',
2107
+ 'image/x-dds'
2108
+ ]
2109
+ },
2110
+ isNullable () {
2111
+ return true;
2112
+ },
2113
+ get (value) {
2114
+ value.str[0] = manager.getAssetId(this.env.sky.cloudDetailNoise) ?? '';
2115
+ },
2116
+ async set (value) {
2117
+ if (!value || !value.str[0]) {
2118
+ this.env.sky.cloudDetailNoise = null;
2119
+ return;
2120
+ }
2121
+ let tex = null;
2122
+ try {
2123
+ // Data, not color: no sRGB decoding
2124
+ tex = await manager.fetchTexture(value.str[0], {
2125
+ linearColorSpace: true
2126
+ });
2127
+ } catch (err) {
2128
+ console.error(`Load asset failed: ${value.str[0]}: ${err}`);
2129
+ }
2130
+ if (tex?.isTexture2D()) {
2131
+ this.env.sky.cloudDetailNoise = tex;
2132
+ } else {
2133
+ console.error('Invalid texture type');
2134
+ }
2135
+ },
2136
+ isValid () {
2137
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2138
+ }
2139
+ },
2140
+ {
2141
+ name: 'VolumetricCloudDebugView',
2142
+ description: 'Shows a cloud resource, height profile or density section over the sky for inspection',
2143
+ type: 'string',
2144
+ default: 'none',
2145
+ phase: 2,
2146
+ options: {
2147
+ group: 'VolumetricClouds',
2148
+ label: 'DebugView',
2149
+ enum: {
2150
+ labels: [
2151
+ 'None',
2152
+ 'WeatherMap',
2153
+ 'BaseNoise',
2154
+ 'DetailNoise',
2155
+ 'HeightProfileXY',
2156
+ 'HeightProfileXZ',
2157
+ 'BaseDensityXY',
2158
+ 'BaseDensityXZ',
2159
+ 'DensityXY',
2160
+ 'DensityXZ'
2161
+ ],
2162
+ values: [
2163
+ 'none',
2164
+ 'weather',
2165
+ 'baseNoise',
2166
+ 'detailNoise',
2167
+ 'profileXY',
2168
+ 'profileXZ',
2169
+ 'baseDensityXY',
2170
+ 'baseDensityXZ',
2171
+ 'densityXY',
2172
+ 'densityXZ'
2173
+ ]
2174
+ }
2175
+ },
2176
+ get (value) {
2177
+ value.str[0] = this.env.sky.cloudDebugView;
2178
+ },
2179
+ set (value) {
2180
+ this.env.sky.cloudDebugView = value.str[0];
2181
+ },
2182
+ isValid () {
2183
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2184
+ }
2185
+ },
2186
+ {
2187
+ name: 'VolumetricCloudDebugSlice',
2188
+ description: 'Noise slice depth, normalized Z of XY sections, or normalized layer height of XZ sections',
2189
+ type: 'float',
2190
+ default: 0,
2191
+ phase: 2,
2192
+ options: {
2193
+ group: 'VolumetricClouds',
2194
+ label: 'DebugSlice',
2195
+ minValue: 0,
2196
+ maxValue: 1
2197
+ },
2198
+ get (value) {
2199
+ value.num[0] = this.env.sky.cloudDebugSlice;
2200
+ },
2201
+ set (value) {
2202
+ this.env.sky.cloudDebugSlice = value.num[0];
2203
+ },
2204
+ isValid () {
2205
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2206
+ }
2207
+ },
2208
+ {
2209
+ name: 'VolumetricCloudDebugChannel',
2210
+ description: 'Channel shown by DebugView: 0 color, 1-4 R, G, B or A as grey',
2211
+ type: 'int',
2212
+ default: 0,
2213
+ phase: 2,
2214
+ options: {
2215
+ group: 'VolumetricClouds',
2216
+ label: 'DebugChannel',
2217
+ minValue: 0,
2218
+ maxValue: 4
2219
+ },
2220
+ get (value) {
2221
+ value.num[0] = this.env.sky.cloudDebugChannel;
2222
+ },
2223
+ set (value) {
2224
+ this.env.sky.cloudDebugChannel = value.num[0];
2225
+ },
2226
+ isValid () {
2227
+ return this.env.sky.skyType === 'scatter' && this.env.sky.cloudMode === 'volumetric';
2228
+ }
2229
+ },
2230
+ {
2231
+ name: 'Wind',
2232
+ description: 'Wind direction and speed used by the procedural sky',
2233
+ type: 'vec2',
2234
+ default: [
2235
+ 0,
2236
+ 0
2237
+ ],
2238
+ phase: 1,
2239
+ options: {
2240
+ animatable: true,
2241
+ minValue: -100,
2242
+ maxValue: 100
2243
+ },
2244
+ get (value) {
2245
+ value.num[0] = this.env.sky.wind.x;
2246
+ value.num[1] = this.env.sky.wind.y;
2247
+ },
2248
+ set (value) {
2249
+ this.env.sky.wind.setXY(value.num[0], value.num[1]);
2250
+ },
2251
+ isValid () {
2252
+ return this.env.sky.skyType === 'scatter';
2253
+ }
2254
+ },
2255
+ {
2256
+ name: 'SkyBoxRotation',
2257
+ description: 'Euler rotation of the skybox',
2258
+ type: 'vec3',
2259
+ default: [
2260
+ 0,
2261
+ 0,
2262
+ 0
2263
+ ],
2264
+ phase: 1,
783
2265
  options: {
784
2266
  label: 'Rotation',
785
2267
  edit: 'quaternion',
@@ -832,6 +2314,139 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
832
2314
  return this.env.sky.skyType === 'skybox';
833
2315
  }
834
2316
  },
2317
+ {
2318
+ name: 'WindFieldDirection',
2319
+ description: 'Compass direction the wind blows toward, in degrees. Grass leans and gusts travel this way',
2320
+ type: 'float',
2321
+ default: 0,
2322
+ options: {
2323
+ group: 'Wind',
2324
+ label: 'Direction',
2325
+ animatable: true,
2326
+ minValue: -180,
2327
+ maxValue: 180
2328
+ },
2329
+ get (value) {
2330
+ value.num[0] = this.env.wind.direction;
2331
+ },
2332
+ set (value) {
2333
+ this.env.wind.direction = value.num[0];
2334
+ }
2335
+ },
2336
+ {
2337
+ name: 'WindFieldStrength',
2338
+ description: 'How hard the wind blows. 0 is still air; higher values bend grass further over',
2339
+ type: 'float',
2340
+ default: 0.3,
2341
+ options: {
2342
+ group: 'Wind',
2343
+ label: 'Strength',
2344
+ animatable: true,
2345
+ minValue: 0,
2346
+ maxValue: 2
2347
+ },
2348
+ get (value) {
2349
+ value.num[0] = this.env.wind.strength;
2350
+ },
2351
+ set (value) {
2352
+ this.env.wind.strength = value.num[0];
2353
+ }
2354
+ },
2355
+ {
2356
+ name: 'WindFieldSpeed',
2357
+ description: 'How fast the gusts sweep across the ground, in units per second',
2358
+ type: 'float',
2359
+ default: 4,
2360
+ options: {
2361
+ group: 'Wind',
2362
+ label: 'GustSpeed',
2363
+ animatable: true,
2364
+ minValue: 0,
2365
+ maxValue: 50
2366
+ },
2367
+ get (value) {
2368
+ value.num[0] = this.env.wind.speed;
2369
+ },
2370
+ set (value) {
2371
+ this.env.wind.speed = value.num[0];
2372
+ }
2373
+ },
2374
+ {
2375
+ name: 'WindFieldGustStrength',
2376
+ description: 'How strongly gusts come and go. 0 gives a steady wind; higher values make waves of stronger wind roll through fields',
2377
+ type: 'float',
2378
+ default: 0.6,
2379
+ options: {
2380
+ group: 'Wind',
2381
+ label: 'GustStrength',
2382
+ animatable: true,
2383
+ minValue: 0,
2384
+ maxValue: 2
2385
+ },
2386
+ get (value) {
2387
+ value.num[0] = this.env.wind.gustStrength;
2388
+ },
2389
+ set (value) {
2390
+ this.env.wind.gustStrength = value.num[0];
2391
+ }
2392
+ },
2393
+ {
2394
+ name: 'WindFieldGustScale',
2395
+ description: 'Size of a gust on the ground, in units. Larger values give broad, slow-looking waves',
2396
+ type: 'float',
2397
+ default: 30,
2398
+ options: {
2399
+ group: 'Wind',
2400
+ label: 'GustSize',
2401
+ animatable: true,
2402
+ minValue: 0.1,
2403
+ maxValue: 500
2404
+ },
2405
+ get (value) {
2406
+ value.num[0] = this.env.wind.gustScale;
2407
+ },
2408
+ set (value) {
2409
+ this.env.wind.gustScale = value.num[0];
2410
+ }
2411
+ },
2412
+ {
2413
+ name: 'WindFieldDetailStrength',
2414
+ description: 'Amount of small, fast flutter on top of the gusts',
2415
+ type: 'float',
2416
+ default: 0.25,
2417
+ options: {
2418
+ group: 'Wind',
2419
+ label: 'TurbulenceStrength',
2420
+ animatable: true,
2421
+ minValue: 0,
2422
+ maxValue: 2
2423
+ },
2424
+ get (value) {
2425
+ value.num[0] = this.env.wind.detailStrength;
2426
+ },
2427
+ set (value) {
2428
+ this.env.wind.detailStrength = value.num[0];
2429
+ }
2430
+ },
2431
+ {
2432
+ name: 'WindFieldDetailScale',
2433
+ description: 'Size of the small flutter patches, in units',
2434
+ type: 'float',
2435
+ default: 4,
2436
+ options: {
2437
+ group: 'Wind',
2438
+ label: 'TurbulenceSize',
2439
+ animatable: true,
2440
+ minValue: 0.1,
2441
+ maxValue: 100
2442
+ },
2443
+ get (value) {
2444
+ value.num[0] = this.env.wind.detailScale;
2445
+ },
2446
+ set (value) {
2447
+ this.env.wind.detailScale = value.num[0];
2448
+ }
2449
+ },
835
2450
  {
836
2451
  name: 'NodeHierarchy',
837
2452
  description: 'Node tree of this scene',
@@ -987,6 +2602,27 @@ import { ScriptAttachment, normalizeScriptAttachmentConfig } from '../../../scen
987
2602
  this.scriptConfigs = data instanceof JSONArray ? data.data : Array.isArray(data) ? data : [];
988
2603
  }
989
2604
  },
2605
+ {
2606
+ name: 'Physics',
2607
+ description: 'Gravity, step rate and collision layers used when the scene is simulated with physics; leave empty for defaults',
2608
+ type: 'object',
2609
+ default: null,
2610
+ options: {
2611
+ objectTypes: [
2612
+ ScenePhysicsSettings
2613
+ ]
2614
+ },
2615
+ isNullable () {
2616
+ return true;
2617
+ },
2618
+ get (value) {
2619
+ value.object[0] = this.physicsSettings;
2620
+ },
2621
+ set (value) {
2622
+ const settings = value?.object[0];
2623
+ this.physicsSettings = settings instanceof ScenePhysicsSettings ? settings : null;
2624
+ }
2625
+ },
990
2626
  {
991
2627
  name: 'Metadata',
992
2628
  description: 'Meta data for this scene',