@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.
- package/README.md +60 -27
- package/dist/animation/animation_bank.js +634 -0
- package/dist/animation/animation_bank.js.map +1 -0
- package/dist/animation/animation_bank_gpu.js +256 -0
- package/dist/animation/animation_bank_gpu.js.map +1 -0
- package/dist/animation/animationset.js +54 -0
- package/dist/animation/animationset.js.map +1 -1
- package/dist/animation/cloth/gpu_cloth_component.js +406 -0
- package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
- package/dist/animation/cloth/gpu_cloth_system.js +332 -202
- package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
- package/dist/animation/gpu_animation_driver.js +289 -0
- package/dist/animation/gpu_animation_driver.js.map +1 -0
- package/dist/animation/joint_dynamics/collision.js +112 -1
- package/dist/animation/joint_dynamics/collision.js.map +1 -1
- package/dist/animation/joint_dynamics/controller.js +6 -0
- package/dist/animation/joint_dynamics/controller.js.map +1 -1
- package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
- package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
- package/dist/animation/joint_dynamics/solver.js +50 -12
- package/dist/animation/joint_dynamics/solver.js.map +1 -1
- package/dist/animation/joint_dynamics/types.js.map +1 -1
- package/dist/animation/skeleton.js +279 -55
- package/dist/animation/skeleton.js.map +1 -1
- package/dist/animation/skin_palette_atlas.js +252 -0
- package/dist/animation/skin_palette_atlas.js.map +1 -0
- package/dist/animation/spring/multi_chain_spring_system.js +298 -38
- package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
- package/dist/animation/spring/spring_chain.js +2 -0
- package/dist/animation/spring/spring_chain.js.map +1 -1
- package/dist/animation/spring/spring_collider.js +159 -21
- package/dist/animation/spring/spring_collider.js.map +1 -1
- package/dist/animation/spring/spring_particle.js +1 -0
- package/dist/animation/spring/spring_particle.js.map +1 -1
- package/dist/animation/spring/spring_solver.js +173 -0
- package/dist/animation/spring/spring_solver.js.map +1 -0
- package/dist/animation/spring/spring_system.js +249 -24
- package/dist/animation/spring/spring_system.js.map +1 -1
- package/dist/animation/spring_modifier.js +32 -1
- package/dist/animation/spring_modifier.js.map +1 -1
- package/dist/app/app.js +26 -0
- package/dist/app/app.js.map +1 -1
- package/dist/app/engine.js +86 -15
- package/dist/app/engine.js.map +1 -1
- package/dist/app/gamepad.js +191 -0
- package/dist/app/gamepad.js.map +1 -0
- package/dist/app/inputactions.js +271 -0
- package/dist/app/inputactions.js.map +1 -0
- package/dist/app/inputmgr.js +331 -22
- package/dist/app/inputmgr.js.map +1 -1
- package/dist/app/loading.js +138 -0
- package/dist/app/loading.js.map +1 -0
- package/dist/app/pipelinecache.js +209 -0
- package/dist/app/pipelinecache.js.map +1 -0
- package/dist/app/runtimescript.js +25 -0
- package/dist/app/runtimescript.js.map +1 -1
- package/dist/app/scriptingsystem.js +54 -0
- package/dist/app/scriptingsystem.js.map +1 -1
- package/dist/app/scriptregistry.js +7 -2
- package/dist/app/scriptregistry.js.map +1 -1
- package/dist/asset/asset_manifest.js +59 -0
- package/dist/asset/asset_manifest.js.map +1 -0
- package/dist/asset/asset_preload.js +258 -0
- package/dist/asset/asset_preload.js.map +1 -0
- package/dist/asset/assetmanager.js +117 -65
- package/dist/asset/assetmanager.js.map +1 -1
- package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/dist/asset/loaders/ktx2/basis_location.js +17 -0
- package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
- package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
- package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
- package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
- package/dist/asset/mesh_lod_builder.js +104 -0
- package/dist/asset/mesh_lod_builder.js.map +1 -0
- package/dist/asset/mesh_settings.js +111 -0
- package/dist/asset/mesh_settings.js.map +1 -0
- package/dist/asset/meshopt_decoder.js +18 -0
- package/dist/asset/meshopt_decoder.js.map +1 -0
- package/dist/asset/meshopt_simplifier.js +26 -0
- package/dist/asset/meshopt_simplifier.js.map +1 -0
- package/dist/asset/model.js +171 -1
- package/dist/asset/model.js.map +1 -1
- package/dist/asset/texture_settings.js +231 -0
- package/dist/asset/texture_settings.js.map +1 -0
- package/dist/asset/zmsh_binary.js +131 -0
- package/dist/asset/zmsh_binary.js.map +1 -0
- package/dist/asset/zsdf_binary.js +111 -0
- package/dist/asset/zsdf_binary.js.map +1 -0
- package/dist/blitter/bilateralblur.js +1 -2
- package/dist/blitter/bilateralblur.js.map +1 -1
- package/dist/blitter/gaussianblur.js +1 -6
- package/dist/blitter/gaussianblur.js.map +1 -1
- package/dist/camera/base.js +31 -10
- package/dist/camera/base.js.map +1 -1
- package/dist/camera/camera.js +104 -178
- package/dist/camera/camera.js.map +1 -1
- package/dist/camera/follow.js +342 -0
- package/dist/camera/follow.js.map +1 -0
- package/dist/camera/fps.js +9 -7
- package/dist/camera/fps.js.map +1 -1
- package/dist/camera/orbit.js +46 -19
- package/dist/camera/orbit.js.map +1 -1
- package/dist/index.d.ts +25436 -15990
- package/dist/index.js +65 -11
- package/dist/index.js.map +1 -1
- package/dist/material/blinn.js +3 -0
- package/dist/material/blinn.js.map +1 -1
- package/dist/material/eye.js +1 -1
- package/dist/material/eye.js.map +1 -1
- package/dist/material/hair.js +2 -3
- package/dist/material/hair.js.map +1 -1
- package/dist/material/lambert.js +4 -1
- package/dist/material/lambert.js.map +1 -1
- package/dist/material/material.js +66 -4
- package/dist/material/material.js.map +1 -1
- package/dist/material/meshmaterial.js +118 -45
- package/dist/material/meshmaterial.js.map +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
- package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
- package/dist/material/mixins/lightmodel/lambert.js +1 -1
- package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
- package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
- package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
- package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
- package/dist/material/mixins/lit.js +191 -83
- package/dist/material/mixins/lit.js.map +1 -1
- package/dist/material/mixins/pbr/common.js +31 -206
- package/dist/material/mixins/pbr/common.js.map +1 -1
- package/dist/material/mtoon.js +1 -1
- package/dist/material/mtoon.js.map +1 -1
- package/dist/material/pbrmr.js +3 -0
- package/dist/material/pbrmr.js.map +1 -1
- package/dist/material/pbrsg.js +3 -0
- package/dist/material/pbrsg.js.map +1 -1
- package/dist/material/sdf_debug.js +78 -0
- package/dist/material/sdf_debug.js.map +1 -0
- package/dist/material/shader/helper.js +333 -191
- package/dist/material/shader/helper.js.map +1 -1
- package/dist/material/shader/terrain_blend.js +204 -43
- package/dist/material/shader/terrain_blend.js.map +1 -1
- package/dist/material/skin.js +331 -297
- package/dist/material/skin.js.map +1 -1
- package/dist/material/skinprofile.js +1058 -0
- package/dist/material/skinprofile.js.map +1 -0
- package/dist/material/sss.js +353 -0
- package/dist/material/sss.js.map +1 -0
- package/dist/material/sss_kernel.js +265 -0
- package/dist/material/sss_kernel.js.map +1 -0
- package/dist/material/sssprofile.js +879 -0
- package/dist/material/sssprofile.js.map +1 -0
- package/dist/material/subsurfaceprofile.js +4 -8
- package/dist/material/subsurfaceprofile.js.map +1 -1
- package/dist/material/terrain-cm.js +464 -188
- package/dist/material/terrain-cm.js.map +1 -1
- package/dist/material/unlit.js +3 -0
- package/dist/material/unlit.js.map +1 -1
- package/dist/material/water.js +1261 -1438
- package/dist/material/water.js.map +1 -1
- package/dist/node_modules/meshoptimizer/LICENSE +21 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
- package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
- package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
- package/dist/physics/character.js +226 -0
- package/dist/physics/character.js.map +1 -0
- package/dist/physics/collider.js +209 -0
- package/dist/physics/collider.js.map +1 -0
- package/dist/physics/events.js +79 -0
- package/dist/physics/events.js.map +1 -0
- package/dist/physics/joint.js +272 -0
- package/dist/physics/joint.js.map +1 -0
- package/dist/physics/node_physics.js +234 -0
- package/dist/physics/node_physics.js.map +1 -0
- package/dist/physics/part.js +91 -0
- package/dist/physics/part.js.map +1 -0
- package/dist/physics/rigid_body.js +379 -0
- package/dist/physics/rigid_body.js.map +1 -0
- package/dist/physics/vehicle.js +335 -0
- package/dist/physics/vehicle.js.map +1 -0
- package/dist/physics/world.js +25 -0
- package/dist/physics/world.js.map +1 -0
- package/dist/posteffect/bloom.js +49 -14
- package/dist/posteffect/bloom.js.map +1 -1
- package/dist/posteffect/motionblur.js +106 -106
- package/dist/posteffect/motionblur.js.map +1 -1
- package/dist/posteffect/postsss.js +572 -0
- package/dist/posteffect/postsss.js.map +1 -0
- package/dist/posteffect/sao.js +2 -6
- package/dist/posteffect/sao.js.map +1 -1
- package/dist/posteffect/skinsss.js +605 -355
- package/dist/posteffect/skinsss.js.map +1 -1
- package/dist/posteffect/ssgi.js +91 -162
- package/dist/posteffect/ssgi.js.map +1 -1
- package/dist/posteffect/ssr.js +3 -11
- package/dist/posteffect/ssr.js.map +1 -1
- package/dist/posteffect/sss.js +4 -13
- package/dist/posteffect/sss.js.map +1 -1
- package/dist/posteffect/taa.js +1 -0
- package/dist/posteffect/taa.js.map +1 -1
- package/dist/render/abuffer_oit.js +3 -2
- package/dist/render/abuffer_oit.js.map +1 -1
- package/dist/render/clipmap.js +179 -64
- package/dist/render/clipmap.js.map +1 -1
- package/dist/render/cluster_light.js +958 -224
- package/dist/render/cluster_light.js.map +1 -1
- package/dist/render/cull_visitor.js +25 -5
- package/dist/render/cull_visitor.js.map +1 -1
- package/dist/render/debug_views.js +37 -0
- package/dist/render/debug_views.js.map +1 -0
- package/dist/render/depthpass.js +5 -1
- package/dist/render/depthpass.js.map +1 -1
- package/dist/render/drawable_mixin.js +53 -6
- package/dist/render/drawable_mixin.js.map +1 -1
- package/dist/render/dualdepthpeeling_oit.js +5 -5
- package/dist/render/dualdepthpeeling_oit.js.map +1 -1
- package/dist/render/envlight.js +196 -113
- package/dist/render/envlight.js.map +1 -1
- package/dist/render/fbm_wavegenerator.js +5 -10
- package/dist/render/fbm_wavegenerator.js.map +1 -1
- package/dist/render/fft_wavegenerator.js +247 -157
- package/dist/render/fft_wavegenerator.js.map +1 -1
- package/dist/render/gerstner_wavegenerator.js +16 -38
- package/dist/render/gerstner_wavegenerator.js.map +1 -1
- package/dist/render/gi/probe_volume.js +1334 -0
- package/dist/render/gi/probe_volume.js.map +1 -0
- package/dist/render/gi/scene_gi.js +282 -0
- package/dist/render/gi/scene_gi.js.map +1 -0
- package/dist/render/gi/voxel_atlas.js +198 -0
- package/dist/render/gi/voxel_atlas.js.map +1 -0
- package/dist/render/gi/voxel_lighting.js +652 -0
- package/dist/render/gi/voxel_lighting.js.map +1 -0
- package/dist/render/gi/voxel_scene.js +642 -0
- package/dist/render/gi/voxel_scene.js.map +1 -0
- package/dist/render/gi/voxelize_pass.js +223 -0
- package/dist/render/gi/voxelize_pass.js.map +1 -0
- package/dist/render/globalbindgroup_allocator.js +3 -2
- package/dist/render/globalbindgroup_allocator.js.map +1 -1
- package/dist/render/gpu_picking.js +9 -36
- package/dist/render/gpu_picking.js.map +1 -1
- package/dist/render/instance_culling.js +499 -0
- package/dist/render/instance_culling.js.map +1 -0
- package/dist/render/lightpass.js +19 -8
- package/dist/render/lightpass.js.map +1 -1
- package/dist/render/lod.js +46 -0
- package/dist/render/lod.js.map +1 -0
- package/dist/render/primitive.js +301 -9
- package/dist/render/primitive.js.map +1 -1
- package/dist/render/primitive_readback.js +209 -0
- package/dist/render/primitive_readback.js.map +1 -0
- package/dist/render/render_queue.js +162 -11
- package/dist/render/render_queue.js.map +1 -1
- package/dist/render/renderer.js +10 -7
- package/dist/render/renderer.js.map +1 -1
- package/dist/render/rendergraph/blackboard.js +14 -1
- package/dist/render/rendergraph/blackboard.js.map +1 -1
- package/dist/render/rendergraph/executor.js +136 -0
- package/dist/render/rendergraph/executor.js.map +1 -1
- package/dist/render/rendergraph/forward_plus_builder.js +272 -55
- package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
- package/dist/render/rendergraph/frame_graph_context.js +41 -0
- package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
- package/dist/render/rendergraph/scene_render_context.js +31 -2
- package/dist/render/rendergraph/scene_render_context.js.map +1 -1
- package/dist/render/rendergraph/types.js.map +1 -1
- package/dist/render/renderpass.js +28 -5
- package/dist/render/renderpass.js.map +1 -1
- package/dist/render/sdf/box_allocator.js +98 -0
- package/dist/render/sdf/box_allocator.js.map +1 -0
- package/dist/render/sdf/global_sdf.js +865 -0
- package/dist/render/sdf/global_sdf.js.map +1 -0
- package/dist/render/sdf/scene_sdf.js +562 -0
- package/dist/render/sdf/scene_sdf.js.map +1 -0
- package/dist/render/sdf/sdf_atlas.js +227 -0
- package/dist/render/sdf/sdf_atlas.js.map +1 -0
- package/dist/render/sdf/sdf_programs.js +42 -0
- package/dist/render/sdf/sdf_programs.js.map +1 -0
- package/dist/render/sdf/sdf_view.js +199 -0
- package/dist/render/sdf/sdf_view.js.map +1 -0
- package/dist/render/sdf/waterline.js +610 -0
- package/dist/render/sdf/waterline.js.map +1 -0
- package/dist/render/shadow_mask_pass.js +142 -25
- package/dist/render/shadow_mask_pass.js.map +1 -1
- package/dist/render/shore_wave_generator.js +1193 -0
- package/dist/render/shore_wave_generator.js.map +1 -0
- package/dist/render/sky.js +516 -86
- package/dist/render/sky.js.map +1 -1
- package/dist/render/transmission_thickness_pass.js +477 -0
- package/dist/render/transmission_thickness_pass.js.map +1 -0
- package/dist/render/underwater.js +58 -158
- package/dist/render/underwater.js.map +1 -1
- package/dist/render/virtualtexture/virtual_texture.js +1214 -0
- package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_common.js +472 -0
- package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
- package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
- package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
- package/dist/render/volumetric_cloud/debug_view.js +131 -0
- package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
- package/dist/render/volumetric_cloud/resources.js +380 -0
- package/dist/render/volumetric_cloud/resources.js.map +1 -0
- package/dist/render/volumetric_cloud/sky_cache.js +380 -0
- package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
- package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
- package/dist/render/water_caustics.js +134 -319
- package/dist/render/water_caustics.js.map +1 -1
- package/dist/render/water_foam.js +627 -0
- package/dist/render/water_foam.js.map +1 -0
- package/dist/render/water_interaction.js +1795 -0
- package/dist/render/water_interaction.js.map +1 -0
- package/dist/render/weightedblended_oit.js +3 -3
- package/dist/render/weightedblended_oit.js.map +1 -1
- package/dist/scene/basesprite.js +9 -4
- package/dist/scene/basesprite.js.map +1 -1
- package/dist/scene/batchgroup.js +108 -12
- package/dist/scene/batchgroup.js.map +1 -1
- package/dist/scene/environment.js +28 -7
- package/dist/scene/environment.js.map +1 -1
- package/dist/scene/foliage.js +1020 -0
- package/dist/scene/foliage.js.map +1 -0
- package/dist/scene/foliage_buckets.js +147 -0
- package/dist/scene/foliage_buckets.js.map +1 -0
- package/dist/scene/foliage_mask.js +358 -0
- package/dist/scene/foliage_mask.js.map +1 -0
- package/dist/scene/hair.js +15 -4
- package/dist/scene/hair.js.map +1 -1
- package/dist/scene/light.js +179 -13
- package/dist/scene/light.js.map +1 -1
- package/dist/scene/mesh.js +327 -45
- package/dist/scene/mesh.js.map +1 -1
- package/dist/scene/meshdrawable.js +6 -0
- package/dist/scene/meshdrawable.js.map +1 -1
- package/dist/scene/msdftext.js +9 -3
- package/dist/scene/msdftext.js.map +1 -1
- package/dist/scene/msdftextsprite.js +9 -3
- package/dist/scene/msdftextsprite.js.map +1 -1
- package/dist/scene/particlesys.js +8 -2
- package/dist/scene/particlesys.js.map +1 -1
- package/dist/scene/physics_settings.js +157 -0
- package/dist/scene/physics_settings.js.map +1 -0
- package/dist/scene/scene.js +190 -44
- package/dist/scene/scene.js.map +1 -1
- package/dist/scene/scene_node.js +147 -6
- package/dist/scene/scene_node.js.map +1 -1
- package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
- package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
- package/dist/scene/terrain-cm/grass.js +881 -42
- package/dist/scene/terrain-cm/grass.js.map +1 -1
- package/dist/scene/terrain-cm/grass_gpu.js +929 -0
- package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
- package/dist/scene/terrain-cm/grassmaterial.js +180 -9
- package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
- package/dist/scene/terrain-cm/terrain-cm.js +465 -36
- package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
- package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
- package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
- package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
- package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
- package/dist/scene/update_queue.js +54 -0
- package/dist/scene/update_queue.js.map +1 -0
- package/dist/scene/water.js +633 -268
- package/dist/scene/water.js.map +1 -1
- package/dist/scene/water_surface_sampler.js +324 -0
- package/dist/scene/water_surface_sampler.js.map +1 -0
- package/dist/scene/wind.js +317 -0
- package/dist/scene/wind.js.map +1 -0
- package/dist/shaders/atmosphere.js +388 -166
- package/dist/shaders/atmosphere.js.map +1 -1
- package/dist/shaders/fog.js +100 -32
- package/dist/shaders/fog.js.map +1 -1
- package/dist/shaders/gi.js +365 -0
- package/dist/shaders/gi.js.map +1 -0
- package/dist/shaders/ltc_rect.js +202 -0
- package/dist/shaders/ltc_rect.js.map +1 -0
- package/dist/shaders/misc.js +1 -10
- package/dist/shaders/misc.js.map +1 -1
- package/dist/shaders/noise.js +5 -1
- package/dist/shaders/noise.js.map +1 -1
- package/dist/shaders/probes.js +309 -0
- package/dist/shaders/probes.js.map +1 -0
- package/dist/shaders/sdf.js +537 -0
- package/dist/shaders/sdf.js.map +1 -0
- package/dist/shaders/shadow.js +104 -70
- package/dist/shaders/shadow.js.map +1 -1
- package/dist/shaders/skin_brdf.js +243 -0
- package/dist/shaders/skin_brdf.js.map +1 -0
- package/dist/shaders/ssgi.js +63 -0
- package/dist/shaders/ssgi.js.map +1 -0
- package/dist/shaders/ssgi_reprojection.js +118 -0
- package/dist/shaders/ssgi_reprojection.js.map +1 -0
- package/dist/shaders/ssr.js +6 -159
- package/dist/shaders/ssr.js.map +1 -1
- package/dist/shaders/temporal.js +38 -27
- package/dist/shaders/temporal.js.map +1 -1
- package/dist/shaders/water.js +32 -82
- package/dist/shaders/water.js.map +1 -1
- package/dist/shaders/water_medium.js +7 -21
- package/dist/shaders/water_medium.js.map +1 -1
- package/dist/shadow/dom.js +110 -19
- package/dist/shadow/dom.js.map +1 -1
- package/dist/shadow/esm.js +3 -3
- package/dist/shadow/esm.js.map +1 -1
- package/dist/shadow/pcf_opt.js +15 -48
- package/dist/shadow/pcf_opt.js.map +1 -1
- package/dist/shadow/pcf_pd.js +15 -53
- package/dist/shadow/pcf_pd.js.map +1 -1
- package/dist/shadow/pcss.js +34 -9
- package/dist/shadow/pcss.js.map +1 -1
- package/dist/shadow/shadow_impl.js +3 -8
- package/dist/shadow/shadow_impl.js.map +1 -1
- package/dist/shadow/shadow_region.js +40 -2
- package/dist/shadow/shadow_region.js.map +1 -1
- package/dist/shadow/shadowmapper.js +93 -53
- package/dist/shadow/shadowmapper.js.map +1 -1
- package/dist/shadow/ssm.js +18 -72
- package/dist/shadow/ssm.js.map +1 -1
- package/dist/shadow/vsm.js +3 -3
- package/dist/shadow/vsm.js.map +1 -1
- package/dist/shapes/shape.js +44 -1
- package/dist/shapes/shape.js.map +1 -1
- package/dist/utility/buoyancy.js +287 -0
- package/dist/utility/buoyancy.js.map +1 -0
- package/dist/utility/physical.js +10 -1
- package/dist/utility/physical.js.map +1 -1
- package/dist/utility/pmrem.js +17 -43
- package/dist/utility/pmrem.js.map +1 -1
- package/dist/utility/sdf/bake.js +435 -0
- package/dist/utility/sdf/bake.js.map +1 -0
- package/dist/utility/sdf/bvh.js +576 -0
- package/dist/utility/sdf/bvh.js.map +1 -0
- package/dist/utility/serialization/manager.js +34 -6
- package/dist/utility/serialization/manager.js.map +1 -1
- package/dist/utility/serialization/scene/animation.js +46 -5
- package/dist/utility/serialization/scene/animation.js.map +1 -1
- package/dist/utility/serialization/scene/batch.js +11 -4
- package/dist/utility/serialization/scene/batch.js.map +1 -1
- package/dist/utility/serialization/scene/camera.js +87 -254
- package/dist/utility/serialization/scene/camera.js.map +1 -1
- package/dist/utility/serialization/scene/cloth.js +25 -0
- package/dist/utility/serialization/scene/cloth.js.map +1 -0
- package/dist/utility/serialization/scene/common.js +14 -6
- package/dist/utility/serialization/scene/common.js.map +1 -1
- package/dist/utility/serialization/scene/foliage.js +821 -0
- package/dist/utility/serialization/scene/foliage.js.map +1 -0
- package/dist/utility/serialization/scene/hair.js +11 -4
- package/dist/utility/serialization/scene/hair.js.map +1 -1
- package/dist/utility/serialization/scene/light.js +115 -7
- package/dist/utility/serialization/scene/light.js.map +1 -1
- package/dist/utility/serialization/scene/material.js +388 -220
- package/dist/utility/serialization/scene/material.js.map +1 -1
- package/dist/utility/serialization/scene/mesh.js +69 -4
- package/dist/utility/serialization/scene/mesh.js.map +1 -1
- package/dist/utility/serialization/scene/node.js +140 -5
- package/dist/utility/serialization/scene/node.js.map +1 -1
- package/dist/utility/serialization/scene/node_physics.js +1318 -0
- package/dist/utility/serialization/scene/node_physics.js.map +1 -0
- package/dist/utility/serialization/scene/particle.js +11 -4
- package/dist/utility/serialization/scene/particle.js.map +1 -1
- package/dist/utility/serialization/scene/physics.js +120 -0
- package/dist/utility/serialization/scene/physics.js.map +1 -0
- package/dist/utility/serialization/scene/primitive.js +124 -10
- package/dist/utility/serialization/scene/primitive.js.map +1 -1
- package/dist/utility/serialization/scene/scene.js +1687 -51
- package/dist/utility/serialization/scene/scene.js.map +1 -1
- package/dist/utility/serialization/scene/sprite.js +11 -4
- package/dist/utility/serialization/scene/sprite.js.map +1 -1
- package/dist/utility/serialization/scene/terrain.js +163 -33
- package/dist/utility/serialization/scene/terrain.js.map +1 -1
- package/dist/utility/serialization/scene/text.js +11 -4
- package/dist/utility/serialization/scene/text.js.map +1 -1
- package/dist/utility/serialization/scene/water.js +1543 -264
- package/dist/utility/serialization/scene/water.js.map +1 -1
- package/dist/utility/serialization/types.js.map +1 -1
- package/dist/utility/shprojector.js +10 -22
- package/dist/utility/shprojector.js.map +1 -1
- package/dist/utility/textures/foam.js +170 -0
- package/dist/utility/textures/foam.js.map +1 -0
- package/dist/utility/textures/ggxlut.js +17 -43
- package/dist/utility/textures/ggxlut.js.map +1 -1
- package/dist/utility/textures/ltcdata.js +4 -4
- package/dist/utility/textures/ltcdata.js.map +1 -1
- package/dist/utility/textures/ltclut.js +16 -6
- package/dist/utility/textures/ltclut.js.map +1 -1
- package/dist/utility/unsupported.js +24 -0
- package/dist/utility/unsupported.js.map +1 -0
- package/dist/values.js +13 -1
- package/dist/values.js.map +1 -1
- package/package.json +25 -12
- package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
- package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
- package/src/asset/meshoptimizer/LICENSE +21 -0
- package/dist/animation/joint_dynamics/convex_collider.js +0 -320
- 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
|