@zephyr3d/scene 0.9.27 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (502) hide show
  1. package/README.md +60 -27
  2. package/dist/animation/animation_bank.js +634 -0
  3. package/dist/animation/animation_bank.js.map +1 -0
  4. package/dist/animation/animation_bank_gpu.js +256 -0
  5. package/dist/animation/animation_bank_gpu.js.map +1 -0
  6. package/dist/animation/animationset.js +54 -0
  7. package/dist/animation/animationset.js.map +1 -1
  8. package/dist/animation/cloth/gpu_cloth_component.js +406 -0
  9. package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
  10. package/dist/animation/cloth/gpu_cloth_system.js +332 -202
  11. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  12. package/dist/animation/gpu_animation_driver.js +289 -0
  13. package/dist/animation/gpu_animation_driver.js.map +1 -0
  14. package/dist/animation/joint_dynamics/collision.js +112 -1
  15. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  16. package/dist/animation/joint_dynamics/controller.js +6 -0
  17. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
  19. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  20. package/dist/animation/joint_dynamics/solver.js +50 -12
  21. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/skeleton.js +279 -55
  24. package/dist/animation/skeleton.js.map +1 -1
  25. package/dist/animation/skin_palette_atlas.js +252 -0
  26. package/dist/animation/skin_palette_atlas.js.map +1 -0
  27. package/dist/animation/spring/multi_chain_spring_system.js +298 -38
  28. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  29. package/dist/animation/spring/spring_chain.js +2 -0
  30. package/dist/animation/spring/spring_chain.js.map +1 -1
  31. package/dist/animation/spring/spring_collider.js +159 -21
  32. package/dist/animation/spring/spring_collider.js.map +1 -1
  33. package/dist/animation/spring/spring_particle.js +1 -0
  34. package/dist/animation/spring/spring_particle.js.map +1 -1
  35. package/dist/animation/spring/spring_solver.js +173 -0
  36. package/dist/animation/spring/spring_solver.js.map +1 -0
  37. package/dist/animation/spring/spring_system.js +249 -24
  38. package/dist/animation/spring/spring_system.js.map +1 -1
  39. package/dist/animation/spring_modifier.js +32 -1
  40. package/dist/animation/spring_modifier.js.map +1 -1
  41. package/dist/app/app.js +26 -0
  42. package/dist/app/app.js.map +1 -1
  43. package/dist/app/engine.js +86 -15
  44. package/dist/app/engine.js.map +1 -1
  45. package/dist/app/gamepad.js +191 -0
  46. package/dist/app/gamepad.js.map +1 -0
  47. package/dist/app/inputactions.js +271 -0
  48. package/dist/app/inputactions.js.map +1 -0
  49. package/dist/app/inputmgr.js +331 -22
  50. package/dist/app/inputmgr.js.map +1 -1
  51. package/dist/app/loading.js +138 -0
  52. package/dist/app/loading.js.map +1 -0
  53. package/dist/app/pipelinecache.js +209 -0
  54. package/dist/app/pipelinecache.js.map +1 -0
  55. package/dist/app/runtimescript.js +25 -0
  56. package/dist/app/runtimescript.js.map +1 -1
  57. package/dist/app/scriptingsystem.js +54 -0
  58. package/dist/app/scriptingsystem.js.map +1 -1
  59. package/dist/app/scriptregistry.js +7 -2
  60. package/dist/app/scriptregistry.js.map +1 -1
  61. package/dist/asset/asset_manifest.js +59 -0
  62. package/dist/asset/asset_manifest.js.map +1 -0
  63. package/dist/asset/asset_preload.js +258 -0
  64. package/dist/asset/asset_preload.js.map +1 -0
  65. package/dist/asset/assetmanager.js +117 -65
  66. package/dist/asset/assetmanager.js.map +1 -1
  67. package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
  68. package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  69. package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  70. package/dist/asset/loaders/ktx2/basis_location.js +17 -0
  71. package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
  72. package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
  73. package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
  74. package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
  75. package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
  76. package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
  77. package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
  78. package/dist/asset/mesh_lod_builder.js +104 -0
  79. package/dist/asset/mesh_lod_builder.js.map +1 -0
  80. package/dist/asset/mesh_settings.js +111 -0
  81. package/dist/asset/mesh_settings.js.map +1 -0
  82. package/dist/asset/meshopt_decoder.js +18 -0
  83. package/dist/asset/meshopt_decoder.js.map +1 -0
  84. package/dist/asset/meshopt_simplifier.js +26 -0
  85. package/dist/asset/meshopt_simplifier.js.map +1 -0
  86. package/dist/asset/model.js +171 -1
  87. package/dist/asset/model.js.map +1 -1
  88. package/dist/asset/texture_settings.js +231 -0
  89. package/dist/asset/texture_settings.js.map +1 -0
  90. package/dist/asset/zmsh_binary.js +131 -0
  91. package/dist/asset/zmsh_binary.js.map +1 -0
  92. package/dist/asset/zsdf_binary.js +111 -0
  93. package/dist/asset/zsdf_binary.js.map +1 -0
  94. package/dist/blitter/bilateralblur.js +1 -2
  95. package/dist/blitter/bilateralblur.js.map +1 -1
  96. package/dist/blitter/gaussianblur.js +1 -6
  97. package/dist/blitter/gaussianblur.js.map +1 -1
  98. package/dist/camera/base.js +31 -10
  99. package/dist/camera/base.js.map +1 -1
  100. package/dist/camera/camera.js +104 -178
  101. package/dist/camera/camera.js.map +1 -1
  102. package/dist/camera/follow.js +342 -0
  103. package/dist/camera/follow.js.map +1 -0
  104. package/dist/camera/fps.js +9 -7
  105. package/dist/camera/fps.js.map +1 -1
  106. package/dist/camera/orbit.js +46 -19
  107. package/dist/camera/orbit.js.map +1 -1
  108. package/dist/index.d.ts +25436 -15990
  109. package/dist/index.js +65 -11
  110. package/dist/index.js.map +1 -1
  111. package/dist/material/blinn.js +3 -0
  112. package/dist/material/blinn.js.map +1 -1
  113. package/dist/material/eye.js +1 -1
  114. package/dist/material/eye.js.map +1 -1
  115. package/dist/material/hair.js +2 -3
  116. package/dist/material/hair.js.map +1 -1
  117. package/dist/material/lambert.js +4 -1
  118. package/dist/material/lambert.js.map +1 -1
  119. package/dist/material/material.js +66 -4
  120. package/dist/material/material.js.map +1 -1
  121. package/dist/material/meshmaterial.js +118 -45
  122. package/dist/material/meshmaterial.js.map +1 -1
  123. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  124. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  126. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  128. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  130. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  132. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  133. package/dist/material/mixins/lit.js +191 -83
  134. package/dist/material/mixins/lit.js.map +1 -1
  135. package/dist/material/mixins/pbr/common.js +31 -206
  136. package/dist/material/mixins/pbr/common.js.map +1 -1
  137. package/dist/material/mtoon.js +1 -1
  138. package/dist/material/mtoon.js.map +1 -1
  139. package/dist/material/pbrmr.js +3 -0
  140. package/dist/material/pbrmr.js.map +1 -1
  141. package/dist/material/pbrsg.js +3 -0
  142. package/dist/material/pbrsg.js.map +1 -1
  143. package/dist/material/sdf_debug.js +78 -0
  144. package/dist/material/sdf_debug.js.map +1 -0
  145. package/dist/material/shader/helper.js +333 -191
  146. package/dist/material/shader/helper.js.map +1 -1
  147. package/dist/material/shader/terrain_blend.js +204 -43
  148. package/dist/material/shader/terrain_blend.js.map +1 -1
  149. package/dist/material/skin.js +331 -297
  150. package/dist/material/skin.js.map +1 -1
  151. package/dist/material/skinprofile.js +1058 -0
  152. package/dist/material/skinprofile.js.map +1 -0
  153. package/dist/material/sss.js +353 -0
  154. package/dist/material/sss.js.map +1 -0
  155. package/dist/material/sss_kernel.js +265 -0
  156. package/dist/material/sss_kernel.js.map +1 -0
  157. package/dist/material/sssprofile.js +879 -0
  158. package/dist/material/sssprofile.js.map +1 -0
  159. package/dist/material/subsurfaceprofile.js +4 -8
  160. package/dist/material/subsurfaceprofile.js.map +1 -1
  161. package/dist/material/terrain-cm.js +464 -188
  162. package/dist/material/terrain-cm.js.map +1 -1
  163. package/dist/material/unlit.js +3 -0
  164. package/dist/material/unlit.js.map +1 -1
  165. package/dist/material/water.js +1261 -1438
  166. package/dist/material/water.js.map +1 -1
  167. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  168. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  169. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  172. package/dist/physics/character.js +226 -0
  173. package/dist/physics/character.js.map +1 -0
  174. package/dist/physics/collider.js +209 -0
  175. package/dist/physics/collider.js.map +1 -0
  176. package/dist/physics/events.js +79 -0
  177. package/dist/physics/events.js.map +1 -0
  178. package/dist/physics/joint.js +272 -0
  179. package/dist/physics/joint.js.map +1 -0
  180. package/dist/physics/node_physics.js +234 -0
  181. package/dist/physics/node_physics.js.map +1 -0
  182. package/dist/physics/part.js +91 -0
  183. package/dist/physics/part.js.map +1 -0
  184. package/dist/physics/rigid_body.js +379 -0
  185. package/dist/physics/rigid_body.js.map +1 -0
  186. package/dist/physics/vehicle.js +335 -0
  187. package/dist/physics/vehicle.js.map +1 -0
  188. package/dist/physics/world.js +25 -0
  189. package/dist/physics/world.js.map +1 -0
  190. package/dist/posteffect/bloom.js +49 -14
  191. package/dist/posteffect/bloom.js.map +1 -1
  192. package/dist/posteffect/motionblur.js +106 -106
  193. package/dist/posteffect/motionblur.js.map +1 -1
  194. package/dist/posteffect/postsss.js +572 -0
  195. package/dist/posteffect/postsss.js.map +1 -0
  196. package/dist/posteffect/sao.js +2 -6
  197. package/dist/posteffect/sao.js.map +1 -1
  198. package/dist/posteffect/skinsss.js +605 -355
  199. package/dist/posteffect/skinsss.js.map +1 -1
  200. package/dist/posteffect/ssgi.js +91 -162
  201. package/dist/posteffect/ssgi.js.map +1 -1
  202. package/dist/posteffect/ssr.js +3 -11
  203. package/dist/posteffect/ssr.js.map +1 -1
  204. package/dist/posteffect/sss.js +4 -13
  205. package/dist/posteffect/sss.js.map +1 -1
  206. package/dist/posteffect/taa.js +1 -0
  207. package/dist/posteffect/taa.js.map +1 -1
  208. package/dist/render/abuffer_oit.js +3 -2
  209. package/dist/render/abuffer_oit.js.map +1 -1
  210. package/dist/render/clipmap.js +179 -64
  211. package/dist/render/clipmap.js.map +1 -1
  212. package/dist/render/cluster_light.js +958 -224
  213. package/dist/render/cluster_light.js.map +1 -1
  214. package/dist/render/cull_visitor.js +25 -5
  215. package/dist/render/cull_visitor.js.map +1 -1
  216. package/dist/render/debug_views.js +37 -0
  217. package/dist/render/debug_views.js.map +1 -0
  218. package/dist/render/depthpass.js +5 -1
  219. package/dist/render/depthpass.js.map +1 -1
  220. package/dist/render/drawable_mixin.js +53 -6
  221. package/dist/render/drawable_mixin.js.map +1 -1
  222. package/dist/render/dualdepthpeeling_oit.js +5 -5
  223. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  224. package/dist/render/envlight.js +196 -113
  225. package/dist/render/envlight.js.map +1 -1
  226. package/dist/render/fbm_wavegenerator.js +5 -10
  227. package/dist/render/fbm_wavegenerator.js.map +1 -1
  228. package/dist/render/fft_wavegenerator.js +247 -157
  229. package/dist/render/fft_wavegenerator.js.map +1 -1
  230. package/dist/render/gerstner_wavegenerator.js +16 -38
  231. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  232. package/dist/render/gi/probe_volume.js +1334 -0
  233. package/dist/render/gi/probe_volume.js.map +1 -0
  234. package/dist/render/gi/scene_gi.js +282 -0
  235. package/dist/render/gi/scene_gi.js.map +1 -0
  236. package/dist/render/gi/voxel_atlas.js +198 -0
  237. package/dist/render/gi/voxel_atlas.js.map +1 -0
  238. package/dist/render/gi/voxel_lighting.js +652 -0
  239. package/dist/render/gi/voxel_lighting.js.map +1 -0
  240. package/dist/render/gi/voxel_scene.js +642 -0
  241. package/dist/render/gi/voxel_scene.js.map +1 -0
  242. package/dist/render/gi/voxelize_pass.js +223 -0
  243. package/dist/render/gi/voxelize_pass.js.map +1 -0
  244. package/dist/render/globalbindgroup_allocator.js +3 -2
  245. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  246. package/dist/render/gpu_picking.js +9 -36
  247. package/dist/render/gpu_picking.js.map +1 -1
  248. package/dist/render/instance_culling.js +499 -0
  249. package/dist/render/instance_culling.js.map +1 -0
  250. package/dist/render/lightpass.js +19 -8
  251. package/dist/render/lightpass.js.map +1 -1
  252. package/dist/render/lod.js +46 -0
  253. package/dist/render/lod.js.map +1 -0
  254. package/dist/render/primitive.js +301 -9
  255. package/dist/render/primitive.js.map +1 -1
  256. package/dist/render/primitive_readback.js +209 -0
  257. package/dist/render/primitive_readback.js.map +1 -0
  258. package/dist/render/render_queue.js +162 -11
  259. package/dist/render/render_queue.js.map +1 -1
  260. package/dist/render/renderer.js +10 -7
  261. package/dist/render/renderer.js.map +1 -1
  262. package/dist/render/rendergraph/blackboard.js +14 -1
  263. package/dist/render/rendergraph/blackboard.js.map +1 -1
  264. package/dist/render/rendergraph/executor.js +136 -0
  265. package/dist/render/rendergraph/executor.js.map +1 -1
  266. package/dist/render/rendergraph/forward_plus_builder.js +272 -55
  267. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  268. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  269. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  270. package/dist/render/rendergraph/scene_render_context.js +31 -2
  271. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  272. package/dist/render/rendergraph/types.js.map +1 -1
  273. package/dist/render/renderpass.js +28 -5
  274. package/dist/render/renderpass.js.map +1 -1
  275. package/dist/render/sdf/box_allocator.js +98 -0
  276. package/dist/render/sdf/box_allocator.js.map +1 -0
  277. package/dist/render/sdf/global_sdf.js +865 -0
  278. package/dist/render/sdf/global_sdf.js.map +1 -0
  279. package/dist/render/sdf/scene_sdf.js +562 -0
  280. package/dist/render/sdf/scene_sdf.js.map +1 -0
  281. package/dist/render/sdf/sdf_atlas.js +227 -0
  282. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  283. package/dist/render/sdf/sdf_programs.js +42 -0
  284. package/dist/render/sdf/sdf_programs.js.map +1 -0
  285. package/dist/render/sdf/sdf_view.js +199 -0
  286. package/dist/render/sdf/sdf_view.js.map +1 -0
  287. package/dist/render/sdf/waterline.js +610 -0
  288. package/dist/render/sdf/waterline.js.map +1 -0
  289. package/dist/render/shadow_mask_pass.js +142 -25
  290. package/dist/render/shadow_mask_pass.js.map +1 -1
  291. package/dist/render/shore_wave_generator.js +1193 -0
  292. package/dist/render/shore_wave_generator.js.map +1 -0
  293. package/dist/render/sky.js +516 -86
  294. package/dist/render/sky.js.map +1 -1
  295. package/dist/render/transmission_thickness_pass.js +477 -0
  296. package/dist/render/transmission_thickness_pass.js.map +1 -0
  297. package/dist/render/underwater.js +58 -158
  298. package/dist/render/underwater.js.map +1 -1
  299. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  300. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  301. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  302. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  303. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  304. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  305. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  306. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  307. package/dist/render/volumetric_cloud/resources.js +380 -0
  308. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  309. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  310. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  311. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  312. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  313. package/dist/render/water_caustics.js +134 -319
  314. package/dist/render/water_caustics.js.map +1 -1
  315. package/dist/render/water_foam.js +627 -0
  316. package/dist/render/water_foam.js.map +1 -0
  317. package/dist/render/water_interaction.js +1795 -0
  318. package/dist/render/water_interaction.js.map +1 -0
  319. package/dist/render/weightedblended_oit.js +3 -3
  320. package/dist/render/weightedblended_oit.js.map +1 -1
  321. package/dist/scene/basesprite.js +9 -4
  322. package/dist/scene/basesprite.js.map +1 -1
  323. package/dist/scene/batchgroup.js +108 -12
  324. package/dist/scene/batchgroup.js.map +1 -1
  325. package/dist/scene/environment.js +28 -7
  326. package/dist/scene/environment.js.map +1 -1
  327. package/dist/scene/foliage.js +1020 -0
  328. package/dist/scene/foliage.js.map +1 -0
  329. package/dist/scene/foliage_buckets.js +147 -0
  330. package/dist/scene/foliage_buckets.js.map +1 -0
  331. package/dist/scene/foliage_mask.js +358 -0
  332. package/dist/scene/foliage_mask.js.map +1 -0
  333. package/dist/scene/hair.js +15 -4
  334. package/dist/scene/hair.js.map +1 -1
  335. package/dist/scene/light.js +179 -13
  336. package/dist/scene/light.js.map +1 -1
  337. package/dist/scene/mesh.js +327 -45
  338. package/dist/scene/mesh.js.map +1 -1
  339. package/dist/scene/meshdrawable.js +6 -0
  340. package/dist/scene/meshdrawable.js.map +1 -1
  341. package/dist/scene/msdftext.js +9 -3
  342. package/dist/scene/msdftext.js.map +1 -1
  343. package/dist/scene/msdftextsprite.js +9 -3
  344. package/dist/scene/msdftextsprite.js.map +1 -1
  345. package/dist/scene/particlesys.js +8 -2
  346. package/dist/scene/particlesys.js.map +1 -1
  347. package/dist/scene/physics_settings.js +157 -0
  348. package/dist/scene/physics_settings.js.map +1 -0
  349. package/dist/scene/scene.js +190 -44
  350. package/dist/scene/scene.js.map +1 -1
  351. package/dist/scene/scene_node.js +147 -6
  352. package/dist/scene/scene_node.js.map +1 -1
  353. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  354. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  355. package/dist/scene/terrain-cm/grass.js +881 -42
  356. package/dist/scene/terrain-cm/grass.js.map +1 -1
  357. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  358. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  359. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  360. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  361. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  362. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  363. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  364. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  365. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  366. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  367. package/dist/scene/update_queue.js +54 -0
  368. package/dist/scene/update_queue.js.map +1 -0
  369. package/dist/scene/water.js +633 -268
  370. package/dist/scene/water.js.map +1 -1
  371. package/dist/scene/water_surface_sampler.js +324 -0
  372. package/dist/scene/water_surface_sampler.js.map +1 -0
  373. package/dist/scene/wind.js +317 -0
  374. package/dist/scene/wind.js.map +1 -0
  375. package/dist/shaders/atmosphere.js +388 -166
  376. package/dist/shaders/atmosphere.js.map +1 -1
  377. package/dist/shaders/fog.js +100 -32
  378. package/dist/shaders/fog.js.map +1 -1
  379. package/dist/shaders/gi.js +365 -0
  380. package/dist/shaders/gi.js.map +1 -0
  381. package/dist/shaders/ltc_rect.js +202 -0
  382. package/dist/shaders/ltc_rect.js.map +1 -0
  383. package/dist/shaders/misc.js +1 -10
  384. package/dist/shaders/misc.js.map +1 -1
  385. package/dist/shaders/noise.js +5 -1
  386. package/dist/shaders/noise.js.map +1 -1
  387. package/dist/shaders/probes.js +309 -0
  388. package/dist/shaders/probes.js.map +1 -0
  389. package/dist/shaders/sdf.js +537 -0
  390. package/dist/shaders/sdf.js.map +1 -0
  391. package/dist/shaders/shadow.js +104 -70
  392. package/dist/shaders/shadow.js.map +1 -1
  393. package/dist/shaders/skin_brdf.js +243 -0
  394. package/dist/shaders/skin_brdf.js.map +1 -0
  395. package/dist/shaders/ssgi.js +63 -0
  396. package/dist/shaders/ssgi.js.map +1 -0
  397. package/dist/shaders/ssgi_reprojection.js +118 -0
  398. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  399. package/dist/shaders/ssr.js +6 -159
  400. package/dist/shaders/ssr.js.map +1 -1
  401. package/dist/shaders/temporal.js +38 -27
  402. package/dist/shaders/temporal.js.map +1 -1
  403. package/dist/shaders/water.js +32 -82
  404. package/dist/shaders/water.js.map +1 -1
  405. package/dist/shaders/water_medium.js +7 -21
  406. package/dist/shaders/water_medium.js.map +1 -1
  407. package/dist/shadow/dom.js +110 -19
  408. package/dist/shadow/dom.js.map +1 -1
  409. package/dist/shadow/esm.js +3 -3
  410. package/dist/shadow/esm.js.map +1 -1
  411. package/dist/shadow/pcf_opt.js +15 -48
  412. package/dist/shadow/pcf_opt.js.map +1 -1
  413. package/dist/shadow/pcf_pd.js +15 -53
  414. package/dist/shadow/pcf_pd.js.map +1 -1
  415. package/dist/shadow/pcss.js +34 -9
  416. package/dist/shadow/pcss.js.map +1 -1
  417. package/dist/shadow/shadow_impl.js +3 -8
  418. package/dist/shadow/shadow_impl.js.map +1 -1
  419. package/dist/shadow/shadow_region.js +40 -2
  420. package/dist/shadow/shadow_region.js.map +1 -1
  421. package/dist/shadow/shadowmapper.js +93 -53
  422. package/dist/shadow/shadowmapper.js.map +1 -1
  423. package/dist/shadow/ssm.js +18 -72
  424. package/dist/shadow/ssm.js.map +1 -1
  425. package/dist/shadow/vsm.js +3 -3
  426. package/dist/shadow/vsm.js.map +1 -1
  427. package/dist/shapes/shape.js +44 -1
  428. package/dist/shapes/shape.js.map +1 -1
  429. package/dist/utility/buoyancy.js +287 -0
  430. package/dist/utility/buoyancy.js.map +1 -0
  431. package/dist/utility/physical.js +10 -1
  432. package/dist/utility/physical.js.map +1 -1
  433. package/dist/utility/pmrem.js +17 -43
  434. package/dist/utility/pmrem.js.map +1 -1
  435. package/dist/utility/sdf/bake.js +435 -0
  436. package/dist/utility/sdf/bake.js.map +1 -0
  437. package/dist/utility/sdf/bvh.js +576 -0
  438. package/dist/utility/sdf/bvh.js.map +1 -0
  439. package/dist/utility/serialization/manager.js +34 -6
  440. package/dist/utility/serialization/manager.js.map +1 -1
  441. package/dist/utility/serialization/scene/animation.js +46 -5
  442. package/dist/utility/serialization/scene/animation.js.map +1 -1
  443. package/dist/utility/serialization/scene/batch.js +11 -4
  444. package/dist/utility/serialization/scene/batch.js.map +1 -1
  445. package/dist/utility/serialization/scene/camera.js +87 -254
  446. package/dist/utility/serialization/scene/camera.js.map +1 -1
  447. package/dist/utility/serialization/scene/cloth.js +25 -0
  448. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  449. package/dist/utility/serialization/scene/common.js +14 -6
  450. package/dist/utility/serialization/scene/common.js.map +1 -1
  451. package/dist/utility/serialization/scene/foliage.js +821 -0
  452. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  453. package/dist/utility/serialization/scene/hair.js +11 -4
  454. package/dist/utility/serialization/scene/hair.js.map +1 -1
  455. package/dist/utility/serialization/scene/light.js +115 -7
  456. package/dist/utility/serialization/scene/light.js.map +1 -1
  457. package/dist/utility/serialization/scene/material.js +388 -220
  458. package/dist/utility/serialization/scene/material.js.map +1 -1
  459. package/dist/utility/serialization/scene/mesh.js +69 -4
  460. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  461. package/dist/utility/serialization/scene/node.js +140 -5
  462. package/dist/utility/serialization/scene/node.js.map +1 -1
  463. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  464. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  465. package/dist/utility/serialization/scene/particle.js +11 -4
  466. package/dist/utility/serialization/scene/particle.js.map +1 -1
  467. package/dist/utility/serialization/scene/physics.js +120 -0
  468. package/dist/utility/serialization/scene/physics.js.map +1 -0
  469. package/dist/utility/serialization/scene/primitive.js +124 -10
  470. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  471. package/dist/utility/serialization/scene/scene.js +1687 -51
  472. package/dist/utility/serialization/scene/scene.js.map +1 -1
  473. package/dist/utility/serialization/scene/sprite.js +11 -4
  474. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  475. package/dist/utility/serialization/scene/terrain.js +163 -33
  476. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  477. package/dist/utility/serialization/scene/text.js +11 -4
  478. package/dist/utility/serialization/scene/text.js.map +1 -1
  479. package/dist/utility/serialization/scene/water.js +1543 -264
  480. package/dist/utility/serialization/scene/water.js.map +1 -1
  481. package/dist/utility/serialization/types.js.map +1 -1
  482. package/dist/utility/shprojector.js +10 -22
  483. package/dist/utility/shprojector.js.map +1 -1
  484. package/dist/utility/textures/foam.js +170 -0
  485. package/dist/utility/textures/foam.js.map +1 -0
  486. package/dist/utility/textures/ggxlut.js +17 -43
  487. package/dist/utility/textures/ggxlut.js.map +1 -1
  488. package/dist/utility/textures/ltcdata.js +4 -4
  489. package/dist/utility/textures/ltcdata.js.map +1 -1
  490. package/dist/utility/textures/ltclut.js +16 -6
  491. package/dist/utility/textures/ltclut.js.map +1 -1
  492. package/dist/utility/unsupported.js +24 -0
  493. package/dist/utility/unsupported.js.map +1 -0
  494. package/dist/values.js +13 -1
  495. package/dist/values.js.map +1 -1
  496. package/package.json +25 -12
  497. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  498. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  499. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  500. package/src/asset/meshoptimizer/LICENSE +21 -0
  501. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  502. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -0,0 +1,642 @@
1
+ import { Vector4 } from '@zephyr3d/base';
2
+ import { getDevice } from '../../app/api.js';
3
+ import { VoxelMaterialAtlas } from './voxel_atlas.js';
4
+ import { Voxelizer } from './voxelize_pass.js';
5
+ import { VoxelLighting } from './voxel_lighting.js';
6
+ import { buildSDFProgram } from '../sdf/sdf_programs.js';
7
+ import { fetchSampler } from '../../utility/misc.js';
8
+ import { declareGlobalSDFUniforms, declareDynamicSDFUniforms } from '../../shaders/sdf.js';
9
+ import { VOXEL_SCENE_ALBEDO, VOXEL_SCENE_EMISSIVE, VOXEL_SCENE_RADIANCE, VOXEL_SCENE_ANISO0, VOXEL_SCENE_ANISO1, declareVoxelSceneUniforms, voxelSceneTexel, loadVoxelSceneAlbedo, loadVoxelSceneEmissive } from '../../shaders/gi.js';
10
+
11
+ /** Most points per {@link VoxelScene.queryVoxels} call. */ const MAX_QUERY_POINTS = 1024;
12
+ /** Seconds a material's uniforms must have been stable before it is voxelized again. */ const REVOXELIZE_COOLDOWN = 0.5;
13
+ /** Seconds an entry nobody wants is kept before it is forgotten. */ const ENTRY_LIFETIME = 30;
14
+ /**
15
+ * Material side of the scene's voxel representation: each static mesh in the scene SDF
16
+ * is rasterized once per (primitive, material) into a {@link VoxelMaterialAtlas}, and
17
+ * global SDF compositing carries the nearest mesh's albedo and emissive into two clipmaps
18
+ * laid out like the field at half its resolution, giving GI ray hits their colour.
19
+ *
20
+ * Voxelizations are budgeted per frame, nearest first, and redone on material change.
21
+ * Materials that cannot be voxelized (see {@link MeshMaterial.supportsVoxelization}) are
22
+ * skipped. The terrain's albedo comes from its top-down capture, see TerrainGIAlbedo. WebGPU only.
23
+ *
24
+ * @public
25
+ */ class VoxelScene {
26
+ /** Meshes voxelized per frame. */ voxelizeBudget;
27
+ atlas;
28
+ _scene;
29
+ _voxelizer;
30
+ _lighting;
31
+ _albedo;
32
+ _emissive;
33
+ _resolution;
34
+ _levels;
35
+ _entries;
36
+ _time;
37
+ _atlasFull;
38
+ _atlasFullWarned;
39
+ _voxelizations;
40
+ _lastVoxelizations;
41
+ _queryProgram;
42
+ _queryLevels;
43
+ _queryBindGroup;
44
+ _queryPoints;
45
+ _queryOutput;
46
+ _queryChain;
47
+ constructor(scene, atlasSize = 256){
48
+ this._scene = scene;
49
+ this.voxelizeBudget = 8;
50
+ this.atlas = new VoxelMaterialAtlas([
51
+ atlasSize,
52
+ atlasSize,
53
+ atlasSize
54
+ ]);
55
+ this._voxelizer = null;
56
+ this._lighting = null;
57
+ this._albedo = null;
58
+ this._emissive = null;
59
+ this._resolution = 0;
60
+ this._levels = 0;
61
+ this._entries = new Map();
62
+ this._time = 0;
63
+ this._atlasFull = 0;
64
+ this._atlasFullWarned = false;
65
+ this._voxelizations = 0;
66
+ this._lastVoxelizations = 0;
67
+ this._queryProgram = null;
68
+ this._queryLevels = 0;
69
+ this._queryBindGroup = null;
70
+ this._queryPoints = null;
71
+ this._queryOutput = null;
72
+ this._queryChain = Promise.resolve();
73
+ }
74
+ get atlasAlbedo() {
75
+ return this.atlas.albedo;
76
+ }
77
+ get atlasEmissive() {
78
+ return this.atlas.emissive;
79
+ }
80
+ get atlasSize() {
81
+ return this.atlas.size;
82
+ }
83
+ /** Albedo clipmap: rgba8unorm, levels stacked along z, rgb the albedo and a = 1 where a surface is. */ get albedo() {
84
+ if (!this._albedo) {
85
+ throw new Error('VoxelScene: no clipmap before the first update');
86
+ }
87
+ return this._albedo;
88
+ }
89
+ /** Emissive clipmap: rgba16float, levels stacked along z. */ get emissive() {
90
+ if (!this._emissive) {
91
+ throw new Error('VoxelScene: no clipmap before the first update');
92
+ }
93
+ return this._emissive;
94
+ }
95
+ /** Outgoing radiance clipmap: rgba16float, laid out like the albedo; see {@link VoxelLighting}. */ get radiance() {
96
+ if (!this._lighting?.ready) {
97
+ throw new Error('VoxelScene: no radiance before the first lighting update');
98
+ }
99
+ return this._lighting.radiance;
100
+ }
101
+ /** Share of the radiance each voxel face carries, (+x, +y, +z, -x); see declareVoxelSceneUniforms. */ get radianceAniso0() {
102
+ if (!this._lighting?.ready) {
103
+ throw new Error('VoxelScene: no radiance before the first lighting update');
104
+ }
105
+ return this._lighting.aniso0;
106
+ }
107
+ /** Share of the radiance each voxel face carries, (-y, -z) in rg. */ get radianceAniso1() {
108
+ if (!this._lighting?.ready) {
109
+ throw new Error('VoxelScene: no radiance before the first lighting update');
110
+ }
111
+ return this._lighting.aniso1;
112
+ }
113
+ /** True once the radiance clipmap exists. */ get lit() {
114
+ return !!this._lighting?.ready;
115
+ }
116
+ /** Voxels per axis of a clipmap level, half the field's. */ get resolution() {
117
+ return this._resolution;
118
+ }
119
+ get levels() {
120
+ return this._levels;
121
+ }
122
+ /** True once the clipmaps exist. */ get ready() {
123
+ return !!this._albedo;
124
+ }
125
+ getSlot(inst) {
126
+ const key = keyOf(inst.mesh);
127
+ const entry = key ? this._entries.get(key) : null;
128
+ return entry && entry.voxelized ? this.atlas.getSlot(entry) : null;
129
+ }
130
+ /**
131
+ * How the voxel scene holds an instance's material, for tools: `unsupported` when it
132
+ * never will, `unknown` before first wanted, else the voxelization state and atlas slot.
133
+ */ describeInstance(inst) {
134
+ const mesh = inst.mesh;
135
+ const primitive = mesh.primitive;
136
+ const material = mesh.material;
137
+ if (!primitive || !material || primitive.primitiveType !== 'triangle-list' || !material.supportsVoxelization()) {
138
+ return {
139
+ state: 'unsupported',
140
+ voxelized: false,
141
+ slot: null
142
+ };
143
+ }
144
+ const key = keyOf(mesh);
145
+ const entry = key ? this._entries.get(key) : null;
146
+ if (!entry) {
147
+ return {
148
+ state: 'unknown',
149
+ voxelized: false,
150
+ slot: null
151
+ };
152
+ }
153
+ return {
154
+ state: entry.state,
155
+ voxelized: entry.voxelized,
156
+ slot: this.atlas.getSlot(entry)
157
+ };
158
+ }
159
+ getStats() {
160
+ const stats = {
161
+ entries: this._entries.size,
162
+ ready: 0,
163
+ pending: 0,
164
+ failed: 0,
165
+ atlasResident: this.atlas.count,
166
+ atlasOccupancy: this.atlas.occupancy,
167
+ atlasFull: this._atlasFull,
168
+ voxelizations: this._voxelizations,
169
+ lastVoxelizations: this._lastVoxelizations,
170
+ lightingPasses: this._lighting?.passes ?? 0
171
+ };
172
+ for (const entry of this._entries.values()){
173
+ stats[entry.state]++;
174
+ }
175
+ return stats;
176
+ }
177
+ /**
178
+ * Voxelizes meshes that entered the scene field, nearest first within the budget.
179
+ * Called once a frame, before the field's own update.
180
+ */ update(sdf, cameraPos, deltaSeconds) {
181
+ const global = sdf.enabled ? sdf.global : null;
182
+ if (!global) {
183
+ return;
184
+ }
185
+ this._time += deltaSeconds;
186
+ this.ensureClipmaps(global);
187
+ if (global.materials !== this) {
188
+ global.materials = this;
189
+ }
190
+ const wanted = new Map();
191
+ for (const inst of sdf.instances){
192
+ if (inst.mode !== 'static') {
193
+ continue;
194
+ }
195
+ const header = inst.asset?.state === 'ready' ? inst.asset.header : null;
196
+ if (!header) {
197
+ continue;
198
+ }
199
+ const mesh = inst.mesh;
200
+ const primitive = mesh.primitive;
201
+ const material = mesh.material;
202
+ const key = keyOf(mesh);
203
+ if (!key || !primitive || !material || primitive.primitiveType !== 'triangle-list' || !material.supportsVoxelization()) {
204
+ continue;
205
+ }
206
+ let entry = this._entries.get(key);
207
+ if (!entry) {
208
+ const resolved = resolveMaterial(material);
209
+ entry = {
210
+ key,
211
+ primitive,
212
+ material: resolved.material,
213
+ ownsMaterial: resolved.owned,
214
+ source: material,
215
+ resolution: header.resolution.map((v)=>Math.max(1, Math.ceil(v / 2))),
216
+ boxMin: [
217
+ ...header.boxMin
218
+ ],
219
+ voxelSize: header.voxelSize * 2,
220
+ state: 'pending',
221
+ voxelized: false,
222
+ materialTag: '',
223
+ lastWanted: 0,
224
+ readyTime: -Infinity,
225
+ failedVersion: -1
226
+ };
227
+ this._entries.set(key, entry);
228
+ }
229
+ entry.lastWanted = this._time;
230
+ // A material edit shows up in its change tag; wait for the edits to settle
231
+ if (entry.state === 'ready' && entry.materialTag !== materialTagOf(material) && this._time - entry.readyTime > REVOXELIZE_COOLDOWN) {
232
+ entry.state = 'pending';
233
+ }
234
+ const d = distanceToBox(cameraPos, inst.bounds);
235
+ const prev = wanted.get(entry);
236
+ wanted.set(entry, prev === undefined ? d : Math.min(prev, d));
237
+ }
238
+ const candidates = [
239
+ ...wanted.entries()
240
+ ].filter((e)=>e[0].state === 'pending' && e[0].failedVersion !== this.atlas.version).sort((a, b)=>a[1] - b[1]).map((e)=>e[0]);
241
+ let done = 0;
242
+ for (const entry of candidates){
243
+ if (done >= this.voxelizeBudget) {
244
+ break;
245
+ }
246
+ const slot = this.atlas.getSlot(entry) ?? this.place(entry, wanted);
247
+ if (!slot) {
248
+ continue;
249
+ }
250
+ if (entry.ownsMaterial) {
251
+ // A copy carries the values of its making; take them again
252
+ entry.material.dispose();
253
+ const resolved = resolveMaterial(entry.source);
254
+ entry.material = resolved.material;
255
+ entry.ownsMaterial = resolved.owned;
256
+ }
257
+ const ok = this.voxelizer.voxelize(entry.primitive, entry.material, {
258
+ albedo: this.atlas.albedo,
259
+ emissive: this.atlas.emissive,
260
+ slot,
261
+ boxMin: entry.boxMin,
262
+ voxelSize: entry.voxelSize
263
+ });
264
+ entry.state = ok ? 'ready' : 'failed';
265
+ entry.voxelized = ok;
266
+ entry.materialTag = materialTagOf(entry.source);
267
+ entry.readyTime = this._time;
268
+ done++;
269
+ this._voxelizations++;
270
+ this.dirtyInstances(sdf, global, entry.key);
271
+ }
272
+ this._lastVoxelizations = done;
273
+ // Entries nobody has wanted for a while are forgotten
274
+ for (const entry of this._entries.values()){
275
+ if (!wanted.has(entry) && this._time - entry.lastWanted > ENTRY_LIFETIME) {
276
+ this.atlas.remove(entry);
277
+ this._entries.delete(entry.key);
278
+ if (entry.ownsMaterial) {
279
+ entry.material.dispose();
280
+ }
281
+ }
282
+ }
283
+ }
284
+ /**
285
+ * Lights the next slab of voxels. Called once a frame after the field's update,
286
+ * which composites the materials it reads.
287
+ */ updateLighting(sdf, camera, options) {
288
+ const global = sdf.enabled ? sdf.global : null;
289
+ if (!global || !this._albedo || !this._emissive) {
290
+ return;
291
+ }
292
+ if (!this._lighting) {
293
+ this._lighting = new VoxelLighting(this._scene);
294
+ }
295
+ this._lighting.update(global, this._albedo, this._emissive, this._resolution, camera, options);
296
+ }
297
+ /** Stops the global field compositing materials, when it still composites this. */ detach(sdf) {
298
+ const global = sdf.enabled ? sdf.global : null;
299
+ if (global && global.materials === this) {
300
+ global.materials = null;
301
+ }
302
+ }
303
+ /**
304
+ * Reads back what the clipmaps hold at world positions, as a GI ray hit would; resolves
305
+ * a frame or two later. For tools, at most 1024 points.
306
+ */ queryVoxels(global, points) {
307
+ const run = async ()=>{
308
+ const n = Math.min(points.length, MAX_QUERY_POINTS);
309
+ if (n === 0 || !this._albedo || !this._emissive) {
310
+ return [];
311
+ }
312
+ const device = getDevice();
313
+ const pixels = new Float32Array(MAX_QUERY_POINTS * 4 * 3);
314
+ // Recorded at the start of a frame, as the field's distance queries are
315
+ await device.runNextFrameAsync(async ()=>{
316
+ if (!this._queryProgram || this._queryLevels !== global.levels) {
317
+ this._queryProgram?.dispose();
318
+ this._queryBindGroup?.dispose();
319
+ this._queryProgram = this.createQueryProgram(global.levels);
320
+ this._queryLevels = global.levels;
321
+ this._queryBindGroup = device.createBindGroup(this._queryProgram.bindGroupLayouts[0]);
322
+ }
323
+ if (!this._queryPoints) {
324
+ this._queryPoints = device.createBuffer(MAX_QUERY_POINTS * 16, {
325
+ usage: 'uniform',
326
+ storage: true
327
+ });
328
+ this._queryOutput = device.createTexture2D('rgba32f', MAX_QUERY_POINTS, 3, {
329
+ mipmapping: false,
330
+ writable: true
331
+ });
332
+ }
333
+ const data = new Float32Array(MAX_QUERY_POINTS * 4);
334
+ for(let i = 0; i < n; i++){
335
+ data.set([
336
+ points[i].x,
337
+ points[i].y,
338
+ points[i].z,
339
+ 0
340
+ ], i * 4);
341
+ }
342
+ this._queryPoints.bufferSubData(0, data);
343
+ const bg = this._queryBindGroup;
344
+ global.applyBindGroup(bg);
345
+ const lit = this.lit;
346
+ const nearest = fetchSampler('clamp_nearest_nomip');
347
+ bg.setTexture(VOXEL_SCENE_ALBEDO, this._albedo, nearest);
348
+ bg.setTexture(VOXEL_SCENE_EMISSIVE, this._emissive, nearest);
349
+ // Before the first lighting any volume of the layout stands in, the radiance read as zero
350
+ bg.setTexture(VOXEL_SCENE_RADIANCE, lit ? this.radiance : this._emissive, nearest);
351
+ bg.setTexture(VOXEL_SCENE_ANISO0, lit ? this.radianceAniso0 : this._albedo, nearest);
352
+ bg.setTexture(VOXEL_SCENE_ANISO1, lit ? this.radianceAniso1 : this._albedo, nearest);
353
+ bg.setBuffer('points', this._queryPoints);
354
+ bg.setTexture('result', this._queryOutput);
355
+ bg.setValue('count', new Vector4(n, lit ? 1 : 0, 0, 0));
356
+ device.setProgram(this._queryProgram);
357
+ device.setBindGroup(0, bg);
358
+ device.compute(Math.ceil(n / 64), 1, 1);
359
+ const read = this._queryOutput.readPixels(0, 0, MAX_QUERY_POINTS, 3, 0, 0, pixels);
360
+ device.flush();
361
+ await read;
362
+ });
363
+ const row = MAX_QUERY_POINTS * 4;
364
+ return Array.from({
365
+ length: n
366
+ }, (_, i)=>{
367
+ const a = pixels.subarray(i * 4, i * 4 + 4);
368
+ const e = pixels.subarray(row + i * 4, row + i * 4 + 4);
369
+ const r = pixels.subarray(2 * row + i * 4, 2 * row + i * 4 + 4);
370
+ return {
371
+ level: Math.round(e[3]),
372
+ albedo: [
373
+ a[0],
374
+ a[1],
375
+ a[2],
376
+ a[3]
377
+ ],
378
+ emissive: [
379
+ e[0],
380
+ e[1],
381
+ e[2]
382
+ ],
383
+ radiance: [
384
+ r[0],
385
+ r[1],
386
+ r[2]
387
+ ]
388
+ };
389
+ });
390
+ };
391
+ const next = this._queryChain.then(run, run);
392
+ this._queryChain = next.catch(()=>undefined);
393
+ return next;
394
+ }
395
+ dispose() {
396
+ this._queryProgram?.dispose();
397
+ this._queryBindGroup?.dispose();
398
+ this._queryPoints?.dispose();
399
+ this._queryOutput?.dispose();
400
+ this._queryProgram = null;
401
+ this._queryBindGroup = null;
402
+ this._queryPoints = null;
403
+ this._queryOutput = null;
404
+ this._voxelizer?.dispose();
405
+ this._voxelizer = null;
406
+ this._lighting?.dispose();
407
+ this._lighting = null;
408
+ this.atlas.dispose();
409
+ this._albedo?.dispose();
410
+ this._emissive?.dispose();
411
+ this._albedo = null;
412
+ this._emissive = null;
413
+ for (const entry of this._entries.values()){
414
+ if (entry.ownsMaterial) {
415
+ entry.material.dispose();
416
+ }
417
+ }
418
+ this._entries.clear();
419
+ }
420
+ /** @internal */ createQueryProgram(levels) {
421
+ return buildSDFProgram({
422
+ label: 'VoxelSceneQuery',
423
+ workgroupSize: [
424
+ 64,
425
+ 1,
426
+ 1
427
+ ],
428
+ compute (pb) {
429
+ this.points = pb.vec4[0]().storageBufferReadonly(0);
430
+ // (point count, 1 once lit)
431
+ this.count = pb.vec4().uniform(0);
432
+ this.result = pb.texStorage2D.rgba32float().storage(0);
433
+ declareGlobalSDFUniforms(this, 0, levels);
434
+ declareDynamicSDFUniforms(this, 0);
435
+ declareVoxelSceneUniforms(this, 0);
436
+ pb.main(function() {
437
+ this.$l.i = this.$builtins.globalInvocationId.x;
438
+ this.$if(pb.lessThan(this.i, pb.uint(this.count.x)), function() {
439
+ this.$l.texel = voxelSceneTexel(this, this.points.at(this.i).xyz, levels);
440
+ this.$l.radiance = pb.vec3(0);
441
+ this.$if(pb.and(pb.greaterThanEqual(this.texel.w, 0), pb.greaterThan(this.count.y, 0)), function() {
442
+ this.radiance = pb.textureLoad(this[VOXEL_SCENE_RADIANCE], this.texel.xyz, 0).rgb;
443
+ });
444
+ pb.textureStore(this.result, pb.uvec2(this.i, 0), loadVoxelSceneAlbedo(this, this.texel));
445
+ pb.textureStore(this.result, pb.uvec2(this.i, 1), pb.vec4(loadVoxelSceneEmissive(this, this.texel), pb.float(this.texel.w)));
446
+ pb.textureStore(this.result, pb.uvec2(this.i, 2), pb.vec4(this.radiance, 0));
447
+ });
448
+ });
449
+ }
450
+ });
451
+ }
452
+ /** @internal */ get voxelizer() {
453
+ if (!this._voxelizer) {
454
+ this._voxelizer = new Voxelizer(this._scene);
455
+ }
456
+ return this._voxelizer;
457
+ }
458
+ /** @internal */ ensureClipmaps(global) {
459
+ const resolution = global.resolution / 2;
460
+ if (this._albedo && this._resolution === resolution && this._levels === global.levels) {
461
+ return;
462
+ }
463
+ this._albedo?.dispose();
464
+ this._emissive?.dispose();
465
+ const device = getDevice();
466
+ this._resolution = resolution;
467
+ this._levels = global.levels;
468
+ this._albedo = device.createTexture3D('rgba8unorm', resolution, resolution, resolution * global.levels, {
469
+ mipmapping: false,
470
+ writable: true
471
+ });
472
+ this._albedo.name = '@VoxelSceneAlbedo';
473
+ this._emissive = device.createTexture3D('rgba16f', resolution, resolution, resolution * global.levels, {
474
+ mipmapping: false,
475
+ writable: true
476
+ });
477
+ this._emissive.name = '@VoxelSceneEmissive';
478
+ // The field must write the new textures everywhere
479
+ if (global.materials === this) {
480
+ global.materials = null;
481
+ global.materials = this;
482
+ }
483
+ }
484
+ /**
485
+ * A slot for an entry, evicting unwanted meshes then farther wanted ones when full.
486
+ * Nearer meshes are never evicted for it, so meshes that don't all fit don't thrash.
487
+ * @internal
488
+ */ place(entry, wanted) {
489
+ let slot = this.atlas.add(entry, entry.resolution);
490
+ if (slot) {
491
+ return slot;
492
+ }
493
+ const resident = [
494
+ ...this._entries.values()
495
+ ].filter((e)=>e !== entry && this.atlas.getSlot(e));
496
+ const dist = wanted.get(entry);
497
+ const kept = resident.filter((e)=>wanted.has(e) && wanted.get(e) <= dist);
498
+ if (!this.atlas.fits([
499
+ entry.resolution,
500
+ ...kept.map((e)=>e.resolution)
501
+ ])) {
502
+ this.fail(entry);
503
+ return null;
504
+ }
505
+ const victims = [
506
+ ...resident.filter((e)=>!wanted.has(e)).sort((a, b)=>a.lastWanted - b.lastWanted),
507
+ ...resident.filter((e)=>wanted.get(e) > dist).sort((a, b)=>wanted.get(b) - wanted.get(a))
508
+ ];
509
+ for (const victim of victims){
510
+ this.atlas.remove(victim);
511
+ victim.state = 'pending';
512
+ victim.voxelized = false;
513
+ slot = this.atlas.add(entry, entry.resolution);
514
+ if (slot) {
515
+ return slot;
516
+ }
517
+ }
518
+ // Fits packed afresh but not around the freed gaps: repack, re-rasterizing only those moved
519
+ const moved = this.atlas.repack([
520
+ entry,
521
+ ...kept
522
+ ].map((e)=>({
523
+ key: e,
524
+ resolution: e.resolution
525
+ })));
526
+ if (moved) {
527
+ for (const e of this._entries.values()){
528
+ if (e !== entry && e.voxelized && (moved.has(e) || !this.atlas.getSlot(e))) {
529
+ e.voxelized = false;
530
+ e.state = 'pending';
531
+ }
532
+ }
533
+ return this.atlas.getSlot(entry);
534
+ }
535
+ this.fail(entry);
536
+ return null;
537
+ }
538
+ /** Records an entry that found no room, not to be tried until the atlas changes. @internal */ fail(entry) {
539
+ entry.failedVersion = this.atlas.version;
540
+ this._atlasFull++;
541
+ if (!this._atlasFullWarned) {
542
+ this._atlasFullWarned = true;
543
+ const s = this.atlas.size;
544
+ console.warn(`VoxelScene: the materials of the meshes in the scene field do not fit the ${s.join('×')} material atlas; the farthest are left out and read black where global illumination rays hit them. Raise SceneGI.atlasSize.`);
545
+ }
546
+ }
547
+ /** Rebuilds the field around every instance drawing a (primitive, material). @internal */ dirtyInstances(sdf, global, key) {
548
+ for (const inst of sdf.instances){
549
+ if (inst.mode === 'static' && keyOf(inst.mesh) === key && boxValid(inst.bounds)) {
550
+ global.markDirty(inst.bounds.minPoint, inst.bounds.maxPoint);
551
+ }
552
+ }
553
+ }
554
+ }
555
+ /**
556
+ * Identity of what a mesh voxelizes to: primitive plus core material, with a material
557
+ * instance's overridden uniform values appended so differently tinted instances differ.
558
+ */ function keyOf(mesh) {
559
+ const primitive = mesh.primitive;
560
+ const material = mesh.material;
561
+ if (!primitive || !material) {
562
+ return null;
563
+ }
564
+ const core = material.coreMaterial;
565
+ return `${primitive.id}:${core.instanceId}${instanceSuffix(material)}`;
566
+ }
567
+ /**
568
+ * What a voxelization depends on in a material: the core's appearance tag (look-changing
569
+ * edits, not the per-frame picking color) and change tag (texture loads).
570
+ */ function materialTagOf(material) {
571
+ const core = material.coreMaterial;
572
+ return `${core.appearanceTag}:${core.changeTag}`;
573
+ }
574
+ /** The instance uniform values a material instance overrides its core with, as a key suffix, else empty. */ function instanceSuffix(material) {
575
+ if (!material.$isInstance) {
576
+ return '';
577
+ }
578
+ const core = material.coreMaterial;
579
+ const parts = [];
580
+ for (const { prop } of core.getInstancedUniforms()){
581
+ const a = material[prop];
582
+ const b = core[prop];
583
+ if (!sameValue(a, b)) {
584
+ parts.push(`${prop}=${String(a)}`);
585
+ }
586
+ }
587
+ return parts.length ? `:${parts.join(',')}` : '';
588
+ }
589
+ function sameValue(a, b) {
590
+ if (typeof a === 'number' || typeof b === 'number') {
591
+ return a === b;
592
+ }
593
+ const va = a;
594
+ const vb = b;
595
+ if (!va || !vb || va.length !== vb.length) {
596
+ return a === b;
597
+ }
598
+ for(let i = 0; i < va.length; i++){
599
+ if (va[i] !== vb[i]) {
600
+ return false;
601
+ }
602
+ }
603
+ return true;
604
+ }
605
+ /**
606
+ * The material to draw: the core, or for an instance with overrides a copy of the core
607
+ * carrying its values, since the voxelize pass draws non-instanced.
608
+ */ function resolveMaterial(material) {
609
+ if (!material.$isInstance || !instanceSuffix(material)) {
610
+ return {
611
+ material: material.coreMaterial,
612
+ owned: false
613
+ };
614
+ }
615
+ const core = material.coreMaterial;
616
+ const copy = core.clone?.();
617
+ if (!copy) {
618
+ return {
619
+ material: core,
620
+ owned: false
621
+ };
622
+ }
623
+ for (const { prop } of core.getInstancedUniforms()){
624
+ copy[prop] = material[prop];
625
+ }
626
+ return {
627
+ material: copy,
628
+ owned: true
629
+ };
630
+ }
631
+ function boxValid(box) {
632
+ return box.minPoint.x <= box.maxPoint.x;
633
+ }
634
+ function distanceToBox(p, box) {
635
+ const dx = Math.max(box.minPoint.x - p.x, 0, p.x - box.maxPoint.x);
636
+ const dy = Math.max(box.minPoint.y - p.y, 0, p.y - box.maxPoint.y);
637
+ const dz = Math.max(box.minPoint.z - p.z, 0, p.z - box.maxPoint.z);
638
+ return Math.hypot(dx, dy, dz);
639
+ }
640
+
641
+ export { VoxelScene };
642
+ //# sourceMappingURL=voxel_scene.js.map