@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
@@ -0,0 +1,524 @@
1
+ import { Vector4, Vector3, DEPTH_FARTHEST } from '@zephyr3d/base';
2
+ import { ShaderHelper } from '../material/shader/helper.js';
3
+ import { waterScatterPhase } from '../shaders/water_medium.js';
4
+ import { LIGHT_TYPE_DIRECTIONAL } from '../values.js';
5
+ import { interleavedGradientNoise } from '../shaders/noise.js';
6
+ import { SkyRenderer } from './sky.js';
7
+ import { fetchSampler } from '../utility/misc.js';
8
+ import { drawFullscreenQuad } from './fullscreenquad.js';
9
+
10
+ /**
11
+ * Which waters each camera is currently inside, and the rest plane of each.
12
+ *
13
+ * Written by {@link Water.updatePerCamera}, which runs for every water every
14
+ * frame whether or not the surface survived culling, so the state survives the
15
+ * surface leaving the frustum.
16
+ *
17
+ * Keyed on the camera so multiple views stay independent. Entries of disposed
18
+ * waters are pruned on read.
19
+ *
20
+ * @internal
21
+ */ const _submergence = new WeakMap();
22
+ /**
23
+ * Record whether `camera` is inside `water` this frame.
24
+ *
25
+ * @param camera - Camera being updated.
26
+ * @param water - Water reporting its own state.
27
+ * @param submerged - Whether the camera is inside this body.
28
+ * @param surfaceY - World Y of the water's rest plane.
29
+ * @internal
30
+ */ function setWaterSubmergence(camera, water, submerged, surfaceY) {
31
+ let bodies = _submergence.get(camera);
32
+ if (submerged) {
33
+ if (!bodies) {
34
+ bodies = new Map();
35
+ _submergence.set(camera, bodies);
36
+ }
37
+ bodies.set(water, surfaceY);
38
+ } else if (bodies) {
39
+ bodies.delete(water);
40
+ }
41
+ }
42
+ /**
43
+ * The water the camera is currently inside, or null when it is above all of them.
44
+ *
45
+ * When several qualify, the highest wins: it is the last surface the eye crossed
46
+ * on its way down.
47
+ *
48
+ * @param ctx - Frame draw context.
49
+ * @returns The submerged state, or null.
50
+ * @internal
51
+ */ function selectUnderwaterSource(ctx) {
52
+ const bodies = _submergence.get(ctx.camera);
53
+ if (!bodies || bodies.size === 0) {
54
+ return null;
55
+ }
56
+ let best = null;
57
+ let bestY = 0;
58
+ for (const [water, surfaceY] of bodies){
59
+ // A node disposed since its last update never clears its own entry.
60
+ if (water.disposed) {
61
+ bodies.delete(water);
62
+ continue;
63
+ }
64
+ if (!best || surfaceY > bestY) {
65
+ best = water;
66
+ bestY = surfaceY;
67
+ }
68
+ }
69
+ const material = best?.material;
70
+ if (!best || !material || !material.underwaterEnabled) {
71
+ return null;
72
+ }
73
+ return {
74
+ water: best,
75
+ material,
76
+ surfaceY: bestY,
77
+ eyeDepth: Math.max(0, bestY - ctx.camera.getWorldPosition().y)
78
+ };
79
+ }
80
+ /**
81
+ * Optical depth at which a channel is taken to have died completely.
82
+ *
83
+ * exp(-30) is about 1e-13, zero in any scene color format. The path length is
84
+ * capped at the distance reaching this on the least attenuated channel.
85
+ * @internal
86
+ */ const OPTICAL_DEPTH_CAP = 30;
87
+ /**
88
+ * Global name of the shadow map the receiver helpers sample.
89
+ *
90
+ * Must match the name `ShaderHelper` declares and the shadow implementation's
91
+ * `computeShadow` reads.
92
+ * @internal
93
+ */ const SHADOW_MAP_UNIFORM = 'Z_UniformShadowMap';
94
+ /**
95
+ * Composites the water body a submerged camera is looking through.
96
+ *
97
+ * Two draws over the opaque scene, both in place on the scene color target:
98
+ *
99
+ * 1. multiply by the medium's transmittance, then
100
+ * 2. add what the medium scatters back towards the eye.
101
+ *
102
+ * Two draws because the transmittance is per channel and a single blend equation
103
+ * only has a scalar `src-alpha`; the first draw uses `src-color` as the
104
+ * destination factor.
105
+ *
106
+ * The pass runs after the sky and treats a sky pixel as a ray that never left
107
+ * the water: its path length is the cap, so the horizon is pure medium.
108
+ *
109
+ * @internal
110
+ */ class UnderwaterRenderer {
111
+ /** Multiplies the scene by the medium transmittance. */ _extinctionProgram;
112
+ _extinctionBindGroup;
113
+ _extinctionStates;
114
+ /**
115
+ * Adds what the medium scatters towards the eye. Two variants: ambient alone,
116
+ * and ambient plus a march for the sun shafts. Keyed on the step count as well
117
+ * as on whether the shafts are on, because the loop is unrolled at that count.
118
+ */ _inscatterPrograms;
119
+ _inscatterStates;
120
+ /** (ambientScale, surfaceY, maxPathLength, godRayIntensity) */ _params;
121
+ /** (scatterAnisotropy, unused, unused, unused) */ _phaseParams;
122
+ _extinction;
123
+ _albedo;
124
+ _sunDir;
125
+ _sunColor;
126
+ /** Shadow receiver uniforms, only touched while the shafts are shadowed. */ _cameraPosition;
127
+ _cameraParams;
128
+ _implParams;
129
+ _cameraForward;
130
+ /** Reused scratch copy of the cascade matrices for the uniform setter. */ _shadowMatrices;
131
+ constructor(){
132
+ this._extinctionProgram = null;
133
+ this._extinctionBindGroup = null;
134
+ this._extinctionStates = null;
135
+ this._inscatterPrograms = new Map();
136
+ this._inscatterStates = null;
137
+ this._params = new Vector4();
138
+ this._phaseParams = new Vector4();
139
+ this._extinction = new Vector3();
140
+ this._albedo = new Vector3();
141
+ this._sunDir = new Vector3();
142
+ this._sunColor = new Vector3();
143
+ this._cameraPosition = new Vector4();
144
+ this._cameraParams = new Vector4();
145
+ this._implParams = new Vector4();
146
+ this._cameraForward = new Vector4();
147
+ this._shadowMatrices = null;
148
+ }
149
+ /**
150
+ * Composite the medium over the opaque scene.
151
+ *
152
+ * @param ctx - Frame draw context.
153
+ * @param state - The water the camera is inside.
154
+ * @param colorFramebuffer - Color-only target holding the opaque scene and the
155
+ * sky. The depth attachment is deliberately absent: this pass samples the
156
+ * scene depth, which it could not do while that texture is still attached.
157
+ * @param depthTexture - Scene depth attachment, sampled for the path length.
158
+ */ render(ctx, state, colorFramebuffer, depthTexture) {
159
+ const device = ctx.device;
160
+ const material = state.material;
161
+ // Shafts need the caustic map and its sun; without them only the ambient term
162
+ // is drawn.
163
+ const sun = ctx.waterCausticLight;
164
+ const godRays = material.underwaterGodRays && !!ctx.waterCaustics && !!sun && material.underwaterGodRayIntensity > 0;
165
+ const steps = godRays ? material.underwaterGodRaySteps : 0;
166
+ const shadowMapParams = godRays && material.underwaterGodRayShadow ? ctx.shadowMapInfo?.get(sun) ?? null : null;
167
+ const shadow = shadowMapParams?.shadowMap ? shadowMapParams : null;
168
+ const { extinctionPass, inscatterPass } = this._prepare(device, steps, shadow);
169
+ const extinction = material.extinction;
170
+ this._extinction.set(extinction);
171
+ this._albedo.set(material.scatterAlbedo);
172
+ // Far enough that the least attenuated channel has died. A channel with no
173
+ // extinction at all has no such distance, and the far plane stands in.
174
+ const minExtinction = Math.min(extinction.x, extinction.y, extinction.z);
175
+ const far = ctx.camera.getFarPlane();
176
+ this._params.setXYZW(// The distant-sky LUT is baked exposure-independently, as everywhere else
177
+ // it is read from.
178
+ SkyRenderer.getBakeToPreExposedScale(ctx) * material.underwaterAmbientIntensity, state.surfaceY, minExtinction > 0 ? Math.min(far, OPTICAL_DEPTH_CAP / minExtinction) : far, godRays ? material.underwaterGodRayIntensity : 0);
179
+ this._phaseParams.setXYZW(material.scatterAnisotropy, 0, 0, 0);
180
+ if (sun) {
181
+ // Direction the light travels, matching what calculateWaterCaustic
182
+ // compares its own against.
183
+ const dir = sun.directionAndCutoff;
184
+ this._sunDir.setXYZ(dir.x, dir.y, dir.z);
185
+ const color = sun.diffuseAndIntensity;
186
+ // Pre-exposed, like every other radiance this pass adds to the scene.
187
+ const intensity = color.w * ShaderHelper.getPreExposure(ctx);
188
+ this._sunColor.setXYZ(color.x * intensity, color.y * intensity, color.z * intensity);
189
+ } else {
190
+ this._sunDir.setXYZ(0, -1, 0);
191
+ this._sunColor.setXYZ(0, 0, 0);
192
+ }
193
+ // Same rule the post effects use (AbstractPostEffect.needFlip): WebGPU's
194
+ // render target has the opposite vertical convention to the screen.
195
+ const flip = device.type === 'webgpu' && colorFramebuffer ? 1 : 0;
196
+ const nearestSampler = fetchSampler('clamp_nearest_nomip');
197
+ const skyLut = ctx.scene.env.sky.getSkyDistantLightLUT(ctx);
198
+ const invProjView = ctx.camera.invViewProjectionMatrix;
199
+ const cameraPos = ctx.camera.getWorldPosition();
200
+ const passes = [
201
+ extinctionPass,
202
+ inscatterPass
203
+ ];
204
+ device.pushDeviceStates();
205
+ try {
206
+ device.setFramebuffer(colorFramebuffer);
207
+ device.setViewport(null);
208
+ device.setScissor(null);
209
+ for (const pass of passes){
210
+ const bindGroup = pass.bindGroup;
211
+ bindGroup.setTexture('depthTex', depthTexture, nearestSampler);
212
+ bindGroup.setTexture('skyLut', skyLut, nearestSampler);
213
+ bindGroup.setValue('invProjViewMatrix', invProjView);
214
+ bindGroup.setValue('cameraPosition', cameraPos);
215
+ bindGroup.setValue('mediumExtinction', this._extinction);
216
+ bindGroup.setValue('mediumAlbedo', this._albedo);
217
+ bindGroup.setValue('params', this._params);
218
+ bindGroup.setValue('flip', flip);
219
+ if (pass === inscatterPass && godRays) {
220
+ bindGroup.setValue('sunDirection', this._sunDir);
221
+ bindGroup.setValue('sunColor', this._sunColor);
222
+ bindGroup.setValue('phaseParams', this._phaseParams);
223
+ // Same uniforms the lit materials bind, so the shafts and the caustics
224
+ // on the sea bed are reading one map through one projection.
225
+ ShaderHelper.setWaterCausticUniforms(bindGroup, ctx);
226
+ if (shadow) {
227
+ this._setShadowUniforms(bindGroup, ctx, sun, shadow);
228
+ }
229
+ }
230
+ device.setProgram(pass.program);
231
+ device.setBindGroup(0, bindGroup);
232
+ drawFullscreenQuad(pass.states);
233
+ }
234
+ } finally{
235
+ device.popDeviceStates();
236
+ }
237
+ }
238
+ /**
239
+ * Upload the shadow receiver uniforms the march samples.
240
+ *
241
+ * Names and struct layouts match the material light pass's globals, which the
242
+ * shadow helpers read; see `ShadowMaskRenderer.setUniforms`.
243
+ * @internal
244
+ */ _setShadowUniforms(bindGroup, ctx, light, shadowMapParams) {
245
+ const camera = ctx.camera;
246
+ const near = camera.getNearPlane();
247
+ const far = camera.getFarPlane();
248
+ const cameraPos = camera.getWorldPosition();
249
+ this._cameraPosition.setXYZW(cameraPos.x, cameraPos.y, cameraPos.z, 0);
250
+ this._cameraParams.setXYZW(near, far, 1, 1);
251
+ bindGroup.setValue('camera', {
252
+ position: this._cameraPosition,
253
+ params: this._cameraParams,
254
+ shadowDebugCascades: camera.shadowDebugCascades ? 1 : 0,
255
+ framestamp: ctx.device.frameInfo.frameCounter
256
+ });
257
+ shadowMapParams.impl.getParams(this._implParams);
258
+ const matrices = shadowMapParams.shadowMatrices;
259
+ if (!this._shadowMatrices || this._shadowMatrices.length !== matrices.length) {
260
+ this._shadowMatrices = new Float32Array(matrices.length);
261
+ }
262
+ this._shadowMatrices.set(matrices);
263
+ bindGroup.setValue('light', {
264
+ sunDir: ctx.sunLight ? ctx.sunLight.directionAndCutoff.xyz().scaleBy(-1) : Vector3.axisPY(),
265
+ shadowCascades: shadowMapParams.numShadowCascades,
266
+ positionAndRange: light.positionAndRange,
267
+ directionAndCutoff: light.directionAndCutoff,
268
+ diffuseAndIntensity: ShaderHelper.getPreExposedColorIntensity(light, ctx),
269
+ extraParams: light.extraParams,
270
+ cascadeDistances: shadowMapParams.cascadeDistances,
271
+ depthBiasValues: shadowMapParams.depthBiasValues[0],
272
+ shadowCameraParams: shadowMapParams.cameraParams,
273
+ depthBiasScales: shadowMapParams.depthBiasScales,
274
+ implParams: this._implParams,
275
+ shadowMatrices: this._shadowMatrices,
276
+ shadowStrength: light.shadow.shadowStrength,
277
+ envLightStrength: ShaderHelper.getEnvLightLuminance(ctx),
278
+ envLightSpecularStrength: ctx.env?.light.specularStrength ?? 1
279
+ });
280
+ // Camera forward, for the cascade split test, which is measured in view
281
+ // depth rather than radial distance.
282
+ camera.worldMatrix.getRow(2, this._cameraForward);
283
+ this._cameraForward.scaleBy(-1);
284
+ bindGroup.setValue('cameraForward', this._cameraForward.xyz());
285
+ bindGroup.setTexture(SHADOW_MAP_UNIFORM, shadowMapParams.shadowMap, shadowMapParams.shadowMapSampler);
286
+ }
287
+ /**
288
+ * Build or fetch the two programs this frame needs.
289
+ *
290
+ * @param device - Rendering device.
291
+ * @param steps - Ray-march steps for the shafts, 0 for the ambient-only variant.
292
+ * @param shadow - Shadow params for the caustic light when the shafts should be
293
+ * occluded by geometry, null when they should not.
294
+ * @internal
295
+ */ _prepare(device, steps, shadow) {
296
+ if (!this._extinctionProgram) {
297
+ this._extinctionProgram = UnderwaterRenderer._createProgram(device, false, 0, null);
298
+ this._extinctionBindGroup = device.createBindGroup(this._extinctionProgram.bindGroupLayouts[0]);
299
+ this._extinctionStates = device.createRenderStateSet();
300
+ this._extinctionStates.useRasterizerState().setCullMode('none');
301
+ this._extinctionStates.useDepthState().enableTest(false).enableWrite(false);
302
+ // dst.rgb *= src.rgb (per-channel transmittance).
303
+ this._extinctionStates.useBlendingState().enable(true).setBlendFuncRGB('zero', 'src-color').setBlendFuncAlpha('zero', 'one');
304
+ }
305
+ if (!this._inscatterStates) {
306
+ this._inscatterStates = device.createRenderStateSet();
307
+ this._inscatterStates.useRasterizerState().setCullMode('none');
308
+ this._inscatterStates.useDepthState().enableTest(false).enableWrite(false);
309
+ // dst.rgb += src.rgb. Alpha is left alone, as in the fog pass, so a dense
310
+ // medium does not make the canvas transparent.
311
+ this._inscatterStates.useBlendingState().enable(true).setBlendFuncRGB('one', 'one').setBlendFuncAlpha('zero', 'one');
312
+ }
313
+ // The march is unrolled, so the step count is part of the program identity,
314
+ // as is the shadow hash the receiver code is generated from.
315
+ const key = `${steps}|${shadow ? shadow.shaderHash : ''}`;
316
+ let inscatter = this._inscatterPrograms.get(key);
317
+ if (!inscatter) {
318
+ const program = UnderwaterRenderer._createProgram(device, true, steps, shadow);
319
+ inscatter = {
320
+ program,
321
+ bindGroup: device.createBindGroup(program.bindGroupLayouts[0])
322
+ };
323
+ this._inscatterPrograms.set(key, inscatter);
324
+ }
325
+ return {
326
+ extinctionPass: {
327
+ program: this._extinctionProgram,
328
+ bindGroup: this._extinctionBindGroup,
329
+ states: this._extinctionStates
330
+ },
331
+ inscatterPass: {
332
+ program: inscatter.program,
333
+ bindGroup: inscatter.bindGroup,
334
+ states: this._inscatterStates
335
+ }
336
+ };
337
+ }
338
+ /**
339
+ * @param device - Rendering device.
340
+ * @param inscatter - Build the in-scattering half rather than the extinction one.
341
+ * @param steps - Ray-march steps for the sun shafts; 0 leaves them out entirely.
342
+ * @param shadowMapParams - Shadow params when the shafts should be occluded by
343
+ * geometry, null when they should not.
344
+ * @internal
345
+ */ static _createProgram(device, inscatter, steps, shadowMapParams) {
346
+ const godRays = inscatter && steps > 0;
347
+ const shadow = godRays ? shadowMapParams : null;
348
+ const numCascades = shadow?.numShadowCascades ?? 0;
349
+ const program = device.buildRenderProgram({
350
+ label: inscatter ? 'UnderwaterInscatter' : 'UnderwaterExtinction',
351
+ vertex (pb) {
352
+ this.flip = pb.int().uniform(0);
353
+ this.$inputs.pos = pb.vec2().attrib('position');
354
+ this.$outputs.uv = pb.vec2();
355
+ pb.main(function() {
356
+ this.$builtins.position = pb.vec4(this.$inputs.pos, DEPTH_FARTHEST, 1);
357
+ this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));
358
+ this.$if(pb.notEqual(this.flip, 0), function() {
359
+ this.$builtins.position.y = pb.neg(this.$builtins.position.y);
360
+ });
361
+ });
362
+ },
363
+ fragment (pb) {
364
+ this.depthTex = pb.tex2D().sampleType('unfilterable-float').uniform(0);
365
+ this.skyLut = pb.tex2D().uniform(0);
366
+ this.invProjViewMatrix = pb.mat4().uniform(0);
367
+ this.cameraPosition = pb.vec3().uniform(0);
368
+ this.mediumExtinction = pb.vec3().uniform(0);
369
+ this.mediumAlbedo = pb.vec3().uniform(0);
370
+ /** (ambientScale, surfaceY, maxPathLength, godRayIntensity) */ this.params = pb.vec4().uniform(0);
371
+ if (godRays) {
372
+ /** Direction the sun travels, as `directionAndCutoff.xyz`. */ this.sunDirection = pb.vec3().uniform(0);
373
+ /** Pre-exposed sun radiance. */ this.sunColor = pb.vec3().uniform(0);
374
+ /** (scatterAnisotropy, unused, unused, unused) */ this.phaseParams = pb.vec4().uniform(0);
375
+ // The same caustic uniforms every lit material declares, so the shafts
376
+ // read the map through the exact projection the sea bed does.
377
+ ShaderHelper.declareWaterCausticUniforms(pb);
378
+ }
379
+ if (shadow) {
380
+ // Reproduces the material light pass's globals the shadow helpers read
381
+ // by name, as ShadowMaskRenderer does.
382
+ const cameraStruct = pb.defineStruct([
383
+ pb.vec4('position'),
384
+ pb.vec4('params'),
385
+ pb.float('shadowDebugCascades'),
386
+ // Read by the PCSS implementation's temporal jitter.
387
+ pb.int('framestamp')
388
+ ]);
389
+ const lightStruct = pb.defineStruct([
390
+ pb.vec3('sunDir'),
391
+ pb.int('shadowCascades'),
392
+ pb.vec4('positionAndRange'),
393
+ pb.vec4('directionAndCutoff'),
394
+ pb.vec4('diffuseAndIntensity'),
395
+ pb.vec4('extraParams'),
396
+ pb.vec4('cascadeDistances'),
397
+ pb.vec4('depthBiasValues'),
398
+ pb.vec4('shadowCameraParams'),
399
+ pb.vec4('depthBiasScales'),
400
+ pb.vec4('implParams'),
401
+ pb.vec4[16]('shadowMatrices'),
402
+ pb.float('shadowStrength'),
403
+ pb.float('envLightStrength'),
404
+ pb.float('envLightSpecularStrength')
405
+ ]);
406
+ this.camera = cameraStruct().uniform(0);
407
+ this.light = lightStruct().uniform(0);
408
+ this.cameraForward = pb.vec3().uniform(0);
409
+ const shadowMap = shadow.shadowMap;
410
+ const shadowTex = shadowMap.isTextureCube() ? shadowMap.isDepth() ? pb.texCubeShadow() : pb.texCube() : shadowMap.isTexture2D() ? shadowMap.isDepth() ? pb.tex2DShadow() : pb.tex2D() : shadowMap.isDepth() ? pb.tex2DArrayShadow() : pb.tex2DArray();
411
+ if (!shadowMap.isDepth() && !device.getDeviceCaps().textureCaps.getTextureFormatInfo(shadowMap.format).filterable) {
412
+ shadowTex.sampleType('unfilterable-float');
413
+ }
414
+ this[SHADOW_MAP_UNIFORM] = shadowTex.uniform(0);
415
+ // How much sun reaches a point inside the water column. A point in the
416
+ // medium has no surface orientation, so no normal offset and NoL = 1.
417
+ pb.func('zUnderwaterShadow', [
418
+ pb.vec3('worldPos'),
419
+ pb.float('viewDepth')
420
+ ], function() {
421
+ if (numCascades > 1) {
422
+ this.$l.comparison = pb.vec4(pb.greaterThan(pb.vec4(this.viewDepth), this.light.cascadeDistances));
423
+ this.$l.cascadeFlags = pb.vec4(pb.float(pb.greaterThan(this.light.shadowCascades, 0)), pb.float(pb.greaterThan(this.light.shadowCascades, 1)), pb.float(pb.greaterThan(this.light.shadowCascades, 2)), pb.float(pb.greaterThan(this.light.shadowCascades, 3)));
424
+ this.$l.split = pb.int(pb.dot(this.comparison, this.cascadeFlags));
425
+ this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(this, pb.vec4(this.worldPos, 1), this.split);
426
+ this.$l.shadow = shadow.impl.computeShadowCSM(shadow, this, this.shadowVertex, pb.float(1), this.split);
427
+ } else {
428
+ this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(this, pb.vec4(this.worldPos, 1));
429
+ this.$l.shadow = shadow.impl.computeShadow(shadow, this, this.shadowVertex, pb.float(1));
430
+ }
431
+ // Fade to unshadowed towards the shadow distance, as the surfaces do.
432
+ this.$l.shadowDistance = this.light.shadowCameraParams.w;
433
+ this.shadow = pb.mix(this.shadow, 1, pb.smoothStep(pb.mul(this.shadowDistance, 0.8), this.shadowDistance, pb.distance(this.camera.position.xyz, this.worldPos)));
434
+ this.shadow = pb.mix(1, this.shadow, this.light.shadowStrength);
435
+ this.$return(pb.clamp(this.shadow, 0, 1));
436
+ });
437
+ }
438
+ this.$outputs.outColor = pb.vec4();
439
+ pb.main(function() {
440
+ this.$l.depthValue = pb.textureSample(this.depthTex, this.$inputs.uv).r;
441
+ this.$l.clipSpacePos = pb.vec4(pb.sub(pb.mul(this.$inputs.uv, 2), pb.vec2(1)), ShaderHelper.deviceDepthToClipZ(this, this.depthValue), 1);
442
+ this.$l.hPos = pb.mul(this.invProjViewMatrix, this.clipSpacePos);
443
+ this.$l.worldPos = pb.div(this.hPos, this.hPos.w).xyz;
444
+ this.$l.isSky = ShaderHelper.isFarthestDepth(this, this.depthValue);
445
+ // Normalised from the raw difference, not divided by the capped path
446
+ // length, so it stays a unit vector and cosTheta stays in [-1, 1].
447
+ this.$l.viewDir = pb.normalize(pb.sub(this.worldPos, this.cameraPosition));
448
+ // A ray that reached the sky never left the water, so it takes the
449
+ // whole cap.
450
+ this.$l.pathLength = this.$choice(this.isSky, this.params.z, pb.min(pb.distance(this.worldPos, this.cameraPosition), this.params.z));
451
+ this.$l.transmittance = pb.exp(pb.neg(pb.mul(this.mediumExtinction, this.pathLength)));
452
+ if (!inscatter) {
453
+ this.$outputs.outColor = pb.vec4(this.transmittance, 1);
454
+ } else {
455
+ // Downwelling sky light, attenuated over the vertical depth averaged
456
+ // between the two ends of the path.
457
+ this.$l.endY = this.$choice(this.isSky, this.cameraPosition.y, this.worldPos.y);
458
+ this.$l.columnDepth = pb.mul(0.5, pb.add(pb.max(pb.sub(this.params.y, this.cameraPosition.y), 0), pb.max(pb.sub(this.params.y, this.endY), 0)));
459
+ this.$l.ambient = pb.mul(pb.textureSampleLevel(this.skyLut, pb.vec2(0.5), 0).rgb, this.params.x, pb.exp(pb.neg(pb.mul(this.mediumExtinction, this.columnDepth))));
460
+ // Single scattering, the same form getScattering() uses on the surface.
461
+ this.$l.inscatter = pb.mul(this.mediumAlbedo, pb.sub(pb.vec3(1), this.transmittance), this.ambient);
462
+ if (godRays) {
463
+ // Sun shafts: the single scattering integral against the sun,
464
+ // marched along the view ray since the sun reaching each point
465
+ // depends on the surface overhead.
466
+ //
467
+ // Scattering angle, constant along the ray; clamped against rounding.
468
+ this.$l.cosTheta = pb.clamp(pb.neg(pb.dot(this.sunDirection, this.viewDir)), -1, 1);
469
+ this.$l.phase = waterScatterPhase(this, this.cosTheta, this.phaseParams.x);
470
+ // Dithered sample offset, trading banding for grain.
471
+ this.$l.jitter = interleavedGradientNoise(this, this.$builtins.fragCoord.xy);
472
+ // The integral is sigma_s * integral(sunAtP(t) * exp(-sigma_t * t) dt),
473
+ // and only `sunAtP` needs sampling - the exponential is analytic.
474
+ // So the march estimates the transmittance-weighted *mean* of
475
+ // sunAtP and the closed form below supplies the rest.
476
+ //
477
+ // Samples are importance-sampled by inverting the exponential of
478
+ // the *least* attenuated channel: the per-channel correction grows
479
+ // like exp((sigma_place - sigma_c) * t), so this keeps every
480
+ // exponent non-positive and no weight can run away.
481
+ this.$l.sigmaPlace = pb.max(pb.min(pb.min(this.mediumExtinction.x, this.mediumExtinction.y), this.mediumExtinction.z), 1e-3);
482
+ // Renormalises the exponential to the finite path, so the samples
483
+ // span exactly the visible stretch however short it is.
484
+ this.$l.cdfMax = pb.sub(1, pb.exp(pb.neg(pb.mul(this.sigmaPlace, this.pathLength))));
485
+ this.$l.shafts = pb.vec3(0);
486
+ this.$l.weightSum = pb.vec3(0);
487
+ this.$for(pb.int('i'), 0, steps, function() {
488
+ this.$l.u = pb.div(pb.add(pb.float(this.i), this.jitter), steps);
489
+ this.$l.t = pb.min(pb.div(pb.neg(pb.log(pb.max(pb.sub(1, pb.mul(this.u, this.cdfMax)), 1e-6))), this.sigmaPlace), this.pathLength);
490
+ this.$l.samplePos = pb.add(this.cameraPosition, pb.mul(this.viewDir, this.t));
491
+ // Sun reaching this point: the caustic map already carries the
492
+ // Beer-Lambert transmittance down the sun ray and the focusing
493
+ // pattern, so shafts line up with the caustics.
494
+ this.$l.sunAtP = ShaderHelper.sampleWaterCaustic(this, this.samplePos, pb.int(LIGHT_TYPE_DIRECTIONAL), this.sunDirection, false);
495
+ if (shadow) {
496
+ // Occlusion by geometry under the surface, which the caustic
497
+ // map does not know about.
498
+ this.$l.viewDepth = pb.dot(pb.sub(this.samplePos, this.cameraPosition), this.cameraForward);
499
+ this.sunAtP = pb.mul(this.sunAtP, this.zUnderwaterShadow(this.samplePos, this.viewDepth));
500
+ }
501
+ // Transmittance back to the eye over the sampling pdf; the pdf's
502
+ // constant factors cancel in the ratio below.
503
+ this.$l.weight = pb.exp(pb.mul(pb.sub(pb.vec3(this.sigmaPlace), this.mediumExtinction), this.t));
504
+ this.shafts = pb.add(this.shafts, pb.mul(this.sunAtP, this.weight));
505
+ this.weightSum = pb.add(this.weightSum, this.weight);
506
+ });
507
+ // Closed form with sunAtP at its sampled mean:
508
+ // sigma_s/sigma_t * (1 - exp(-sigma_t * path)), the same
509
+ // normalisation as the ambient term.
510
+ this.$l.meanSun = pb.div(this.shafts, pb.max(this.weightSum, pb.vec3(1e-6)));
511
+ this.inscatter = pb.add(this.inscatter, pb.mul(this.meanSun, this.mediumAlbedo, pb.sub(pb.vec3(1), this.transmittance), this.sunColor, pb.mul(this.phase, this.params.w)));
512
+ }
513
+ this.$outputs.outColor = pb.vec4(this.inscatter, 1);
514
+ }
515
+ });
516
+ }
517
+ });
518
+ program.name = inscatter ? '@UnderwaterInscatter' : '@UnderwaterExtinction';
519
+ return program;
520
+ }
521
+ }
522
+
523
+ export { UnderwaterRenderer, selectUnderwaterSource, setWaterSubmergence };
524
+ //# sourceMappingURL=underwater.js.map