@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
package/dist/shadow/dom.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ShadowImpl } from './shadow_impl.js';
|
|
2
2
|
import { LIGHT_TYPE_POINT } from '../values.js';
|
|
3
|
-
import { ndcToShadowCoord3, shadowCoordDepthInRange
|
|
3
|
+
import { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow.js';
|
|
4
4
|
import { computeShadowBias } from './shader.js';
|
|
5
5
|
import { ShaderHelper } from '../material/shader/helper.js';
|
|
6
6
|
import { getDevice } from '../app/api.js';
|
|
7
7
|
import { fetchSampler } from '../utility/misc.js';
|
|
8
|
-
import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
8
|
+
import { Vector4, CubeFace, REVERSE_Z } from '@zephyr3d/base';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Opacity layers, which is three rather than four because the fourth channel of
|
|
@@ -108,7 +108,8 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
108
108
|
* interior unshadowed.
|
|
109
109
|
*
|
|
110
110
|
* Exact for directional lights, whose orthographic projection makes device
|
|
111
|
-
* depth a linear function of world depth
|
|
111
|
+
* depth a linear function of world depth, and for point and rect lights,
|
|
112
|
+
* whose cube maps store distance from the light. Spot lights project
|
|
112
113
|
* perspectively, so there the value is only accurate near the middle of the
|
|
113
114
|
* shadow camera's range - which is where hair lit by one usually sits.
|
|
114
115
|
*/ get layerDistance() {
|
|
@@ -190,8 +191,20 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
190
191
|
// The light camera is finalised by the time the casters are drawn, so this is
|
|
191
192
|
// where the world-to-device depth scale becomes known. It stays valid for the
|
|
192
193
|
// lighting pass that follows, which reads the same converted params back.
|
|
193
|
-
|
|
194
|
+
// A cube map stores radial distance over the light's range instead, which is
|
|
195
|
+
// what the layer span must then be measured against.
|
|
196
|
+
const range = isCube(shadowMapParams) ? shadowMapParams.depthRange ?? 1 : shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;
|
|
194
197
|
this._depthRange = range > 1e-6 ? range : 1;
|
|
198
|
+
if (isCube(shadowMapParams)) {
|
|
199
|
+
// These framebuffers are this implementation's own, so the face the shadow
|
|
200
|
+
// mapper selected on the shared one has to be selected on them too.
|
|
201
|
+
const face = shadowMapParams.cubeFace ?? CubeFace.PX;
|
|
202
|
+
if (pass === 0) {
|
|
203
|
+
implData.depthFramebuffer.setDepthAttachmentCubeFace(face);
|
|
204
|
+
} else {
|
|
205
|
+
implData.opacityFramebuffer.setColorAttachmentCubeFace(0, face);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
195
208
|
getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);
|
|
196
209
|
}
|
|
197
210
|
setCasterRenderStates(_shadowMapParams, stateSet) {
|
|
@@ -207,13 +220,14 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
207
220
|
stateSet.useBlendingState().enable(true).setBlendEquation('add', 'add').setBlendFuncRGB('one', 'one').setBlendFuncAlpha('one', 'zero');
|
|
208
221
|
stateSet.useDepthState().enableTest(false).enableWrite(false);
|
|
209
222
|
}
|
|
210
|
-
getShadowMapClearColor(
|
|
223
|
+
getShadowMapClearColor(shadowMapParams) {
|
|
224
|
+
// Radial distance in a cube map is linear, so reverse-Z does not flip it.
|
|
225
|
+
const farthest = REVERSE_Z && !isCube(shadowMapParams) ? 0 : 1;
|
|
211
226
|
if (this._geometryPass === 1) {
|
|
212
227
|
// No hair over this texel means no absorption. Alpha carries z0, and the
|
|
213
|
-
// sentinel
|
|
214
|
-
return new Vector4(0, 0, 0,
|
|
228
|
+
// sentinel makes an uncovered texel read as "nothing in front".
|
|
229
|
+
return new Vector4(0, 0, 0, farthest);
|
|
215
230
|
}
|
|
216
|
-
const farthest = REVERSE_Z ? 0 : 1;
|
|
217
231
|
return new Vector4(farthest, farthest, farthest, 1);
|
|
218
232
|
}
|
|
219
233
|
getShadowMapColorFormat(_shadowMapParams) {
|
|
@@ -273,7 +287,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
273
287
|
// and cleared at the end of each frame, so holding directly-created textures
|
|
274
288
|
// in it leaks them at whatever rate the scene renders.
|
|
275
289
|
const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);
|
|
276
|
-
const result = device.pool.fetchTemporalTexture2D(false, format, width, height, false);
|
|
290
|
+
const result = isCube(shadowMapParams) ? device.pool.fetchTemporalTextureCube(false, format, width, false) : device.pool.fetchTemporalTexture2D(false, format, width, height, false);
|
|
277
291
|
// Pass 0 borrows the shadow map's own depth attachment, which is otherwise
|
|
278
292
|
// unused - this implementation asks for no colour there - so the hardware
|
|
279
293
|
// depth test resolves the frontmost strand for it. Pass 1 gets no depth,
|
|
@@ -334,9 +348,11 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
334
348
|
* behind the front and the clamp below flattens the whole technique to no
|
|
335
349
|
* shadow at all.
|
|
336
350
|
* @internal
|
|
337
|
-
*/ layerCoord(scope, depth, z0, layerSpan) {
|
|
351
|
+
*/ layerCoord(scope, depth, z0, layerSpan, radial) {
|
|
338
352
|
const pb = scope.$builder;
|
|
339
|
-
|
|
353
|
+
// A cube map's radial distance grows away from the light whatever the depth
|
|
354
|
+
// convention.
|
|
355
|
+
const delta = REVERSE_Z && !radial ? pb.sub(z0, depth) : pb.sub(depth, z0);
|
|
340
356
|
return pb.div(pb.max(delta, 0), layerSpan);
|
|
341
357
|
}
|
|
342
358
|
/**
|
|
@@ -354,7 +370,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
354
370
|
// two cases that matter - an opaque caster and a fully transparent one - are
|
|
355
371
|
// the same value there.
|
|
356
372
|
const hasAlpha = geometryPass === 1 && !!alpha;
|
|
357
|
-
const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}`;
|
|
373
|
+
const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}${isCube(shadowMapParams) ? '_c' : ''}`;
|
|
358
374
|
const params = hasAlpha ? [
|
|
359
375
|
pb.vec3('worldPos'),
|
|
360
376
|
pb.float('alpha')
|
|
@@ -370,7 +386,7 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
370
386
|
this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;
|
|
371
387
|
// Distance behind the frontmost strand, in layer-span units. A fragment at
|
|
372
388
|
// or in front of z0 lands at zero and fills every layer.
|
|
373
|
-
this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan);
|
|
389
|
+
this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan, isCube(shadowMapParams));
|
|
374
390
|
// Layer k's far boundary sits at (k+1)/3 of the span, and a fragment
|
|
375
391
|
// contributes to every layer whose boundary lies behind it. The last
|
|
376
392
|
// layer has no far boundary: it extends to the end of the caster volume,
|
|
@@ -417,9 +433,33 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
417
433
|
return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;
|
|
418
434
|
}
|
|
419
435
|
computeShadow(shadowMapParams, scope, shadowVertex, NdotL) {
|
|
420
|
-
const funcName = 'lib_computeShadowDOM';
|
|
421
436
|
const pb = scope.$builder;
|
|
422
437
|
const that = this;
|
|
438
|
+
if (isCube(shadowMapParams)) {
|
|
439
|
+
// The shadow matrix is the identity for a cube map, so the "shadow vertex"
|
|
440
|
+
// is the receiver's world position; its depth is the radial distance the
|
|
441
|
+
// casters stored, over the same range.
|
|
442
|
+
pb.func('lib_computeShadowDOMCube', [
|
|
443
|
+
pb.vec4('shadowVertex'),
|
|
444
|
+
pb.float('NdotL')
|
|
445
|
+
], function() {
|
|
446
|
+
this.$l.posRange = ShaderHelper.getLightPositionAndRangeForShadow(this);
|
|
447
|
+
this.$l.dir = pb.sub(this.shadowVertex.xyz, this.posRange.xyz);
|
|
448
|
+
this.$l.depth = pb.div(pb.length(this.dir), this.posRange.w);
|
|
449
|
+
this.$l.shadow = pb.float(1);
|
|
450
|
+
this.$if(pb.lessThanEqual(this.depth, 1), function() {
|
|
451
|
+
// The kernel needs the bias for the same reason as the 2D map below.
|
|
452
|
+
if (that._filterSize > 1) {
|
|
453
|
+
this.$l.bias = computeShadowBias(shadowMapParams.lightType, this, this.depth, this.NdotL, true);
|
|
454
|
+
this.depth = applyShadowDepthBias(this, this.depth, this.bias, false);
|
|
455
|
+
}
|
|
456
|
+
this.shadow = that.transmittanceCube(this, this.dir, this.depth);
|
|
457
|
+
});
|
|
458
|
+
this.$return(this.shadow);
|
|
459
|
+
});
|
|
460
|
+
return pb.getGlobalScope().lib_computeShadowDOMCube(shadowVertex, NdotL);
|
|
461
|
+
}
|
|
462
|
+
const funcName = 'lib_computeShadowDOM';
|
|
423
463
|
pb.func(funcName, [
|
|
424
464
|
pb.vec4('shadowVertex'),
|
|
425
465
|
pb.float('NdotL')
|
|
@@ -495,22 +535,70 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
495
535
|
return pb.getGlobalScope()[funcName](shadowCoord);
|
|
496
536
|
}
|
|
497
537
|
/**
|
|
538
|
+
* {@link DOM.transmittance} for a cube map: the same kernel, laid out on the
|
|
539
|
+
* face around the receiver's direction.
|
|
540
|
+
*
|
|
541
|
+
* @remarks
|
|
542
|
+
* The taps step one texel at a time on the unit cube, where a face texel spans
|
|
543
|
+
* `2 / size`, in a plane perpendicular to the ray - which matches the face's
|
|
544
|
+
* own grid at its centre and differs only to second order off it.
|
|
545
|
+
* @internal
|
|
546
|
+
*/ transmittanceCube(scope, dir, receiverDepth) {
|
|
547
|
+
const pb = scope.$builder;
|
|
548
|
+
const that = this;
|
|
549
|
+
const size = this._filterSize;
|
|
550
|
+
const funcName = `lib_domTransmittanceCube_${size}`;
|
|
551
|
+
pb.func(funcName, [
|
|
552
|
+
pb.vec3('dir'),
|
|
553
|
+
pb.float('receiverDepth')
|
|
554
|
+
], function() {
|
|
555
|
+
if (size <= 1) {
|
|
556
|
+
this.$return(that.layerTransmittance(this, this.dir, this.receiverDepth, true));
|
|
557
|
+
} else {
|
|
558
|
+
this.$l.unitDir = pb.normalize(this.dir);
|
|
559
|
+
this.$l.onCube = pb.div(this.unitDir, pb.max(pb.max(pb.abs(this.unitDir.x), pb.abs(this.unitDir.y)), pb.abs(this.unitDir.z)));
|
|
560
|
+
this.$l.helper = this.$choice(pb.lessThan(pb.abs(this.unitDir.y), 0.99), pb.vec3(0, 1, 0), pb.vec3(1, 0, 0));
|
|
561
|
+
this.$l.side = pb.normalize(pb.cross(this.helper, this.unitDir));
|
|
562
|
+
this.$l.up = pb.cross(this.unitDir, this.side);
|
|
563
|
+
this.$l.texelSize = pb.div(2, ShaderHelper.getShadowCameraParams(this).z);
|
|
564
|
+
this.$l.sum = pb.float(0);
|
|
565
|
+
this.$l.tapDir = pb.vec3();
|
|
566
|
+
const radius = (size - 1) / 2;
|
|
567
|
+
for(let y = -radius; y <= radius; y++){
|
|
568
|
+
for(let x = -radius; x <= radius; x++){
|
|
569
|
+
this.tapDir = pb.add(this.onCube, pb.mul(pb.add(pb.mul(this.side, x), pb.mul(this.up, y)), this.texelSize));
|
|
570
|
+
this.sum = pb.add(this.sum, that.layerTransmittance(this, this.tapDir, this.receiverDepth, true));
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
this.$return(pb.div(this.sum, size * size));
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
return pb.getGlobalScope()[funcName](dir, receiverDepth);
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
498
579
|
* Transmittance from a single shadow map texel.
|
|
499
580
|
* @internal
|
|
500
581
|
*/ tapTransmittance(scope, uv, receiverDepth) {
|
|
582
|
+
return this.layerTransmittance(scope, uv, receiverDepth, false);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Transmittance from the texel at `coord` - a map UV, or for a cube map a
|
|
586
|
+
* direction from the light.
|
|
587
|
+
* @internal
|
|
588
|
+
*/ layerTransmittance(scope, coord, receiverDepth, radial) {
|
|
501
589
|
const pb = scope.$builder;
|
|
502
590
|
const that = this;
|
|
503
|
-
const funcName = 'lib_domTap';
|
|
591
|
+
const funcName = radial ? 'lib_domTapCube' : 'lib_domTap';
|
|
504
592
|
pb.func(funcName, [
|
|
505
|
-
pb.vec2('
|
|
593
|
+
radial ? pb.vec3('coord') : pb.vec2('coord'),
|
|
506
594
|
pb.float('receiverDepth')
|
|
507
595
|
], function() {
|
|
508
|
-
this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.
|
|
596
|
+
this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.coord, 0);
|
|
509
597
|
this.$l.layers = this.texel.rgb;
|
|
510
598
|
this.$l.z0 = this.texel.a;
|
|
511
599
|
this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;
|
|
512
600
|
this.$l.density = ShaderHelper.getShadowImplParams(this).y;
|
|
513
|
-
this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan);
|
|
601
|
+
this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan, radial);
|
|
514
602
|
// The layers are cumulative, so opacity at an arbitrary depth is a lerp
|
|
515
603
|
// between the two bracketing layer values. Scaling t by the layer count puts
|
|
516
604
|
// the integer part on the near layer and the fraction between the pair.
|
|
@@ -538,9 +626,12 @@ import { Vector4, REVERSE_Z } from '@zephyr3d/base';
|
|
|
538
626
|
// would have.
|
|
539
627
|
this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));
|
|
540
628
|
});
|
|
541
|
-
return pb.getGlobalScope()[funcName](
|
|
629
|
+
return pb.getGlobalScope()[funcName](coord, receiverDepth);
|
|
542
630
|
}
|
|
543
631
|
}
|
|
632
|
+
/** Whether the map is a point-projection cube (point and rect lights). @internal */ function isCube(shadowMapParams) {
|
|
633
|
+
return shadowMapParams.lightType === LIGHT_TYPE_POINT;
|
|
634
|
+
}
|
|
544
635
|
|
|
545
636
|
export { DOM };
|
|
546
637
|
//# sourceMappingURL=dom.js.map
|
package/dist/shadow/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sources":["../../src/shadow/dom.ts"],"sourcesContent":["import type {\r\n BindGroup,\r\n FrameBuffer,\r\n PBGlobalScope,\r\n PBInsideFunctionScope,\r\n PBShaderExp,\r\n RenderStateSet,\r\n Texture2D,\r\n TextureFormat\r\n} from '@zephyr3d/device';\r\nimport { ShadowImpl } from './shadow_impl';\r\nimport type { ShadowMapParams, ShadowMapType } from './shadowmapper';\r\nimport { LIGHT_TYPE_POINT } from '../values';\r\nimport { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow';\r\nimport { computeShadowBias } from './shader';\r\nimport { ShaderHelper } from '../material/shader/helper';\r\nimport { getDevice } from '../app/api';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport { REVERSE_Z, Vector4, type Nullable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Opacity layers, which is three rather than four because the fourth channel of\r\n * the result texture carries the depth the layers are measured from. Keeping\r\n * both in one texture is what lets the receiver read the whole technique through\r\n * the single shadow-map binding the lighting shaders declare.\r\n * @internal\r\n */\r\nconst DOM_LAYER_COUNT = 3;\r\n\r\n/** @internal Caster-pass uniform holding the frontmost depth from geometry pass 0. */\r\nconst UNIFORM_NAME_DOM_FRONT_DEPTH = 'Z_domFrontDepth';\r\n\r\n/**\r\n * Transmittance a fully opaque caster is recorded as, since zero has no finite\r\n * optical depth to blend. Dark enough to read as black, and small enough in the\r\n * exponent that several opaque layers can stack without saturating half floats.\r\n * @internal\r\n */\r\nconst DOM_MIN_TRANSMITTANCE = 0.001;\r\n\r\n/** @internal */\r\ntype DOMImplData = {\r\n /**\r\n * Frontmost caster depth, written by geometry pass 0 and sampled by pass 1.\r\n * Separate from the result texture on purpose: a texture cannot be a render\r\n * target and a sampled resource in the same pass.\r\n */\r\n frontDepth: Texture2D;\r\n /** RGB = cumulative optical depth per layer, A = the depth those layers start at. */\r\n result: Texture2D;\r\n /** Targets {@link DOMImplData.frontDepth}, reusing the shared depth attachment. */\r\n depthFramebuffer: FrameBuffer;\r\n /** Targets {@link DOMImplData.result}. No depth attachment - pass 1 does not test. */\r\n opacityFramebuffer: FrameBuffer;\r\n};\r\n\r\n/**\r\n * Deep opacity map shadows.\r\n *\r\n * @remarks\r\n * Hair is the case an ordinary shadow map cannot express. A shadow map answers\r\n * \"is this point behind the nearest caster\", which is the right question for a\r\n * wall and the wrong one for ten thousand strands: light entering a groom is not\r\n * blocked at its surface, it is attenuated gradually as it passes more and more\r\n * fibres. A binary test renders that as a hard edge with everything behind it\r\n * uniformly black.\r\n *\r\n * A deep opacity map (Yuksel & Keyser 2008) records the attenuation instead of\r\n * the boundary. Geometry pass 0 writes the frontmost caster depth `z0` per texel.\r\n * Pass 1 rasterises the casters again and each fragment adds its optical depth to\r\n * every layer lying behind it, giving cumulative absorption sampled at three\r\n * depths measured *from `z0`* rather than from the light. Because the layers\r\n * follow the hair surface, three of them resolve what a plain opacity shadow map\r\n * needs dozens of uniformly spaced ones to match.\r\n *\r\n * Recording optical depth rather than coverage is what keeps it exact for solid\r\n * casters as well as thin ones, so a scene does not have to reserve this mode for\r\n * its hair: see the caster output for why the two differ.\r\n *\r\n * WebGPU only, and deliberately so: the strand geometry this exists to shadow is\r\n * itself WebGPU only, so supporting the WebGL fallbacks - cascade atlases instead\r\n * of array layers, RGBA8-packed depth instead of float - would double the surface\r\n * area to serve no material.\r\n *\r\n * @internal\r\n */\r\nexport class DOM extends ShadowImpl {\r\n /** @internal */\r\n private _layerDistance: number;\r\n /** @internal */\r\n private _density: number;\r\n /** @internal Width of the sampling kernel in texels; 1 disables filtering. */\r\n private _filterSize: number;\r\n /** @internal */\r\n private readonly _paramsScratch: Vector4;\r\n /**\r\n * @internal\r\n * Which geometry pass is being rasterised. Lives on the implementation rather\r\n * than in `implData` because {@link DOM.getShaderHash} has no access to the\r\n * params, and the hash must separate the two passes or they share a program.\r\n */\r\n private _geometryPass: number;\r\n /**\r\n * @internal\r\n * Depth the shadow camera spans, captured when the map is rendered. Needed to\r\n * express {@link DOM.layerDistance} in world units: the shader compares device\r\n * depths, and for the orthographic projection a directional light uses those\r\n * are the world depth divided by exactly this.\r\n */\r\n private _depthRange: number;\r\n constructor(layerDistance = 0.25, density = 1, filterSize = 5) {\r\n super();\r\n this._layerDistance = layerDistance;\r\n this._density = density;\r\n this._filterSize = DOM.clampFilterSize(filterSize);\r\n this._paramsScratch = new Vector4();\r\n this._geometryPass = 0;\r\n this._depthRange = 1;\r\n }\r\n /** @internal */\r\n private static clampFilterSize(val: number) {\r\n return val !== 1 && val !== 3 && val !== 5 && val !== 7 ? 5 : val;\r\n }\r\n /**\r\n * Width of the sampling kernel, in shadow map texels. One of 1, 3, 5 or 7.\r\n *\r\n * @remarks\r\n * The graded transmittance this technique records runs along the light, not\r\n * across the map, so at the silhouette of a groom - where the change is one of\r\n * coverage rather than of depth - a single tap is as abrupt as an unfiltered\r\n * shadow map. This is the kernel that softens that edge, and it is the same\r\n * knob PCF's kernel size is, with the difference that each tap here costs a\r\n * layer lookup rather than a depth comparison.\r\n *\r\n * Set to 1 to sample once, which is measurably cheaper and visibly harder.\r\n */\r\n get filterSize() {\r\n return this._filterSize;\r\n }\r\n set filterSize(val) {\r\n this._filterSize = DOM.clampFilterSize(val);\r\n }\r\n /**\r\n * Depth the layers span, in world units along the light direction.\r\n *\r\n * @remarks\r\n * Set it to roughly the thickness of the hair. Too small and everything past\r\n * the outer strands saturates the last layer, which is a hard shadow again;\r\n * too large and all three layers land inside the first strand, leaving the\r\n * interior unshadowed.\r\n *\r\n * Exact for directional lights, whose orthographic projection makes device\r\n * depth a linear function of world depth. Spot and point lights project\r\n * perspectively, so there the value is only accurate near the middle of the\r\n * shadow camera's range - which is where hair lit by one usually sits.\r\n */\r\n get layerDistance() {\r\n return this._layerDistance;\r\n }\r\n set layerDistance(val) {\r\n this._layerDistance = val > 0 ? val : 0.0001;\r\n }\r\n /**\r\n * Artistic multiplier on the absorption the casters actually recorded.\r\n *\r\n * @remarks\r\n * One reproduces alpha compositing exactly and is the right default. Raise it\r\n * to deepen the interior of a groom without moving the layers, lower it to let\r\n * more light through than the geometry strictly would.\r\n */\r\n get density() {\r\n return this._density;\r\n }\r\n set density(val) {\r\n this._density = val < 0 ? 0 : val;\r\n }\r\n getType() {\r\n return 'dom' as const;\r\n }\r\n resourceDirty() {\r\n return this._resourceDirty;\r\n }\r\n getShadowMapBorder() {\r\n // Margin so the kernel's outer taps still land inside the map at the edges of\r\n // the shadow region, matching what the PCF implementations reserve.\r\n return this._filterSize;\r\n }\r\n getDepthScale() {\r\n return 1;\r\n }\r\n setDepthScale(_val: number) {}\r\n /**\r\n * Layer geometry and density, for both the caster and the receiver. `z` and\r\n * `w` are unused.\r\n *\r\n * @remarks\r\n * `x` is the layer span converted from world units into the device-depth\r\n * difference the shaders actually compare, using the range captured when the\r\n * map was rendered.\r\n */\r\n getParams(out?: Vector4) {\r\n const result = out ?? this._paramsScratch;\r\n result.setXYZW(this._layerDistance / this._depthRange, this._density, 0, 0);\r\n return result;\r\n }\r\n getGeometryPassCount() {\r\n return 2;\r\n }\r\n supportsCascades() {\r\n // Each split would need its own depth and layer set, and both already share\r\n // the one texture the receiver can bind.\r\n return false;\r\n }\r\n clipsCasterAlpha() {\r\n // Neither pass wants the clip. Pass 1 integrates the alpha, and clipping is\r\n // destructive to it in both of the forms the material applies: a dithered\r\n // caster survives with probability alpha and then contributes the absorption\r\n // of that same alpha, counting it twice, and a hard cutoff drops the sub-pixel\r\n // strands that carry most of a groom's transmittance.\r\n //\r\n // Pass 0 skips it for a different reason. Its job is to find the frontmost\r\n // strand, and under dithering the clip makes that choice per-pixel random -\r\n // the layers would then start at a depth that flickers between strands, and\r\n // every opacity reading behind it inherits the jitter.\r\n //\r\n // The case this gives up is a caster whose alpha is a real mask rather than a\r\n // coverage value, such as a hair card with cut-out texels: pass 0 will place\r\n // z0 on the card's surface even where it is fully transparent. Strand\r\n // geometry, which is what this technique is for, has no such texels.\r\n return false;\r\n }\r\n beginGeometryPass(shadowMapParams: ShadowMapParams, pass: number) {\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n this._geometryPass = pass;\r\n // The light camera is finalised by the time the casters are drawn, so this is\r\n // where the world-to-device depth scale becomes known. It stays valid for the\r\n // lighting pass that follows, which reads the same converted params back.\r\n const range = shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;\r\n this._depthRange = range > 1e-6 ? range : 1;\r\n getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);\r\n }\r\n setCasterRenderStates(_shadowMapParams: ShadowMapParams, stateSet: RenderStateSet) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n // Every strand between z0 and the last layer has to contribute, so the pass\r\n // must not depth-test against the frontmost surface pass 0 resolved, and must\r\n // not write depth of its own - its framebuffer has no depth attachment at all.\r\n // Optical depth sums across the three layer channels; alpha instead carries\r\n // z0, which every fragment reads from the same texel, so replacing is correct\r\n // where summing would multiply it by the number of overlapping strands.\r\n stateSet\r\n .useBlendingState()\r\n .enable(true)\r\n .setBlendEquation('add', 'add')\r\n .setBlendFuncRGB('one', 'one')\r\n .setBlendFuncAlpha('one', 'zero');\r\n stateSet.useDepthState().enableTest(false).enableWrite(false);\r\n }\r\n getShadowMapClearColor(_shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass === 1) {\r\n // No hair over this texel means no absorption. Alpha carries z0, and the\r\n // sentinel below makes an uncovered texel read as \"nothing in front\".\r\n return new Vector4(0, 0, 0, REVERSE_Z ? 0 : 1);\r\n }\r\n const farthest = REVERSE_Z ? 0 : 1;\r\n return new Vector4(farthest, farthest, farthest, 1);\r\n }\r\n getShadowMapColorFormat(_shadowMapParams: ShadowMapParams) {\r\n // Null keeps the framebuffer the caller allocates depth-only. The colour this\r\n // technique needs is allocated here, against framebuffers of its own, so\r\n // letting the caller also allocate a full-size colour attachment would waste\r\n // it outright.\r\n return null;\r\n }\r\n getShadowMapDepthFormat(_shadowMapParams: ShadowMapParams) {\r\n return this.preferredShadowMapDepthFormat();\r\n }\r\n useNativeShadowMap(_shadowMapParams: ShadowMapParams) {\r\n // The receiver needs the actual stored values - a depth to measure offsets\r\n // from and three sums to interpolate - not the result of a hardware compare.\r\n return false;\r\n }\r\n getShadowMap(shadowMapParams: ShadowMapParams) {\r\n return (shadowMapParams.implData as DOMImplData).result as ShadowMapType;\r\n }\r\n /**\r\n * Format for both targets.\r\n *\r\n * @remarks\r\n * Full float wherever the accumulation pass can blend into it, and the reason\r\n * is the anchor depth, not the absorption sums. `z0` is stored absolute, in\r\n * units of the shadow camera's whole depth range, and every layer coordinate\r\n * on both sides of the technique is a difference against it divided by the\r\n * layer span. At half precision its quantisation step is about 2^-11 of the\r\n * stored value - roughly `0.0005 * depthRange` in world units - which for a\r\n * shadow camera spanning a large scene is comparable to the depth of the hair\r\n * itself. The error is independent per texel, so it does not read as bias but\r\n * as blotches: patches of a backlit groom whose receivers land in front of\r\n * their quantised `z0` and come out fully lit. A layer span large enough to\r\n * drown the noise hides it, but throws away the graded falloff the technique\r\n * exists for.\r\n *\r\n * Half float remains the fallback for devices whose blending cannot target\r\n * full float; there the practical mitigation is a tight shadow distance.\r\n * @internal\r\n */\r\n private colorFormat(): TextureFormat {\r\n const caps = getDevice().getDeviceCaps().textureCaps;\r\n if (caps.supportFloatColorBuffer && caps.supportFloatBlending) {\r\n return 'rgba32f';\r\n }\r\n return caps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba32f';\r\n }\r\n doUpdateResources(shadowMapParams: ShadowMapParams) {\r\n const device = getDevice();\r\n const sharedDepth = shadowMapParams.shadowMapFramebuffer!.getDepthAttachment()!;\r\n const width = sharedDepth.width;\r\n const height = sharedDepth.height;\r\n const format = this.colorFormat();\r\n // Everything here is pooled, per frame, the way the blur targets of VSM and\r\n // ESM are. `implData` cannot cache across frames even though it looks like it\r\n // could: it lives on a ShadowMapParams that is recycled between every light\r\n // and cleared at the end of each frame, so holding directly-created textures\r\n // in it leaks them at whatever rate the scene renders.\r\n const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n const result = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n // Pass 0 borrows the shadow map's own depth attachment, which is otherwise\r\n // unused - this implementation asks for no colour there - so the hardware\r\n // depth test resolves the frontmost strand for it. Pass 1 gets no depth,\r\n // which is both what stops it testing and what frees `frontDepth` to be\r\n // sampled while `result` is written.\r\n const depthFramebuffer = device.pool.createTemporalFramebuffer(true, [frontDepth], sharedDepth);\r\n const opacityFramebuffer = device.pool.createTemporalFramebuffer(true, [result], null);\r\n // The framebuffers hold the references now; these drop the fetch counts so\r\n // both textures return to the pool when the frame ends.\r\n device.pool.releaseTexture(frontDepth);\r\n device.pool.releaseTexture(result);\r\n shadowMapParams.implData = {\r\n frontDepth,\r\n result,\r\n depthFramebuffer,\r\n opacityFramebuffer\r\n } satisfies DOMImplData;\r\n shadowMapParams.shadowMap = result;\r\n shadowMapParams.shadowMapSampler = result.getDefaultSampler(false);\r\n this._resourceDirty = false;\r\n }\r\n postRenderShadowMap(_shadowMapParams: ShadowMapParams) {}\r\n getShaderHash() {\r\n // The two geometry passes emit different caster fragments and the shadow pass\r\n // keys its programs on this hash, so the pass index has to appear in it. The\r\n // kernel is unrolled into the receiver, so it belongs here too.\r\n return `${DOM_LAYER_COUNT}_${this._geometryPass}_${this._filterSize}`;\r\n }\r\n declareCasterUniforms(scope: PBGlobalScope, _shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const pb = scope.$builder;\r\n // sampleType before uniform(), matching how the receiver's shadow map is\r\n // declared: the binding is created from the accumulated descriptor.\r\n const tex = pb.tex2D();\r\n tex.sampleType('unfilterable-float');\r\n scope[UNIFORM_NAME_DOM_FRONT_DEPTH] = tex.uniform(0);\r\n }\r\n applyCasterUniforms(bindGroup: BindGroup, shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n bindGroup.setTexture(\r\n UNIFORM_NAME_DOM_FRONT_DEPTH,\r\n implData.frontDepth,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n }\r\n /**\r\n * How far a depth lies behind the frontmost strand, in layer-span units.\r\n *\r\n * @remarks\r\n * Both callers measure \"deeper into the hair than z0\", but which direction that\r\n * is depends on the depth encoding: under reverse-Z a farther surface has the\r\n * *smaller* value, so the plain subtraction is negative for every fragment\r\n * behind the front and the clamp below flattens the whole technique to no\r\n * shadow at all.\r\n * @internal\r\n */\r\n private layerCoord(\r\n scope: PBInsideFunctionScope,\r\n depth: PBShaderExp,\r\n z0: PBShaderExp,\r\n layerSpan: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const delta = REVERSE_Z ? pb.sub(z0, depth) : pb.sub(depth, z0);\r\n return pb.div(pb.max(delta, 0), layerSpan);\r\n }\r\n /**\r\n * Caster output.\r\n *\r\n * Pass 0 writes the frontmost depth. Pass 1 writes this fragment's optical depth\r\n * into the layers behind it, for additive blending to sum, and carries z0\r\n * through alpha so the receiver can find where the layers start.\r\n */\r\n computeShadowMapDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp,\r\n alpha: Nullable<PBShaderExp>\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const geometryPass = this._geometryPass;\r\n // Alpha travels as a parameter. Reaching into the caller's scope for its\r\n // `outColor` would be reading a local of a different shader function, and the\r\n // two cases that matter - an opaque caster and a fully transparent one - are\r\n // the same value there.\r\n const hasAlpha = geometryPass === 1 && !!alpha;\r\n const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}`;\r\n const params = hasAlpha ? [pb.vec3('worldPos'), pb.float('alpha')] : [pb.vec3('worldPos')];\r\n pb.func(funcName, params, function () {\r\n this.$l.depth = that.casterDepth(shadowMapParams, this, this.worldPos);\r\n if (geometryPass === 0) {\r\n this.$return(pb.vec4(this.depth, 0, 0, 1));\r\n } else {\r\n this.$l.z0 = pb.textureLoad(\r\n this[UNIFORM_NAME_DOM_FRONT_DEPTH],\r\n pb.ivec2(this.$builtins.fragCoord.xy),\r\n 0\r\n ).x;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n // Distance behind the frontmost strand, in layer-span units. A fragment at\r\n // or in front of z0 lands at zero and fills every layer.\r\n this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan);\r\n // Layer k's far boundary sits at (k+1)/3 of the span, and a fragment\r\n // contributes to every layer whose boundary lies behind it. The last\r\n // layer has no far boundary: it extends to the end of the caster volume,\r\n // so a fragment deeper than the span still lands in it and the third\r\n // layer holds the cumulative absorption of *everything* behind z0.\r\n // Dropping deep fragments instead - step(t, 1) - deletes the hair behind\r\n // the front slice from the map entirely, and any receiver deeper than\r\n // the span reads only that slice: wherever it happens to be sparse, the\r\n // middle of a dense backlit groom comes out fully lit in blotches.\r\n this.$l.mask = pb.vec3(pb.step(this.t, 1 / 3), pb.step(this.t, 2 / 3), 1);\r\n // A caster that computes no fragment colour covers fully.\r\n this.$l.casterAlpha = hasAlpha ? this.alpha : pb.float(1);\r\n // Optical depth rather than raw coverage, because what has to be additive\r\n // here is the exponent, not the alpha. Compositing N layers multiplies\r\n // their transmittances - prod(1 - a) - and blending can only sum, so each\r\n // fragment contributes -log(1 - a) and the receiver's exp(-sum) reproduces\r\n // that product exactly.\r\n //\r\n // Summing alpha instead makes exp(-sum) an approximation that only holds\r\n // while alpha is small, which is true of a sub-pixel strand and false of\r\n // anything solid: a single opaque caster would sum to 1 and shadow to\r\n // exp(-1), a 37% grey rather than black.\r\n //\r\n // The floor bounds what alpha = 1 encodes. It has to be finite to blend,\r\n // and 0.001 transmittance is already black; it also leaves room for\r\n // several opaque layers to stack without leaving half precision.\r\n this.$l.opticalDepth = pb.neg(pb.log(pb.max(pb.sub(1, this.casterAlpha), DOM_MIN_TRANSMITTANCE)));\r\n this.$return(pb.vec4(pb.mul(this.mask, this.opticalDepth), this.z0));\r\n }\r\n });\r\n const global = pb.getGlobalScope();\r\n return (hasAlpha ? global[funcName](worldPos, alpha!) : global[funcName](worldPos)) as PBShaderExp;\r\n }\r\n /**\r\n * Normalized light-space depth of a caster fragment, in the encoding the\r\n * receiver reconstructs.\r\n * @internal\r\n */\r\n private casterDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n if (shadowMapParams.lightType === LIGHT_TYPE_POINT) {\r\n const lightSpacePos = pb.mul(ShaderHelper.getLightViewMatrixForShadow(scope), pb.vec4(worldPos, 1));\r\n return pb.clamp(\r\n pb.div(pb.length(lightSpacePos.xyz), ShaderHelper.getLightPositionAndRangeForShadow(scope).w),\r\n 0,\r\n 1\r\n );\r\n }\r\n return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;\r\n }\r\n computeShadow(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp\r\n ) {\r\n const funcName = 'lib_computeShadowDOM';\r\n const pb = scope.$builder;\r\n const that = this;\r\n pb.func(funcName, [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.shadowCoord = pb.div(this.shadowVertex.xyz, this.shadowVertex.w);\r\n this.$l.shadowCoord = ndcToShadowCoord3(this, this.shadowCoord.xyz);\r\n this.$l.inRange = pb.all(\r\n pb.bvec2(\r\n pb.all(\r\n pb.bvec4(\r\n pb.greaterThanEqual(this.shadowCoord.x, 0),\r\n pb.lessThanEqual(this.shadowCoord.x, 1),\r\n pb.greaterThanEqual(this.shadowCoord.y, 0),\r\n pb.lessThanEqual(this.shadowCoord.y, 1)\r\n )\r\n ),\r\n shadowCoordDepthInRange(this, this.shadowCoord.z)\r\n )\r\n );\r\n this.$l.shadow = pb.float(1);\r\n this.$if(this.inRange, function () {\r\n // A single tap needs no bias: it reads the texel the receiver itself\r\n // wrote, so its own surface sits exactly at z0 and contributes nothing.\r\n // A kernel breaks that. Neighbouring texels record the frontmost surface\r\n // at their own position, which on anything sloped is nearer the light\r\n // than the receiver, and the receiver then reads itself as being behind a\r\n // caster. On a solid surface that is the full jump from no absorption to\r\n // all of it, so it shows up as the banding an unbiased shadow map has.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(\r\n shadowMapParams.lightType,\r\n this,\r\n this.shadowCoord.z,\r\n this.NdotL,\r\n false\r\n );\r\n this.shadowCoord.z = applyShadowDepthBias(this, this.shadowCoord.z, this.bias, true);\r\n }\r\n this.shadow = that.transmittance(this, this.shadowCoord);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope()[funcName](shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n computeShadowCSM(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp,\r\n _split: PBShaderExp\r\n ) {\r\n // Cascades would need a depth and a layer set per split, which no longer fits\r\n // the one texture the single shadow-map binding allows. Callers keep working\r\n // by shadowing from the first cascade's map.\r\n return this.computeShadow(shadowMapParams, scope, shadowVertex, NdotL);\r\n }\r\n /**\r\n * Fraction of light surviving the hair in front of the receiver, averaged over\r\n * the filter kernel.\r\n *\r\n * @remarks\r\n * The averaging is over transmittance, one value per tap, rather than over the\r\n * stored texels. Blending the texels first would interpolate `z0` across the\r\n * silhouette of the groom, where one side holds a real strand depth and the\r\n * other the empty-texel sentinel, and the depth halfway between them describes\r\n * nothing - every layer reading taken against it would be measured from the\r\n * wrong origin. Averaging the results instead asks a well-posed question of\r\n * each texel and combines only the answers, which is also what makes this an\r\n * antialiased edge rather than a blurred one.\r\n * @internal\r\n */\r\n private transmittance(scope: PBInsideFunctionScope, shadowCoord: PBShaderExp): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittance_${size}`;\r\n pb.func(funcName, [pb.vec3('shadowCoord')], function () {\r\n if (size <= 1) {\r\n this.$return(that.tapTransmittance(this, this.shadowCoord.xy, this.shadowCoord.z));\r\n } else {\r\n // cameraParams.z carries the shadow map size, and this implementation\r\n // never splits into cascades, so the map is exactly that wide.\r\n this.$l.texelSize = pb.div(1, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapUV = pb.vec2();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapUV = pb.add(this.shadowCoord.xy, pb.mul(pb.vec2(x, y), this.texelSize));\r\n this.sum = pb.add(this.sum, that.tapTransmittance(this, this.tapUV, this.shadowCoord.z));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](shadowCoord) as PBShaderExp;\r\n }\r\n /**\r\n * Transmittance from a single shadow map texel.\r\n * @internal\r\n */\r\n private tapTransmittance(\r\n scope: PBInsideFunctionScope,\r\n uv: PBShaderExp,\r\n receiverDepth: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const funcName = 'lib_domTap';\r\n pb.func(funcName, [pb.vec2('uv'), pb.float('receiverDepth')], function () {\r\n this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.uv, 0);\r\n this.$l.layers = this.texel.rgb;\r\n this.$l.z0 = this.texel.a;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n this.$l.density = ShaderHelper.getShadowImplParams(this).y;\r\n this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan);\r\n // The layers are cumulative, so opacity at an arbitrary depth is a lerp\r\n // between the two bracketing layer values. Scaling t by the layer count puts\r\n // the integer part on the near layer and the fraction between the pair.\r\n this.$l.scaled = pb.clamp(pb.mul(this.t, DOM_LAYER_COUNT), 0, DOM_LAYER_COUNT);\r\n this.$l.index = pb.floor(this.scaled);\r\n this.$l.frac = pb.sub(this.scaled, this.index);\r\n // Nothing has been traversed before the first layer, so the near value at\r\n // index 0 is zero rather than layers.x.\r\n this.$l.near = pb.float(0);\r\n this.$l.far = this.layers.x;\r\n this.$if(pb.greaterThanEqual(this.index, 2), function () {\r\n this.near = this.layers.y;\r\n this.far = this.layers.z;\r\n }).$elseif(pb.greaterThanEqual(this.index, 1), function () {\r\n this.near = this.layers.x;\r\n this.far = this.layers.y;\r\n });\r\n // Optical depth is what accumulates linearly through a medium, so the lerp\r\n // between two layer readings is meaningful in a way that lerping stored\r\n // alphas would not have been.\r\n this.$l.absorption = pb.mix(this.near, this.far, this.frac);\r\n // Beer-Lambert. With the casters recording -log(1 - alpha) this is exactly\r\n // prod(1 - alpha) over everything crossed, so a solid caster reaches black\r\n // and a stack of thin strands reaches the same value alpha compositing them\r\n // would have.\r\n this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));\r\n });\r\n return pb.getGlobalScope()[funcName](uv, receiverDepth) as PBShaderExp;\r\n }\r\n}\r\n"],"names":["DOM_LAYER_COUNT","UNIFORM_NAME_DOM_FRONT_DEPTH","DOM_MIN_TRANSMITTANCE","DOM","ShadowImpl","layerDistance","density","filterSize","_layerDistance","_density","_filterSize","clampFilterSize","_paramsScratch","Vector4","_geometryPass","_depthRange","val","getType","resourceDirty","_resourceDirty","getShadowMapBorder","getDepthScale","setDepthScale","_val","getParams","out","result","setXYZW","getGeometryPassCount","supportsCascades","clipsCasterAlpha","beginGeometryPass","shadowMapParams","pass","implData","range","cameraParams","y","x","getDevice","setFramebuffer","depthFramebuffer","opacityFramebuffer","setCasterRenderStates","_shadowMapParams","stateSet","useBlendingState","enable","setBlendEquation","setBlendFuncRGB","setBlendFuncAlpha","useDepthState","enableTest","enableWrite","getShadowMapClearColor","REVERSE_Z","farthest","getShadowMapColorFormat","getShadowMapDepthFormat","preferredShadowMapDepthFormat","useNativeShadowMap","getShadowMap","caps","getDeviceCaps","textureCaps","supportFloatColorBuffer","supportFloatBlending","supportHalfFloatColorBuffer","doUpdateResources","device","sharedDepth","shadowMapFramebuffer","getDepthAttachment","width","height","format","colorFormat","frontDepth","pool","fetchTemporalTexture2D","createTemporalFramebuffer","releaseTexture","shadowMap","shadowMapSampler","getDefaultSampler","postRenderShadowMap","getShaderHash","declareCasterUniforms","scope","pb","$builder","tex","tex2D","sampleType","uniform","applyCasterUniforms","bindGroup","setTexture","fetchSampler","layerCoord","depth","z0","layerSpan","delta","sub","div","max","computeShadowMapDepth","worldPos","alpha","that","geometryPass","hasAlpha","funcName","params","vec3","float","func","$l","casterDepth","$return","vec4","textureLoad","ivec2","$builtins","fragCoord","xy","ShaderHelper","getShadowImplParams","t","mask","step","casterAlpha","opticalDepth","neg","log","mul","global","getGlobalScope","lightType","LIGHT_TYPE_POINT","lightSpacePos","getLightViewMatrixForShadow","clamp","length","xyz","getLightPositionAndRangeForShadow","w","emulateDepthClamp","$inputs","clamppedDepth","z","computeShadow","shadowVertex","NdotL","shadowCoord","ndcToShadowCoord3","inRange","all","bvec2","bvec4","greaterThanEqual","lessThanEqual","shadowCoordDepthInRange","shadow","$if","bias","computeShadowBias","applyShadowDepthBias","transmittance","computeShadowCSM","_split","size","tapTransmittance","texelSize","getShadowCameraParams","sum","tapUV","vec2","radius","add","uv","receiverDepth","texel","textureSampleLevel","layers","rgb","a","scaled","index","floor","frac","near","far","$elseif","absorption","mix","exp"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dom.js","sources":["../../src/shadow/dom.ts"],"sourcesContent":["import type {\r\n BindGroup,\r\n FrameBuffer,\r\n PBGlobalScope,\r\n PBInsideFunctionScope,\r\n PBShaderExp,\r\n RenderStateSet,\r\n Texture2D,\r\n TextureCube,\r\n TextureFormat\r\n} from '@zephyr3d/device';\r\nimport { ShadowImpl } from './shadow_impl';\r\nimport type { ShadowMapParams, ShadowMapType } from './shadowmapper';\r\nimport { LIGHT_TYPE_POINT } from '../values';\r\nimport { applyShadowDepthBias, ndcToShadowCoord3, shadowCoordDepthInRange } from '../shaders/shadow';\r\nimport { computeShadowBias } from './shader';\r\nimport { ShaderHelper } from '../material/shader/helper';\r\nimport { getDevice } from '../app/api';\r\nimport { fetchSampler } from '../utility/misc';\r\nimport { CubeFace, REVERSE_Z, Vector4, type Nullable } from '@zephyr3d/base';\r\n\r\n/**\r\n * Opacity layers, which is three rather than four because the fourth channel of\r\n * the result texture carries the depth the layers are measured from. Keeping\r\n * both in one texture is what lets the receiver read the whole technique through\r\n * the single shadow-map binding the lighting shaders declare.\r\n * @internal\r\n */\r\nconst DOM_LAYER_COUNT = 3;\r\n\r\n/** @internal Caster-pass uniform holding the frontmost depth from geometry pass 0. */\r\nconst UNIFORM_NAME_DOM_FRONT_DEPTH = 'Z_domFrontDepth';\r\n\r\n/**\r\n * Transmittance a fully opaque caster is recorded as, since zero has no finite\r\n * optical depth to blend. Dark enough to read as black, and small enough in the\r\n * exponent that several opaque layers can stack without saturating half floats.\r\n * @internal\r\n */\r\nconst DOM_MIN_TRANSMITTANCE = 0.001;\r\n\r\n/** @internal */\r\ntype DOMImplData = {\r\n /**\r\n * Frontmost caster depth, written by geometry pass 0 and sampled by pass 1.\r\n * Separate from the result texture on purpose: a texture cannot be a render\r\n * target and a sampled resource in the same pass.\r\n *\r\n * 2D even for a cube map: the shadow mapper draws both passes of one face\r\n * before moving to the next, so one face's worth is all pass 1 ever reads.\r\n */\r\n frontDepth: Texture2D;\r\n /**\r\n * RGB = cumulative optical depth per layer, A = the depth those layers start\r\n * at. A cube for point-projection lights (point and rect).\r\n */\r\n result: Texture2D | TextureCube;\r\n /** Targets {@link DOMImplData.frontDepth}, reusing the shared depth attachment. */\r\n depthFramebuffer: FrameBuffer;\r\n /** Targets {@link DOMImplData.result}. No depth attachment - pass 1 does not test. */\r\n opacityFramebuffer: FrameBuffer;\r\n};\r\n\r\n/**\r\n * Deep opacity map shadows.\r\n *\r\n * @remarks\r\n * Hair is the case an ordinary shadow map cannot express. A shadow map answers\r\n * \"is this point behind the nearest caster\", which is the right question for a\r\n * wall and the wrong one for ten thousand strands: light entering a groom is not\r\n * blocked at its surface, it is attenuated gradually as it passes more and more\r\n * fibres. A binary test renders that as a hard edge with everything behind it\r\n * uniformly black.\r\n *\r\n * A deep opacity map (Yuksel & Keyser 2008) records the attenuation instead of\r\n * the boundary. Geometry pass 0 writes the frontmost caster depth `z0` per texel.\r\n * Pass 1 rasterises the casters again and each fragment adds its optical depth to\r\n * every layer lying behind it, giving cumulative absorption sampled at three\r\n * depths measured *from `z0`* rather than from the light. Because the layers\r\n * follow the hair surface, three of them resolve what a plain opacity shadow map\r\n * needs dozens of uniformly spaced ones to match.\r\n *\r\n * Recording optical depth rather than coverage is what keeps it exact for solid\r\n * casters as well as thin ones, so a scene does not have to reserve this mode for\r\n * its hair: see the caster output for why the two differ.\r\n *\r\n * WebGPU only, and deliberately so: the strand geometry this exists to shadow is\r\n * itself WebGPU only, so supporting the WebGL fallbacks - cascade atlases instead\r\n * of array layers, RGBA8-packed depth instead of float - would double the surface\r\n * area to serve no material.\r\n *\r\n * @internal\r\n */\r\nexport class DOM extends ShadowImpl {\r\n /** @internal */\r\n private _layerDistance: number;\r\n /** @internal */\r\n private _density: number;\r\n /** @internal Width of the sampling kernel in texels; 1 disables filtering. */\r\n private _filterSize: number;\r\n /** @internal */\r\n private readonly _paramsScratch: Vector4;\r\n /**\r\n * @internal\r\n * Which geometry pass is being rasterised. Lives on the implementation rather\r\n * than in `implData` because {@link DOM.getShaderHash} has no access to the\r\n * params, and the hash must separate the two passes or they share a program.\r\n */\r\n private _geometryPass: number;\r\n /**\r\n * @internal\r\n * Depth the shadow camera spans, captured when the map is rendered. Needed to\r\n * express {@link DOM.layerDistance} in world units: the shader compares device\r\n * depths, and for the orthographic projection a directional light uses those\r\n * are the world depth divided by exactly this.\r\n */\r\n private _depthRange: number;\r\n constructor(layerDistance = 0.25, density = 1, filterSize = 5) {\r\n super();\r\n this._layerDistance = layerDistance;\r\n this._density = density;\r\n this._filterSize = DOM.clampFilterSize(filterSize);\r\n this._paramsScratch = new Vector4();\r\n this._geometryPass = 0;\r\n this._depthRange = 1;\r\n }\r\n /** @internal */\r\n private static clampFilterSize(val: number) {\r\n return val !== 1 && val !== 3 && val !== 5 && val !== 7 ? 5 : val;\r\n }\r\n /**\r\n * Width of the sampling kernel, in shadow map texels. One of 1, 3, 5 or 7.\r\n *\r\n * @remarks\r\n * The graded transmittance this technique records runs along the light, not\r\n * across the map, so at the silhouette of a groom - where the change is one of\r\n * coverage rather than of depth - a single tap is as abrupt as an unfiltered\r\n * shadow map. This is the kernel that softens that edge, and it is the same\r\n * knob PCF's kernel size is, with the difference that each tap here costs a\r\n * layer lookup rather than a depth comparison.\r\n *\r\n * Set to 1 to sample once, which is measurably cheaper and visibly harder.\r\n */\r\n get filterSize() {\r\n return this._filterSize;\r\n }\r\n set filterSize(val) {\r\n this._filterSize = DOM.clampFilterSize(val);\r\n }\r\n /**\r\n * Depth the layers span, in world units along the light direction.\r\n *\r\n * @remarks\r\n * Set it to roughly the thickness of the hair. Too small and everything past\r\n * the outer strands saturates the last layer, which is a hard shadow again;\r\n * too large and all three layers land inside the first strand, leaving the\r\n * interior unshadowed.\r\n *\r\n * Exact for directional lights, whose orthographic projection makes device\r\n * depth a linear function of world depth, and for point and rect lights,\r\n * whose cube maps store distance from the light. Spot lights project\r\n * perspectively, so there the value is only accurate near the middle of the\r\n * shadow camera's range - which is where hair lit by one usually sits.\r\n */\r\n get layerDistance() {\r\n return this._layerDistance;\r\n }\r\n set layerDistance(val) {\r\n this._layerDistance = val > 0 ? val : 0.0001;\r\n }\r\n /**\r\n * Artistic multiplier on the absorption the casters actually recorded.\r\n *\r\n * @remarks\r\n * One reproduces alpha compositing exactly and is the right default. Raise it\r\n * to deepen the interior of a groom without moving the layers, lower it to let\r\n * more light through than the geometry strictly would.\r\n */\r\n get density() {\r\n return this._density;\r\n }\r\n set density(val) {\r\n this._density = val < 0 ? 0 : val;\r\n }\r\n getType() {\r\n return 'dom' as const;\r\n }\r\n resourceDirty() {\r\n return this._resourceDirty;\r\n }\r\n getShadowMapBorder() {\r\n // Margin so the kernel's outer taps still land inside the map at the edges of\r\n // the shadow region, matching what the PCF implementations reserve.\r\n return this._filterSize;\r\n }\r\n getDepthScale() {\r\n return 1;\r\n }\r\n setDepthScale(_val: number) {}\r\n /**\r\n * Layer geometry and density, for both the caster and the receiver. `z` and\r\n * `w` are unused.\r\n *\r\n * @remarks\r\n * `x` is the layer span converted from world units into the device-depth\r\n * difference the shaders actually compare, using the range captured when the\r\n * map was rendered.\r\n */\r\n getParams(out?: Vector4) {\r\n const result = out ?? this._paramsScratch;\r\n result.setXYZW(this._layerDistance / this._depthRange, this._density, 0, 0);\r\n return result;\r\n }\r\n getGeometryPassCount() {\r\n return 2;\r\n }\r\n supportsCascades() {\r\n // Each split would need its own depth and layer set, and both already share\r\n // the one texture the receiver can bind.\r\n return false;\r\n }\r\n clipsCasterAlpha() {\r\n // Neither pass wants the clip. Pass 1 integrates the alpha, and clipping is\r\n // destructive to it in both of the forms the material applies: a dithered\r\n // caster survives with probability alpha and then contributes the absorption\r\n // of that same alpha, counting it twice, and a hard cutoff drops the sub-pixel\r\n // strands that carry most of a groom's transmittance.\r\n //\r\n // Pass 0 skips it for a different reason. Its job is to find the frontmost\r\n // strand, and under dithering the clip makes that choice per-pixel random -\r\n // the layers would then start at a depth that flickers between strands, and\r\n // every opacity reading behind it inherits the jitter.\r\n //\r\n // The case this gives up is a caster whose alpha is a real mask rather than a\r\n // coverage value, such as a hair card with cut-out texels: pass 0 will place\r\n // z0 on the card's surface even where it is fully transparent. Strand\r\n // geometry, which is what this technique is for, has no such texels.\r\n return false;\r\n }\r\n beginGeometryPass(shadowMapParams: ShadowMapParams, pass: number) {\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n this._geometryPass = pass;\r\n // The light camera is finalised by the time the casters are drawn, so this is\r\n // where the world-to-device depth scale becomes known. It stays valid for the\r\n // lighting pass that follows, which reads the same converted params back.\r\n // A cube map stores radial distance over the light's range instead, which is\r\n // what the layer span must then be measured against.\r\n const range = isCube(shadowMapParams)\r\n ? (shadowMapParams.depthRange ?? 1)\r\n : shadowMapParams.cameraParams.y - shadowMapParams.cameraParams.x;\r\n this._depthRange = range > 1e-6 ? range : 1;\r\n if (isCube(shadowMapParams)) {\r\n // These framebuffers are this implementation's own, so the face the shadow\r\n // mapper selected on the shared one has to be selected on them too.\r\n const face = shadowMapParams.cubeFace ?? CubeFace.PX;\r\n if (pass === 0) {\r\n implData.depthFramebuffer.setDepthAttachmentCubeFace(face);\r\n } else {\r\n implData.opacityFramebuffer.setColorAttachmentCubeFace(0, face);\r\n }\r\n }\r\n getDevice().setFramebuffer(pass === 0 ? implData.depthFramebuffer : implData.opacityFramebuffer);\r\n }\r\n setCasterRenderStates(_shadowMapParams: ShadowMapParams, stateSet: RenderStateSet) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n // Every strand between z0 and the last layer has to contribute, so the pass\r\n // must not depth-test against the frontmost surface pass 0 resolved, and must\r\n // not write depth of its own - its framebuffer has no depth attachment at all.\r\n // Optical depth sums across the three layer channels; alpha instead carries\r\n // z0, which every fragment reads from the same texel, so replacing is correct\r\n // where summing would multiply it by the number of overlapping strands.\r\n stateSet\r\n .useBlendingState()\r\n .enable(true)\r\n .setBlendEquation('add', 'add')\r\n .setBlendFuncRGB('one', 'one')\r\n .setBlendFuncAlpha('one', 'zero');\r\n stateSet.useDepthState().enableTest(false).enableWrite(false);\r\n }\r\n getShadowMapClearColor(shadowMapParams: ShadowMapParams) {\r\n // Radial distance in a cube map is linear, so reverse-Z does not flip it.\r\n const farthest = REVERSE_Z && !isCube(shadowMapParams) ? 0 : 1;\r\n if (this._geometryPass === 1) {\r\n // No hair over this texel means no absorption. Alpha carries z0, and the\r\n // sentinel makes an uncovered texel read as \"nothing in front\".\r\n return new Vector4(0, 0, 0, farthest);\r\n }\r\n return new Vector4(farthest, farthest, farthest, 1);\r\n }\r\n getShadowMapColorFormat(_shadowMapParams: ShadowMapParams) {\r\n // Null keeps the framebuffer the caller allocates depth-only. The colour this\r\n // technique needs is allocated here, against framebuffers of its own, so\r\n // letting the caller also allocate a full-size colour attachment would waste\r\n // it outright.\r\n return null;\r\n }\r\n getShadowMapDepthFormat(_shadowMapParams: ShadowMapParams) {\r\n return this.preferredShadowMapDepthFormat();\r\n }\r\n useNativeShadowMap(_shadowMapParams: ShadowMapParams) {\r\n // The receiver needs the actual stored values - a depth to measure offsets\r\n // from and three sums to interpolate - not the result of a hardware compare.\r\n return false;\r\n }\r\n getShadowMap(shadowMapParams: ShadowMapParams) {\r\n return (shadowMapParams.implData as DOMImplData).result as ShadowMapType;\r\n }\r\n /**\r\n * Format for both targets.\r\n *\r\n * @remarks\r\n * Full float wherever the accumulation pass can blend into it, and the reason\r\n * is the anchor depth, not the absorption sums. `z0` is stored absolute, in\r\n * units of the shadow camera's whole depth range, and every layer coordinate\r\n * on both sides of the technique is a difference against it divided by the\r\n * layer span. At half precision its quantisation step is about 2^-11 of the\r\n * stored value - roughly `0.0005 * depthRange` in world units - which for a\r\n * shadow camera spanning a large scene is comparable to the depth of the hair\r\n * itself. The error is independent per texel, so it does not read as bias but\r\n * as blotches: patches of a backlit groom whose receivers land in front of\r\n * their quantised `z0` and come out fully lit. A layer span large enough to\r\n * drown the noise hides it, but throws away the graded falloff the technique\r\n * exists for.\r\n *\r\n * Half float remains the fallback for devices whose blending cannot target\r\n * full float; there the practical mitigation is a tight shadow distance.\r\n * @internal\r\n */\r\n private colorFormat(): TextureFormat {\r\n const caps = getDevice().getDeviceCaps().textureCaps;\r\n if (caps.supportFloatColorBuffer && caps.supportFloatBlending) {\r\n return 'rgba32f';\r\n }\r\n return caps.supportHalfFloatColorBuffer ? 'rgba16f' : 'rgba32f';\r\n }\r\n doUpdateResources(shadowMapParams: ShadowMapParams) {\r\n const device = getDevice();\r\n const sharedDepth = shadowMapParams.shadowMapFramebuffer!.getDepthAttachment()!;\r\n const width = sharedDepth.width;\r\n const height = sharedDepth.height;\r\n const format = this.colorFormat();\r\n // Everything here is pooled, per frame, the way the blur targets of VSM and\r\n // ESM are. `implData` cannot cache across frames even though it looks like it\r\n // could: it lives on a ShadowMapParams that is recycled between every light\r\n // and cleared at the end of each frame, so holding directly-created textures\r\n // in it leaks them at whatever rate the scene renders.\r\n const frontDepth = device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n const result = isCube(shadowMapParams)\r\n ? device.pool.fetchTemporalTextureCube(false, format, width, false)\r\n : device.pool.fetchTemporalTexture2D(false, format, width, height, false);\r\n // Pass 0 borrows the shadow map's own depth attachment, which is otherwise\r\n // unused - this implementation asks for no colour there - so the hardware\r\n // depth test resolves the frontmost strand for it. Pass 1 gets no depth,\r\n // which is both what stops it testing and what frees `frontDepth` to be\r\n // sampled while `result` is written.\r\n const depthFramebuffer = device.pool.createTemporalFramebuffer(true, [frontDepth], sharedDepth);\r\n const opacityFramebuffer = device.pool.createTemporalFramebuffer(true, [result], null);\r\n // The framebuffers hold the references now; these drop the fetch counts so\r\n // both textures return to the pool when the frame ends.\r\n device.pool.releaseTexture(frontDepth);\r\n device.pool.releaseTexture(result);\r\n shadowMapParams.implData = {\r\n frontDepth,\r\n result,\r\n depthFramebuffer,\r\n opacityFramebuffer\r\n } satisfies DOMImplData;\r\n shadowMapParams.shadowMap = result;\r\n shadowMapParams.shadowMapSampler = result.getDefaultSampler(false);\r\n this._resourceDirty = false;\r\n }\r\n postRenderShadowMap(_shadowMapParams: ShadowMapParams) {}\r\n getShaderHash() {\r\n // The two geometry passes emit different caster fragments and the shadow pass\r\n // keys its programs on this hash, so the pass index has to appear in it. The\r\n // kernel is unrolled into the receiver, so it belongs here too.\r\n return `${DOM_LAYER_COUNT}_${this._geometryPass}_${this._filterSize}`;\r\n }\r\n declareCasterUniforms(scope: PBGlobalScope, _shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const pb = scope.$builder;\r\n // sampleType before uniform(), matching how the receiver's shadow map is\r\n // declared: the binding is created from the accumulated descriptor.\r\n const tex = pb.tex2D();\r\n tex.sampleType('unfilterable-float');\r\n scope[UNIFORM_NAME_DOM_FRONT_DEPTH] = tex.uniform(0);\r\n }\r\n applyCasterUniforms(bindGroup: BindGroup, shadowMapParams: ShadowMapParams) {\r\n if (this._geometryPass !== 1) {\r\n return;\r\n }\r\n const implData = shadowMapParams.implData as DOMImplData;\r\n bindGroup.setTexture(\r\n UNIFORM_NAME_DOM_FRONT_DEPTH,\r\n implData.frontDepth,\r\n fetchSampler('clamp_nearest_nomip')\r\n );\r\n }\r\n /**\r\n * How far a depth lies behind the frontmost strand, in layer-span units.\r\n *\r\n * @remarks\r\n * Both callers measure \"deeper into the hair than z0\", but which direction that\r\n * is depends on the depth encoding: under reverse-Z a farther surface has the\r\n * *smaller* value, so the plain subtraction is negative for every fragment\r\n * behind the front and the clamp below flattens the whole technique to no\r\n * shadow at all.\r\n * @internal\r\n */\r\n private layerCoord(\r\n scope: PBInsideFunctionScope,\r\n depth: PBShaderExp,\r\n z0: PBShaderExp,\r\n layerSpan: PBShaderExp,\r\n radial: boolean\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n // A cube map's radial distance grows away from the light whatever the depth\r\n // convention.\r\n const delta = REVERSE_Z && !radial ? pb.sub(z0, depth) : pb.sub(depth, z0);\r\n return pb.div(pb.max(delta, 0), layerSpan);\r\n }\r\n /**\r\n * Caster output.\r\n *\r\n * Pass 0 writes the frontmost depth. Pass 1 writes this fragment's optical depth\r\n * into the layers behind it, for additive blending to sum, and carries z0\r\n * through alpha so the receiver can find where the layers start.\r\n */\r\n computeShadowMapDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp,\r\n alpha: Nullable<PBShaderExp>\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const geometryPass = this._geometryPass;\r\n // Alpha travels as a parameter. Reaching into the caller's scope for its\r\n // `outColor` would be reading a local of a different shader function, and the\r\n // two cases that matter - an opaque caster and a fully transparent one - are\r\n // the same value there.\r\n const hasAlpha = geometryPass === 1 && !!alpha;\r\n const funcName = `lib_domCasterOutput_${geometryPass}_${hasAlpha ? 'a' : 'o'}${isCube(shadowMapParams) ? '_c' : ''}`;\r\n const params = hasAlpha ? [pb.vec3('worldPos'), pb.float('alpha')] : [pb.vec3('worldPos')];\r\n pb.func(funcName, params, function () {\r\n this.$l.depth = that.casterDepth(shadowMapParams, this, this.worldPos);\r\n if (geometryPass === 0) {\r\n this.$return(pb.vec4(this.depth, 0, 0, 1));\r\n } else {\r\n this.$l.z0 = pb.textureLoad(\r\n this[UNIFORM_NAME_DOM_FRONT_DEPTH],\r\n pb.ivec2(this.$builtins.fragCoord.xy),\r\n 0\r\n ).x;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n // Distance behind the frontmost strand, in layer-span units. A fragment at\r\n // or in front of z0 lands at zero and fills every layer.\r\n this.$l.t = that.layerCoord(this, this.depth, this.z0, this.layerSpan, isCube(shadowMapParams));\r\n // Layer k's far boundary sits at (k+1)/3 of the span, and a fragment\r\n // contributes to every layer whose boundary lies behind it. The last\r\n // layer has no far boundary: it extends to the end of the caster volume,\r\n // so a fragment deeper than the span still lands in it and the third\r\n // layer holds the cumulative absorption of *everything* behind z0.\r\n // Dropping deep fragments instead - step(t, 1) - deletes the hair behind\r\n // the front slice from the map entirely, and any receiver deeper than\r\n // the span reads only that slice: wherever it happens to be sparse, the\r\n // middle of a dense backlit groom comes out fully lit in blotches.\r\n this.$l.mask = pb.vec3(pb.step(this.t, 1 / 3), pb.step(this.t, 2 / 3), 1);\r\n // A caster that computes no fragment colour covers fully.\r\n this.$l.casterAlpha = hasAlpha ? this.alpha : pb.float(1);\r\n // Optical depth rather than raw coverage, because what has to be additive\r\n // here is the exponent, not the alpha. Compositing N layers multiplies\r\n // their transmittances - prod(1 - a) - and blending can only sum, so each\r\n // fragment contributes -log(1 - a) and the receiver's exp(-sum) reproduces\r\n // that product exactly.\r\n //\r\n // Summing alpha instead makes exp(-sum) an approximation that only holds\r\n // while alpha is small, which is true of a sub-pixel strand and false of\r\n // anything solid: a single opaque caster would sum to 1 and shadow to\r\n // exp(-1), a 37% grey rather than black.\r\n //\r\n // The floor bounds what alpha = 1 encodes. It has to be finite to blend,\r\n // and 0.001 transmittance is already black; it also leaves room for\r\n // several opaque layers to stack without leaving half precision.\r\n this.$l.opticalDepth = pb.neg(pb.log(pb.max(pb.sub(1, this.casterAlpha), DOM_MIN_TRANSMITTANCE)));\r\n this.$return(pb.vec4(pb.mul(this.mask, this.opticalDepth), this.z0));\r\n }\r\n });\r\n const global = pb.getGlobalScope();\r\n return (hasAlpha ? global[funcName](worldPos, alpha!) : global[funcName](worldPos)) as PBShaderExp;\r\n }\r\n /**\r\n * Normalized light-space depth of a caster fragment, in the encoding the\r\n * receiver reconstructs.\r\n * @internal\r\n */\r\n private casterDepth(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n worldPos: PBShaderExp\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n if (shadowMapParams.lightType === LIGHT_TYPE_POINT) {\r\n const lightSpacePos = pb.mul(ShaderHelper.getLightViewMatrixForShadow(scope), pb.vec4(worldPos, 1));\r\n return pb.clamp(\r\n pb.div(pb.length(lightSpacePos.xyz), ShaderHelper.getLightPositionAndRangeForShadow(scope).w),\r\n 0,\r\n 1\r\n );\r\n }\r\n return pb.emulateDepthClamp ? pb.clamp(scope.$inputs.clamppedDepth, 0, 1) : scope.$builtins.fragCoord.z;\r\n }\r\n computeShadow(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp\r\n ) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n if (isCube(shadowMapParams)) {\r\n // The shadow matrix is the identity for a cube map, so the \"shadow vertex\"\r\n // is the receiver's world position; its depth is the radial distance the\r\n // casters stored, over the same range.\r\n pb.func('lib_computeShadowDOMCube', [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.posRange = ShaderHelper.getLightPositionAndRangeForShadow(this);\r\n this.$l.dir = pb.sub(this.shadowVertex.xyz, this.posRange.xyz);\r\n this.$l.depth = pb.div(pb.length(this.dir), this.posRange.w);\r\n this.$l.shadow = pb.float(1);\r\n this.$if(pb.lessThanEqual(this.depth, 1), function () {\r\n // The kernel needs the bias for the same reason as the 2D map below.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(shadowMapParams.lightType, this, this.depth, this.NdotL, true);\r\n this.depth = applyShadowDepthBias(this, this.depth, this.bias, false);\r\n }\r\n this.shadow = that.transmittanceCube(this, this.dir, this.depth);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope().lib_computeShadowDOMCube(shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n const funcName = 'lib_computeShadowDOM';\r\n pb.func(funcName, [pb.vec4('shadowVertex'), pb.float('NdotL')], function () {\r\n this.$l.shadowCoord = pb.div(this.shadowVertex.xyz, this.shadowVertex.w);\r\n this.$l.shadowCoord = ndcToShadowCoord3(this, this.shadowCoord.xyz);\r\n this.$l.inRange = pb.all(\r\n pb.bvec2(\r\n pb.all(\r\n pb.bvec4(\r\n pb.greaterThanEqual(this.shadowCoord.x, 0),\r\n pb.lessThanEqual(this.shadowCoord.x, 1),\r\n pb.greaterThanEqual(this.shadowCoord.y, 0),\r\n pb.lessThanEqual(this.shadowCoord.y, 1)\r\n )\r\n ),\r\n shadowCoordDepthInRange(this, this.shadowCoord.z)\r\n )\r\n );\r\n this.$l.shadow = pb.float(1);\r\n this.$if(this.inRange, function () {\r\n // A single tap needs no bias: it reads the texel the receiver itself\r\n // wrote, so its own surface sits exactly at z0 and contributes nothing.\r\n // A kernel breaks that. Neighbouring texels record the frontmost surface\r\n // at their own position, which on anything sloped is nearer the light\r\n // than the receiver, and the receiver then reads itself as being behind a\r\n // caster. On a solid surface that is the full jump from no absorption to\r\n // all of it, so it shows up as the banding an unbiased shadow map has.\r\n if (that._filterSize > 1) {\r\n this.$l.bias = computeShadowBias(\r\n shadowMapParams.lightType,\r\n this,\r\n this.shadowCoord.z,\r\n this.NdotL,\r\n false\r\n );\r\n this.shadowCoord.z = applyShadowDepthBias(this, this.shadowCoord.z, this.bias, true);\r\n }\r\n this.shadow = that.transmittance(this, this.shadowCoord);\r\n });\r\n this.$return(this.shadow);\r\n });\r\n return pb.getGlobalScope()[funcName](shadowVertex, NdotL) as PBShaderExp;\r\n }\r\n computeShadowCSM(\r\n shadowMapParams: ShadowMapParams,\r\n scope: PBInsideFunctionScope,\r\n shadowVertex: PBShaderExp,\r\n NdotL: PBShaderExp,\r\n _split: PBShaderExp\r\n ) {\r\n // Cascades would need a depth and a layer set per split, which no longer fits\r\n // the one texture the single shadow-map binding allows. Callers keep working\r\n // by shadowing from the first cascade's map.\r\n return this.computeShadow(shadowMapParams, scope, shadowVertex, NdotL);\r\n }\r\n /**\r\n * Fraction of light surviving the hair in front of the receiver, averaged over\r\n * the filter kernel.\r\n *\r\n * @remarks\r\n * The averaging is over transmittance, one value per tap, rather than over the\r\n * stored texels. Blending the texels first would interpolate `z0` across the\r\n * silhouette of the groom, where one side holds a real strand depth and the\r\n * other the empty-texel sentinel, and the depth halfway between them describes\r\n * nothing - every layer reading taken against it would be measured from the\r\n * wrong origin. Averaging the results instead asks a well-posed question of\r\n * each texel and combines only the answers, which is also what makes this an\r\n * antialiased edge rather than a blurred one.\r\n * @internal\r\n */\r\n private transmittance(scope: PBInsideFunctionScope, shadowCoord: PBShaderExp): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittance_${size}`;\r\n pb.func(funcName, [pb.vec3('shadowCoord')], function () {\r\n if (size <= 1) {\r\n this.$return(that.tapTransmittance(this, this.shadowCoord.xy, this.shadowCoord.z));\r\n } else {\r\n // cameraParams.z carries the shadow map size, and this implementation\r\n // never splits into cascades, so the map is exactly that wide.\r\n this.$l.texelSize = pb.div(1, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapUV = pb.vec2();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapUV = pb.add(this.shadowCoord.xy, pb.mul(pb.vec2(x, y), this.texelSize));\r\n this.sum = pb.add(this.sum, that.tapTransmittance(this, this.tapUV, this.shadowCoord.z));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](shadowCoord) as PBShaderExp;\r\n }\r\n /**\r\n * {@link DOM.transmittance} for a cube map: the same kernel, laid out on the\r\n * face around the receiver's direction.\r\n *\r\n * @remarks\r\n * The taps step one texel at a time on the unit cube, where a face texel spans\r\n * `2 / size`, in a plane perpendicular to the ray - which matches the face's\r\n * own grid at its centre and differs only to second order off it.\r\n * @internal\r\n */\r\n private transmittanceCube(scope: PBInsideFunctionScope, dir: PBShaderExp, receiverDepth: PBShaderExp) {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const size = this._filterSize;\r\n const funcName = `lib_domTransmittanceCube_${size}`;\r\n pb.func(funcName, [pb.vec3('dir'), pb.float('receiverDepth')], function () {\r\n if (size <= 1) {\r\n this.$return(that.layerTransmittance(this, this.dir, this.receiverDepth, true));\r\n } else {\r\n this.$l.unitDir = pb.normalize(this.dir);\r\n this.$l.onCube = pb.div(\r\n this.unitDir,\r\n pb.max(pb.max(pb.abs(this.unitDir.x), pb.abs(this.unitDir.y)), pb.abs(this.unitDir.z))\r\n );\r\n this.$l.helper = this.$choice(\r\n pb.lessThan(pb.abs(this.unitDir.y), 0.99),\r\n pb.vec3(0, 1, 0),\r\n pb.vec3(1, 0, 0)\r\n );\r\n this.$l.side = pb.normalize(pb.cross(this.helper, this.unitDir));\r\n this.$l.up = pb.cross(this.unitDir, this.side);\r\n this.$l.texelSize = pb.div(2, ShaderHelper.getShadowCameraParams(this).z);\r\n this.$l.sum = pb.float(0);\r\n this.$l.tapDir = pb.vec3();\r\n const radius = (size - 1) / 2;\r\n for (let y = -radius; y <= radius; y++) {\r\n for (let x = -radius; x <= radius; x++) {\r\n this.tapDir = pb.add(\r\n this.onCube,\r\n pb.mul(pb.add(pb.mul(this.side, x), pb.mul(this.up, y)), this.texelSize)\r\n );\r\n this.sum = pb.add(this.sum, that.layerTransmittance(this, this.tapDir, this.receiverDepth, true));\r\n }\r\n }\r\n this.$return(pb.div(this.sum, size * size));\r\n }\r\n });\r\n return pb.getGlobalScope()[funcName](dir, receiverDepth) as PBShaderExp;\r\n }\r\n /**\r\n * Transmittance from a single shadow map texel.\r\n * @internal\r\n */\r\n private tapTransmittance(\r\n scope: PBInsideFunctionScope,\r\n uv: PBShaderExp,\r\n receiverDepth: PBShaderExp\r\n ): PBShaderExp {\r\n return this.layerTransmittance(scope, uv, receiverDepth, false);\r\n }\r\n /**\r\n * Transmittance from the texel at `coord` - a map UV, or for a cube map a\r\n * direction from the light.\r\n * @internal\r\n */\r\n private layerTransmittance(\r\n scope: PBInsideFunctionScope,\r\n coord: PBShaderExp,\r\n receiverDepth: PBShaderExp,\r\n radial: boolean\r\n ): PBShaderExp {\r\n const pb = scope.$builder;\r\n const that = this;\r\n const funcName = radial ? 'lib_domTapCube' : 'lib_domTap';\r\n pb.func(funcName, [radial ? pb.vec3('coord') : pb.vec2('coord'), pb.float('receiverDepth')], function () {\r\n this.$l.texel = pb.textureSampleLevel(ShaderHelper.getShadowMap(this), this.coord, 0);\r\n this.$l.layers = this.texel.rgb;\r\n this.$l.z0 = this.texel.a;\r\n this.$l.layerSpan = ShaderHelper.getShadowImplParams(this).x;\r\n this.$l.density = ShaderHelper.getShadowImplParams(this).y;\r\n this.$l.t = that.layerCoord(this, this.receiverDepth, this.z0, this.layerSpan, radial);\r\n // The layers are cumulative, so opacity at an arbitrary depth is a lerp\r\n // between the two bracketing layer values. Scaling t by the layer count puts\r\n // the integer part on the near layer and the fraction between the pair.\r\n this.$l.scaled = pb.clamp(pb.mul(this.t, DOM_LAYER_COUNT), 0, DOM_LAYER_COUNT);\r\n this.$l.index = pb.floor(this.scaled);\r\n this.$l.frac = pb.sub(this.scaled, this.index);\r\n // Nothing has been traversed before the first layer, so the near value at\r\n // index 0 is zero rather than layers.x.\r\n this.$l.near = pb.float(0);\r\n this.$l.far = this.layers.x;\r\n this.$if(pb.greaterThanEqual(this.index, 2), function () {\r\n this.near = this.layers.y;\r\n this.far = this.layers.z;\r\n }).$elseif(pb.greaterThanEqual(this.index, 1), function () {\r\n this.near = this.layers.x;\r\n this.far = this.layers.y;\r\n });\r\n // Optical depth is what accumulates linearly through a medium, so the lerp\r\n // between two layer readings is meaningful in a way that lerping stored\r\n // alphas would not have been.\r\n this.$l.absorption = pb.mix(this.near, this.far, this.frac);\r\n // Beer-Lambert. With the casters recording -log(1 - alpha) this is exactly\r\n // prod(1 - alpha) over everything crossed, so a solid caster reaches black\r\n // and a stack of thin strands reaches the same value alpha compositing them\r\n // would have.\r\n this.$return(pb.exp(pb.neg(pb.mul(this.absorption, this.density))));\r\n });\r\n return pb.getGlobalScope()[funcName](coord, receiverDepth) as PBShaderExp;\r\n }\r\n}\r\n\r\n/** Whether the map is a point-projection cube (point and rect lights). @internal */\r\nfunction isCube(shadowMapParams: ShadowMapParams) {\r\n return shadowMapParams.lightType === LIGHT_TYPE_POINT;\r\n}\r\n"],"names":["DOM_LAYER_COUNT","UNIFORM_NAME_DOM_FRONT_DEPTH","DOM_MIN_TRANSMITTANCE","DOM","ShadowImpl","layerDistance","density","filterSize","_layerDistance","_density","_filterSize","clampFilterSize","_paramsScratch","Vector4","_geometryPass","_depthRange","val","getType","resourceDirty","_resourceDirty","getShadowMapBorder","getDepthScale","setDepthScale","_val","getParams","out","result","setXYZW","getGeometryPassCount","supportsCascades","clipsCasterAlpha","beginGeometryPass","shadowMapParams","pass","implData","range","isCube","depthRange","cameraParams","y","x","face","cubeFace","CubeFace","PX","depthFramebuffer","setDepthAttachmentCubeFace","opacityFramebuffer","setColorAttachmentCubeFace","getDevice","setFramebuffer","setCasterRenderStates","_shadowMapParams","stateSet","useBlendingState","enable","setBlendEquation","setBlendFuncRGB","setBlendFuncAlpha","useDepthState","enableTest","enableWrite","getShadowMapClearColor","farthest","REVERSE_Z","getShadowMapColorFormat","getShadowMapDepthFormat","preferredShadowMapDepthFormat","useNativeShadowMap","getShadowMap","caps","getDeviceCaps","textureCaps","supportFloatColorBuffer","supportFloatBlending","supportHalfFloatColorBuffer","doUpdateResources","device","sharedDepth","shadowMapFramebuffer","getDepthAttachment","width","height","format","colorFormat","frontDepth","pool","fetchTemporalTexture2D","fetchTemporalTextureCube","createTemporalFramebuffer","releaseTexture","shadowMap","shadowMapSampler","getDefaultSampler","postRenderShadowMap","getShaderHash","declareCasterUniforms","scope","pb","$builder","tex","tex2D","sampleType","uniform","applyCasterUniforms","bindGroup","setTexture","fetchSampler","layerCoord","depth","z0","layerSpan","radial","delta","sub","div","max","computeShadowMapDepth","worldPos","alpha","that","geometryPass","hasAlpha","funcName","params","vec3","float","func","$l","casterDepth","$return","vec4","textureLoad","ivec2","$builtins","fragCoord","xy","ShaderHelper","getShadowImplParams","t","mask","step","casterAlpha","opticalDepth","neg","log","mul","global","getGlobalScope","lightType","LIGHT_TYPE_POINT","lightSpacePos","getLightViewMatrixForShadow","clamp","length","xyz","getLightPositionAndRangeForShadow","w","emulateDepthClamp","$inputs","clamppedDepth","z","computeShadow","shadowVertex","NdotL","posRange","dir","shadow","$if","lessThanEqual","bias","computeShadowBias","applyShadowDepthBias","transmittanceCube","lib_computeShadowDOMCube","shadowCoord","ndcToShadowCoord3","inRange","all","bvec2","bvec4","greaterThanEqual","shadowCoordDepthInRange","transmittance","computeShadowCSM","_split","size","tapTransmittance","texelSize","getShadowCameraParams","sum","tapUV","vec2","radius","add","receiverDepth","layerTransmittance","unitDir","normalize","onCube","abs","helper","$choice","lessThan","side","cross","up","tapDir","uv","coord","texel","textureSampleLevel","layers","rgb","a","scaled","index","floor","frac","near","far","$elseif","absorption","mix","exp"],"mappings":";;;;;;;;;AAqBA;;;;;;AAMC,IACD,MAAMA,eAAkB,GAAA,CAAA;AAExB,uFACA,MAAMC,4BAA+B,GAAA,iBAAA;AAErC;;;;;AAKC,IACD,MAAMC,qBAAwB,GAAA,KAAA;AAwB9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BO,MAAMC,GAAYC,SAAAA,UAAAA,CAAAA;qBAEvB,cAA+B;qBAE/B,QAAyB;mFAEzB,WAA4B;qBAE5B,cAAyC;AACzC;;;;;AAKC,MACD,aAA8B;AAC9B;;;;;;AAMC,MACD,WAA4B;IAC5B,WAAYC,CAAAA,aAAAA,GAAgB,IAAI,EAAEC,OAAAA,GAAU,CAAC,EAAEC,UAAAA,GAAa,CAAC,CAAE;QAC7D,KAAK,EAAA;QACL,IAAI,CAACC,cAAc,GAAGH,aAAAA;QACtB,IAAI,CAACI,QAAQ,GAAGH,OAAAA;AAChB,QAAA,IAAI,CAACI,WAAW,GAAGP,GAAAA,CAAIQ,eAAe,CAACJ,UAAAA,CAAAA;QACvC,IAAI,CAACK,cAAc,GAAG,IAAIC,OAAAA,EAAAA;QAC1B,IAAI,CAACC,aAAa,GAAG,CAAA;QACrB,IAAI,CAACC,WAAW,GAAG,CAAA;AACrB;AACA,qBACA,OAAeJ,eAAgBK,CAAAA,GAAW,EAAE;QAC1C,OAAOA,GAAAA,KAAQ,KAAKA,GAAQ,KAAA,CAAA,IAAKA,QAAQ,CAAKA,IAAAA,GAAAA,KAAQ,IAAI,CAAIA,GAAAA,GAAAA;AAChE;AACA;;;;;;;;;;;;AAYC,MACD,IAAIT,UAAa,GAAA;QACf,OAAO,IAAI,CAACG,WAAW;AACzB;IACA,IAAIH,UAAAA,CAAWS,GAAG,EAAE;AAClB,QAAA,IAAI,CAACN,WAAW,GAAGP,GAAAA,CAAIQ,eAAe,CAACK,GAAAA,CAAAA;AACzC;AACA;;;;;;;;;;;;;;AAcC,MACD,IAAIX,aAAgB,GAAA;QAClB,OAAO,IAAI,CAACG,cAAc;AAC5B;IACA,IAAIH,aAAAA,CAAcW,GAAG,EAAE;AACrB,QAAA,IAAI,CAACR,cAAc,GAAGQ,GAAAA,GAAM,IAAIA,GAAM,GAAA,MAAA;AACxC;AACA;;;;;;;AAOC,MACD,IAAIV,OAAU,GAAA;QACZ,OAAO,IAAI,CAACG,QAAQ;AACtB;IACA,IAAIH,OAAAA,CAAQU,GAAG,EAAE;AACf,QAAA,IAAI,CAACP,QAAQ,GAAGO,GAAAA,GAAM,IAAI,CAAIA,GAAAA,GAAAA;AAChC;IACAC,OAAU,GAAA;QACR,OAAO,KAAA;AACT;IACAC,aAAgB,GAAA;QACd,OAAO,IAAI,CAACC,cAAc;AAC5B;IACAC,kBAAqB,GAAA;;;QAGnB,OAAO,IAAI,CAACV,WAAW;AACzB;IACAW,aAAgB,GAAA;QACd,OAAO,CAAA;AACT;IACAC,aAAcC,CAAAA,IAAY,EAAE;AAC5B;;;;;;;;MASAC,SAAAA,CAAUC,GAAa,EAAE;AACvB,QAAA,MAAMC,MAASD,GAAAA,GAAAA,IAAO,IAAI,CAACb,cAAc;AACzCc,QAAAA,MAAAA,CAAOC,OAAO,CAAC,IAAI,CAACnB,cAAc,GAAG,IAAI,CAACO,WAAW,EAAE,IAAI,CAACN,QAAQ,EAAE,CAAG,EAAA,CAAA,CAAA;QACzE,OAAOiB,MAAAA;AACT;IACAE,oBAAuB,GAAA;QACrB,OAAO,CAAA;AACT;IACAC,gBAAmB,GAAA;;;QAGjB,OAAO,KAAA;AACT;IACAC,gBAAmB,GAAA;;;;;;;;;;;;;;;;QAgBjB,OAAO,KAAA;AACT;IACAC,iBAAkBC,CAAAA,eAAgC,EAAEC,IAAY,EAAE;QAChE,MAAMC,QAAAA,GAAWF,gBAAgBE,QAAQ;QACzC,IAAI,CAACpB,aAAa,GAAGmB,IAAAA;;;;;;AAMrB,QAAA,MAAME,KAAQC,GAAAA,MAAAA,CAAOJ,eAChBA,CAAAA,GAAAA,eAAAA,CAAgBK,UAAU,IAAI,CAAA,GAC/BL,eAAgBM,CAAAA,YAAY,CAACC,CAAC,GAAGP,eAAgBM,CAAAA,YAAY,CAACE,CAAC;AACnE,QAAA,IAAI,CAACzB,WAAW,GAAGoB,KAAAA,GAAQ,OAAOA,KAAQ,GAAA,CAAA;AAC1C,QAAA,IAAIC,OAAOJ,eAAkB,CAAA,EAAA;;;AAG3B,YAAA,MAAMS,IAAOT,GAAAA,eAAAA,CAAgBU,QAAQ,IAAIC,SAASC,EAAE;AACpD,YAAA,IAAIX,SAAS,CAAG,EAAA;gBACdC,QAASW,CAAAA,gBAAgB,CAACC,0BAA0B,CAACL,IAAAA,CAAAA;aAChD,MAAA;AACLP,gBAAAA,QAAAA,CAASa,kBAAkB,CAACC,0BAA0B,CAAC,CAAGP,EAAAA,IAAAA,CAAAA;AAC5D;AACF;QACAQ,SAAYC,EAAAA,CAAAA,cAAc,CAACjB,IAAS,KAAA,CAAA,GAAIC,SAASW,gBAAgB,GAAGX,SAASa,kBAAkB,CAAA;AACjG;IACAI,qBAAsBC,CAAAA,gBAAiC,EAAEC,QAAwB,EAAE;AACjF,QAAA,IAAI,IAAI,CAACvC,aAAa,KAAK,CAAG,EAAA;AAC5B,YAAA;AACF;;;;;;;AAOAuC,QAAAA,QAAAA,CACGC,gBAAgB,EAAA,CAChBC,MAAM,CAAC,MACPC,gBAAgB,CAAC,KAAO,EAAA,KAAA,CAAA,CACxBC,eAAe,CAAC,KAAA,EAAO,KACvBC,CAAAA,CAAAA,iBAAiB,CAAC,KAAO,EAAA,MAAA,CAAA;AAC5BL,QAAAA,QAAAA,CAASM,aAAa,EAAGC,CAAAA,UAAU,CAAC,KAAA,CAAA,CAAOC,WAAW,CAAC,KAAA,CAAA;AACzD;AACAC,IAAAA,sBAAAA,CAAuB9B,eAAgC,EAAE;;AAEvD,QAAA,MAAM+B,QAAWC,GAAAA,SAAAA,IAAa,CAAC5B,MAAAA,CAAOJ,mBAAmB,CAAI,GAAA,CAAA;AAC7D,QAAA,IAAI,IAAI,CAAClB,aAAa,KAAK,CAAG,EAAA;;;AAG5B,YAAA,OAAO,IAAID,OAAAA,CAAQ,CAAG,EAAA,CAAA,EAAG,CAAGkD,EAAAA,QAAAA,CAAAA;AAC9B;AACA,QAAA,OAAO,IAAIlD,OAAAA,CAAQkD,QAAUA,EAAAA,QAAAA,EAAUA,QAAU,EAAA,CAAA,CAAA;AACnD;AACAE,IAAAA,uBAAAA,CAAwBb,gBAAiC,EAAE;;;;;QAKzD,OAAO,IAAA;AACT;AACAc,IAAAA,uBAAAA,CAAwBd,gBAAiC,EAAE;QACzD,OAAO,IAAI,CAACe,6BAA6B,EAAA;AAC3C;AACAC,IAAAA,kBAAAA,CAAmBhB,gBAAiC,EAAE;;;QAGpD,OAAO,KAAA;AACT;AACAiB,IAAAA,YAAAA,CAAarC,eAAgC,EAAE;AAC7C,QAAA,OAAO,eAACA,CAAgBE,QAAQ,CAAiBR,MAAM;AACzD;AACA;;;;;;;;;;;;;;;;;;;;AAoBC,MACD,WAAqC,GAAA;AACnC,QAAA,MAAM4C,IAAOrB,GAAAA,SAAAA,EAAAA,CAAYsB,aAAa,EAAA,CAAGC,WAAW;AACpD,QAAA,IAAIF,IAAKG,CAAAA,uBAAuB,IAAIH,IAAAA,CAAKI,oBAAoB,EAAE;YAC7D,OAAO,SAAA;AACT;QACA,OAAOJ,IAAAA,CAAKK,2BAA2B,GAAG,SAAY,GAAA,SAAA;AACxD;AACAC,IAAAA,iBAAAA,CAAkB5C,eAAgC,EAAE;AAClD,QAAA,MAAM6C,MAAS5B,GAAAA,SAAAA,EAAAA;AACf,QAAA,MAAM6B,WAAc9C,GAAAA,eAAAA,CAAgB+C,oBAAoB,CAAEC,kBAAkB,EAAA;QAC5E,MAAMC,KAAAA,GAAQH,YAAYG,KAAK;QAC/B,MAAMC,MAAAA,GAASJ,YAAYI,MAAM;QACjC,MAAMC,MAAAA,GAAS,IAAI,CAACC,WAAW,EAAA;;;;;;QAM/B,MAAMC,UAAAA,GAAaR,OAAOS,IAAI,CAACC,sBAAsB,CAAC,KAAA,EAAOJ,MAAQF,EAAAA,KAAAA,EAAOC,MAAQ,EAAA,KAAA,CAAA;QACpF,MAAMxD,MAAAA,GAASU,OAAOJ,eAClB6C,CAAAA,GAAAA,MAAAA,CAAOS,IAAI,CAACE,wBAAwB,CAAC,KAAOL,EAAAA,MAAAA,EAAQF,OAAO,KAC3DJ,CAAAA,GAAAA,MAAAA,CAAOS,IAAI,CAACC,sBAAsB,CAAC,KAAOJ,EAAAA,MAAAA,EAAQF,OAAOC,MAAQ,EAAA,KAAA,CAAA;;;;;;AAMrE,QAAA,MAAMrC,mBAAmBgC,MAAOS,CAAAA,IAAI,CAACG,yBAAyB,CAAC,IAAM,EAAA;AAACJ,YAAAA;SAAW,EAAEP,WAAAA,CAAAA;AACnF,QAAA,MAAM/B,qBAAqB8B,MAAOS,CAAAA,IAAI,CAACG,yBAAyB,CAAC,IAAM,EAAA;AAAC/D,YAAAA;SAAO,EAAE,IAAA,CAAA;;;QAGjFmD,MAAOS,CAAAA,IAAI,CAACI,cAAc,CAACL,UAAAA,CAAAA;QAC3BR,MAAOS,CAAAA,IAAI,CAACI,cAAc,CAAChE,MAAAA,CAAAA;AAC3BM,QAAAA,eAAAA,CAAgBE,QAAQ,GAAG;AACzBmD,YAAAA,UAAAA;AACA3D,YAAAA,MAAAA;AACAmB,YAAAA,gBAAAA;AACAE,YAAAA;AACF,SAAA;AACAf,QAAAA,eAAAA,CAAgB2D,SAAS,GAAGjE,MAAAA;AAC5BM,QAAAA,eAAAA,CAAgB4D,gBAAgB,GAAGlE,MAAOmE,CAAAA,iBAAiB,CAAC,KAAA,CAAA;QAC5D,IAAI,CAAC1E,cAAc,GAAG,KAAA;AACxB;IACA2E,mBAAoB1C,CAAAA,gBAAiC,EAAE;IACvD2C,aAAgB,GAAA;;;;AAId,QAAA,OAAO,CAAG/F,EAAAA,eAAAA,CAAgB,CAAC,EAAE,IAAI,CAACc,aAAa,CAAC,CAAC,EAAE,IAAI,CAACJ,WAAW,CAAE,CAAA;AACvE;IACAsF,qBAAsBC,CAAAA,KAAoB,EAAE7C,gBAAiC,EAAE;AAC7E,QAAA,IAAI,IAAI,CAACtC,aAAa,KAAK,CAAG,EAAA;AAC5B,YAAA;AACF;QACA,MAAMoF,EAAAA,GAAKD,MAAME,QAAQ;;;QAGzB,MAAMC,GAAAA,GAAMF,GAAGG,KAAK,EAAA;AACpBD,QAAAA,GAAAA,CAAIE,UAAU,CAAC,oBAAA,CAAA;AACfL,QAAAA,KAAK,CAAChG,4BAAAA,CAA6B,GAAGmG,GAAAA,CAAIG,OAAO,CAAC,CAAA,CAAA;AACpD;IACAC,mBAAoBC,CAAAA,SAAoB,EAAEzE,eAAgC,EAAE;AAC1E,QAAA,IAAI,IAAI,CAAClB,aAAa,KAAK,CAAG,EAAA;AAC5B,YAAA;AACF;QACA,MAAMoB,QAAAA,GAAWF,gBAAgBE,QAAQ;AACzCuE,QAAAA,SAAAA,CAAUC,UAAU,CAClBzG,4BAAAA,EACAiC,QAASmD,CAAAA,UAAU,EACnBsB,YAAa,CAAA,qBAAA,CAAA,CAAA;AAEjB;AACA;;;;;;;;;;MAWQC,UACNX,CAAAA,KAA4B,EAC5BY,KAAkB,EAClBC,EAAe,EACfC,SAAsB,EACtBC,MAAe,EACF;QACb,MAAMd,EAAAA,GAAKD,MAAME,QAAQ;;;AAGzB,QAAA,MAAMc,KAAQjD,GAAAA,SAAAA,IAAa,CAACgD,MAAAA,GAASd,EAAGgB,CAAAA,GAAG,CAACJ,EAAAA,EAAID,KAASX,CAAAA,GAAAA,EAAAA,CAAGgB,GAAG,CAACL,KAAOC,EAAAA,EAAAA,CAAAA;AACvE,QAAA,OAAOZ,GAAGiB,GAAG,CAACjB,GAAGkB,GAAG,CAACH,OAAO,CAAIF,CAAAA,EAAAA,SAAAA,CAAAA;AAClC;AACA;;;;;;MAOAM,qBAAAA,CACErF,eAAgC,EAChCiE,KAA4B,EAC5BqB,QAAqB,EACrBC,KAA4B,EAC5B;QACA,MAAMrB,EAAAA,GAAKD,MAAME,QAAQ;AACzB,QAAA,MAAMqB,OAAO,IAAI;QACjB,MAAMC,YAAAA,GAAe,IAAI,CAAC3G,aAAa;;;;;AAKvC,QAAA,MAAM4G,QAAWD,GAAAA,YAAAA,KAAiB,CAAK,IAAA,CAAC,CAACF,KAAAA;AACzC,QAAA,MAAMI,QAAW,GAAA,CAAC,oBAAoB,EAAEF,YAAa,CAAA,CAAC,EAAEC,QAAAA,GAAW,GAAM,GAAA,GAAA,CAAA,EAAMtF,MAAOJ,CAAAA,eAAAA,CAAAA,GAAmB,OAAO,EAAI,CAAA,CAAA;AACpH,QAAA,MAAM4F,SAASF,QAAW,GAAA;AAACxB,YAAAA,EAAAA,CAAG2B,IAAI,CAAC,UAAA,CAAA;AAAa3B,YAAAA,EAAAA,CAAG4B,KAAK,CAAC,OAAA;SAAS,GAAG;AAAC5B,YAAAA,EAAAA,CAAG2B,IAAI,CAAC,UAAA;AAAY,SAAA;QAC1F3B,EAAG6B,CAAAA,IAAI,CAACJ,QAAAA,EAAUC,MAAQ,EAAA,WAAA;AACxB,YAAA,IAAI,CAACI,EAAE,CAACnB,KAAK,GAAGW,IAAAA,CAAKS,WAAW,CAACjG,eAAiB,EAAA,IAAI,EAAE,IAAI,CAACsF,QAAQ,CAAA;AACrE,YAAA,IAAIG,iBAAiB,CAAG,EAAA;gBACtB,IAAI,CAACS,OAAO,CAAChC,EAAGiC,CAAAA,IAAI,CAAC,IAAI,CAACtB,KAAK,EAAE,CAAA,EAAG,CAAG,EAAA,CAAA,CAAA,CAAA;aAClC,MAAA;gBACL,IAAI,CAACmB,EAAE,CAAClB,EAAE,GAAGZ,GAAGkC,WAAW,CACzB,IAAI,CAACnI,4BAA6B,CAAA,EAClCiG,GAAGmC,KAAK,CAAC,IAAI,CAACC,SAAS,CAACC,SAAS,CAACC,EAAE,CACpC,EAAA,CAAA,CAAA,CACAhG,CAAC;gBACH,IAAI,CAACwF,EAAE,CAACjB,SAAS,GAAG0B,aAAaC,mBAAmB,CAAC,IAAI,CAAA,CAAElG,CAAC;;;gBAG5D,IAAI,CAACwF,EAAE,CAACW,CAAC,GAAGnB,IAAKZ,CAAAA,UAAU,CAAC,IAAI,EAAE,IAAI,CAACC,KAAK,EAAE,IAAI,CAACC,EAAE,EAAE,IAAI,CAACC,SAAS,EAAE3E,MAAOJ,CAAAA,eAAAA,CAAAA,CAAAA;;;;;;;;;;gBAU9E,IAAI,CAACgG,EAAE,CAACY,IAAI,GAAG1C,GAAG2B,IAAI,CAAC3B,EAAG2C,CAAAA,IAAI,CAAC,IAAI,CAACF,CAAC,EAAE,CAAI,GAAA,CAAA,CAAA,EAAIzC,EAAG2C,CAAAA,IAAI,CAAC,IAAI,CAACF,CAAC,EAAE,CAAA,GAAI,CAAI,CAAA,EAAA,CAAA,CAAA;;AAEvE,gBAAA,IAAI,CAACX,EAAE,CAACc,WAAW,GAAGpB,QAAAA,GAAW,IAAI,CAACH,KAAK,GAAGrB,EAAG4B,CAAAA,KAAK,CAAC,CAAA,CAAA;;;;;;;;;;;;;;;gBAevD,IAAI,CAACE,EAAE,CAACe,YAAY,GAAG7C,EAAG8C,CAAAA,GAAG,CAAC9C,EAAG+C,CAAAA,GAAG,CAAC/C,EAAGkB,CAAAA,GAAG,CAAClB,EAAGgB,CAAAA,GAAG,CAAC,CAAG,EAAA,IAAI,CAAC4B,WAAW,CAAG5I,EAAAA,qBAAAA,CAAAA,CAAAA,CAAAA;AACzE,gBAAA,IAAI,CAACgI,OAAO,CAAChC,GAAGiC,IAAI,CAACjC,GAAGgD,GAAG,CAAC,IAAI,CAACN,IAAI,EAAE,IAAI,CAACG,YAAY,CAAG,EAAA,IAAI,CAACjC,EAAE,CAAA,CAAA;AACpE;AACF,SAAA,CAAA;QACA,MAAMqC,MAAAA,GAASjD,GAAGkD,cAAc,EAAA;QAChC,OAAQ1B,QAAAA,GAAWyB,MAAM,CAACxB,QAAS,CAAA,CAACL,UAAUC,KAAU4B,CAAAA,GAAAA,MAAM,CAACxB,QAAAA,CAAS,CAACL,QAAAA,CAAAA;AAC3E;AACA;;;;AAIC,MACD,WACEtF,CAAAA,eAAgC,EAChCiE,KAA4B,EAC5BqB,QAAqB,EACR;QACb,MAAMpB,EAAAA,GAAKD,MAAME,QAAQ;QACzB,IAAInE,eAAAA,CAAgBqH,SAAS,KAAKC,gBAAkB,EAAA;YAClD,MAAMC,aAAAA,GAAgBrD,EAAGgD,CAAAA,GAAG,CAACT,YAAAA,CAAae,2BAA2B,CAACvD,KAAQC,CAAAA,EAAAA,EAAAA,CAAGiC,IAAI,CAACb,QAAU,EAAA,CAAA,CAAA,CAAA;AAChG,YAAA,OAAOpB,GAAGuD,KAAK,CACbvD,GAAGiB,GAAG,CAACjB,GAAGwD,MAAM,CAACH,aAAcI,CAAAA,GAAG,GAAGlB,YAAamB,CAAAA,iCAAiC,CAAC3D,KAAO4D,CAAAA,CAAAA,CAAC,GAC5F,CACA,EAAA,CAAA,CAAA;AAEJ;AACA,QAAA,OAAO3D,GAAG4D,iBAAiB,GAAG5D,GAAGuD,KAAK,CAACxD,MAAM8D,OAAO,CAACC,aAAa,EAAE,GAAG,CAAK/D,CAAAA,GAAAA,KAAAA,CAAMqC,SAAS,CAACC,SAAS,CAAC0B,CAAC;AACzG;AACAC,IAAAA,aAAAA,CACElI,eAAgC,EAChCiE,KAA4B,EAC5BkE,YAAyB,EACzBC,KAAkB,EAClB;QACA,MAAMlE,EAAAA,GAAKD,MAAME,QAAQ;AACzB,QAAA,MAAMqB,OAAO,IAAI;AACjB,QAAA,IAAIpF,OAAOJ,eAAkB,CAAA,EAAA;;;;YAI3BkE,EAAG6B,CAAAA,IAAI,CAAC,0BAA4B,EAAA;AAAC7B,gBAAAA,EAAAA,CAAGiC,IAAI,CAAC,cAAA,CAAA;AAAiBjC,gBAAAA,EAAAA,CAAG4B,KAAK,CAAC,OAAA;aAAS,EAAE,WAAA;gBAChF,IAAI,CAACE,EAAE,CAACqC,QAAQ,GAAG5B,YAAamB,CAAAA,iCAAiC,CAAC,IAAI,CAAA;AACtE,gBAAA,IAAI,CAAC5B,EAAE,CAACsC,GAAG,GAAGpE,EAAAA,CAAGgB,GAAG,CAAC,IAAI,CAACiD,YAAY,CAACR,GAAG,EAAE,IAAI,CAACU,QAAQ,CAACV,GAAG,CAAA;AAC7D,gBAAA,IAAI,CAAC3B,EAAE,CAACnB,KAAK,GAAGX,EAAAA,CAAGiB,GAAG,CAACjB,EAAAA,CAAGwD,MAAM,CAAC,IAAI,CAACY,GAAG,CAAA,EAAG,IAAI,CAACD,QAAQ,CAACR,CAAC,CAAA;AAC3D,gBAAA,IAAI,CAAC7B,EAAE,CAACuC,MAAM,GAAGrE,EAAAA,CAAG4B,KAAK,CAAC,CAAA,CAAA;gBAC1B,IAAI,CAAC0C,GAAG,CAACtE,EAAGuE,CAAAA,aAAa,CAAC,IAAI,CAAC5D,KAAK,EAAE,CAAI,CAAA,EAAA,WAAA;;oBAExC,IAAIW,IAAAA,CAAK9G,WAAW,GAAG,CAAG,EAAA;AACxB,wBAAA,IAAI,CAACsH,EAAE,CAAC0C,IAAI,GAAGC,iBAAAA,CAAkB3I,gBAAgBqH,SAAS,EAAE,IAAI,EAAE,IAAI,CAACxC,KAAK,EAAE,IAAI,CAACuD,KAAK,EAAE,IAAA,CAAA;AAC1F,wBAAA,IAAI,CAACvD,KAAK,GAAG+D,oBAAAA,CAAqB,IAAI,EAAE,IAAI,CAAC/D,KAAK,EAAE,IAAI,CAAC6D,IAAI,EAAE,KAAA,CAAA;AACjE;AACA,oBAAA,IAAI,CAACH,MAAM,GAAG/C,IAAAA,CAAKqD,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAACP,GAAG,EAAE,IAAI,CAACzD,KAAK,CAAA;AACjE,iBAAA,CAAA;AACA,gBAAA,IAAI,CAACqB,OAAO,CAAC,IAAI,CAACqC,MAAM,CAAA;AAC1B,aAAA,CAAA;AACA,YAAA,OAAOrE,EAAGkD,CAAAA,cAAc,EAAG0B,CAAAA,wBAAwB,CAACX,YAAcC,EAAAA,KAAAA,CAAAA;AACpE;AACA,QAAA,MAAMzC,QAAW,GAAA,sBAAA;QACjBzB,EAAG6B,CAAAA,IAAI,CAACJ,QAAU,EAAA;AAACzB,YAAAA,EAAAA,CAAGiC,IAAI,CAAC,cAAA,CAAA;AAAiBjC,YAAAA,EAAAA,CAAG4B,KAAK,CAAC,OAAA;SAAS,EAAE,WAAA;AAC9D,YAAA,IAAI,CAACE,EAAE,CAAC+C,WAAW,GAAG7E,EAAAA,CAAGiB,GAAG,CAAC,IAAI,CAACgD,YAAY,CAACR,GAAG,EAAE,IAAI,CAACQ,YAAY,CAACN,CAAC,CAAA;AACvE,YAAA,IAAI,CAAC7B,EAAE,CAAC+C,WAAW,GAAGC,iBAAAA,CAAkB,IAAI,EAAE,IAAI,CAACD,WAAW,CAACpB,GAAG,CAAA;AAClE,YAAA,IAAI,CAAC3B,EAAE,CAACiD,OAAO,GAAG/E,EAAAA,CAAGgF,GAAG,CACtBhF,EAAGiF,CAAAA,KAAK,CACNjF,EAAAA,CAAGgF,GAAG,CACJhF,EAAAA,CAAGkF,KAAK,CACNlF,EAAGmF,CAAAA,gBAAgB,CAAC,IAAI,CAACN,WAAW,CAACvI,CAAC,EAAE,CAAA,CAAA,EACxC0D,EAAGuE,CAAAA,aAAa,CAAC,IAAI,CAACM,WAAW,CAACvI,CAAC,EAAE,CACrC0D,CAAAA,EAAAA,EAAAA,CAAGmF,gBAAgB,CAAC,IAAI,CAACN,WAAW,CAACxI,CAAC,EAAE,IACxC2D,EAAGuE,CAAAA,aAAa,CAAC,IAAI,CAACM,WAAW,CAACxI,CAAC,EAAE,CAAA,CAAA,CAAA,CAAA,EAGzC+I,uBAAwB,CAAA,IAAI,EAAE,IAAI,CAACP,WAAW,CAACd,CAAC,CAAA,CAAA,CAAA;AAGpD,YAAA,IAAI,CAACjC,EAAE,CAACuC,MAAM,GAAGrE,EAAAA,CAAG4B,KAAK,CAAC,CAAA,CAAA;AAC1B,YAAA,IAAI,CAAC0C,GAAG,CAAC,IAAI,CAACS,OAAO,EAAE,WAAA;;;;;;;;gBAQrB,IAAIzD,IAAAA,CAAK9G,WAAW,GAAG,CAAG,EAAA;oBACxB,IAAI,CAACsH,EAAE,CAAC0C,IAAI,GAAGC,iBACb3I,CAAAA,eAAAA,CAAgBqH,SAAS,EACzB,IAAI,EACJ,IAAI,CAAC0B,WAAW,CAACd,CAAC,EAClB,IAAI,CAACG,KAAK,EACV,KAAA,CAAA;AAEF,oBAAA,IAAI,CAACW,WAAW,CAACd,CAAC,GAAGW,qBAAqB,IAAI,EAAE,IAAI,CAACG,WAAW,CAACd,CAAC,EAAE,IAAI,CAACS,IAAI,EAAE,IAAA,CAAA;AACjF;gBACA,IAAI,CAACH,MAAM,GAAG/C,IAAK+D,CAAAA,aAAa,CAAC,IAAI,EAAE,IAAI,CAACR,WAAW,CAAA;AACzD,aAAA,CAAA;AACA,YAAA,IAAI,CAAC7C,OAAO,CAAC,IAAI,CAACqC,MAAM,CAAA;AAC1B,SAAA,CAAA;AACA,QAAA,OAAOrE,GAAGkD,cAAc,EAAE,CAACzB,QAAAA,CAAS,CAACwC,YAAcC,EAAAA,KAAAA,CAAAA;AACrD;IACAoB,gBACExJ,CAAAA,eAAgC,EAChCiE,KAA4B,EAC5BkE,YAAyB,EACzBC,KAAkB,EAClBqB,MAAmB,EACnB;;;;AAIA,QAAA,OAAO,IAAI,CAACvB,aAAa,CAAClI,eAAAA,EAAiBiE,OAAOkE,YAAcC,EAAAA,KAAAA,CAAAA;AAClE;AACA;;;;;;;;;;;;;;AAcC,MACD,aAAQmB,CAActF,KAA4B,EAAE8E,WAAwB,EAAe;QACzF,MAAM7E,EAAAA,GAAKD,MAAME,QAAQ;AACzB,QAAA,MAAMqB,OAAO,IAAI;QACjB,MAAMkE,IAAAA,GAAO,IAAI,CAAChL,WAAW;AAC7B,QAAA,MAAMiH,QAAW,GAAA,CAAC,qBAAqB,EAAE+D,IAAM,CAAA,CAAA;QAC/CxF,EAAG6B,CAAAA,IAAI,CAACJ,QAAU,EAAA;AAACzB,YAAAA,EAAAA,CAAG2B,IAAI,CAAC,aAAA;SAAe,EAAE,WAAA;AAC1C,YAAA,IAAI6D,QAAQ,CAAG,EAAA;AACb,gBAAA,IAAI,CAACxD,OAAO,CAACV,KAAKmE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAACZ,WAAW,CAACvC,EAAE,EAAE,IAAI,CAACuC,WAAW,CAACd,CAAC,CAAA,CAAA;aAC3E,MAAA;;;AAGL,gBAAA,IAAI,CAACjC,EAAE,CAAC4D,SAAS,GAAG1F,EAAGiB,CAAAA,GAAG,CAAC,CAAA,EAAGsB,YAAaoD,CAAAA,qBAAqB,CAAC,IAAI,EAAE5B,CAAC,CAAA;AACxE,gBAAA,IAAI,CAACjC,EAAE,CAAC8D,GAAG,GAAG5F,EAAAA,CAAG4B,KAAK,CAAC,CAAA,CAAA;AACvB,gBAAA,IAAI,CAACE,EAAE,CAAC+D,KAAK,GAAG7F,GAAG8F,IAAI,EAAA;AACvB,gBAAA,MAAMC,MAAS,GAACP,CAAAA,IAAAA,GAAO,CAAA,IAAK,CAAA;AAC5B,gBAAA,IAAK,IAAInJ,CAAI,GAAA,CAAC0J,MAAQ1J,EAAAA,CAAAA,IAAK0J,QAAQ1J,CAAK,EAAA,CAAA;AACtC,oBAAA,IAAK,IAAIC,CAAI,GAAA,CAACyJ,MAAQzJ,EAAAA,CAAAA,IAAKyJ,QAAQzJ,CAAK,EAAA,CAAA;wBACtC,IAAI,CAACuJ,KAAK,GAAG7F,EAAAA,CAAGgG,GAAG,CAAC,IAAI,CAACnB,WAAW,CAACvC,EAAE,EAAEtC,EAAGgD,CAAAA,GAAG,CAAChD,EAAG8F,CAAAA,IAAI,CAACxJ,CAAGD,EAAAA,CAAAA,CAAAA,EAAI,IAAI,CAACqJ,SAAS,CAAA,CAAA;wBAC7E,IAAI,CAACE,GAAG,GAAG5F,EAAAA,CAAGgG,GAAG,CAAC,IAAI,CAACJ,GAAG,EAAEtE,IAAAA,CAAKmE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAACI,KAAK,EAAE,IAAI,CAAChB,WAAW,CAACd,CAAC,CAAA,CAAA;AACxF;AACF;gBACA,IAAI,CAAC/B,OAAO,CAAChC,EAAGiB,CAAAA,GAAG,CAAC,IAAI,CAAC2E,GAAG,EAAEJ,IAAOA,GAAAA,IAAAA,CAAAA,CAAAA;AACvC;AACF,SAAA,CAAA;AACA,QAAA,OAAOxF,EAAGkD,CAAAA,cAAc,EAAE,CAACzB,SAAS,CAACoD,WAAAA,CAAAA;AACvC;AACA;;;;;;;;;AASC,MACD,iBAA0B9E,CAAAA,KAA4B,EAAEqE,GAAgB,EAAE6B,aAA0B,EAAE;QACpG,MAAMjG,EAAAA,GAAKD,MAAME,QAAQ;AACzB,QAAA,MAAMqB,OAAO,IAAI;QACjB,MAAMkE,IAAAA,GAAO,IAAI,CAAChL,WAAW;AAC7B,QAAA,MAAMiH,QAAW,GAAA,CAAC,yBAAyB,EAAE+D,IAAM,CAAA,CAAA;QACnDxF,EAAG6B,CAAAA,IAAI,CAACJ,QAAU,EAAA;AAACzB,YAAAA,EAAAA,CAAG2B,IAAI,CAAC,KAAA,CAAA;AAAQ3B,YAAAA,EAAAA,CAAG4B,KAAK,CAAC,eAAA;SAAiB,EAAE,WAAA;AAC7D,YAAA,IAAI4D,QAAQ,CAAG,EAAA;AACb,gBAAA,IAAI,CAACxD,OAAO,CAACV,IAAAA,CAAK4E,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC9B,GAAG,EAAE,IAAI,CAAC6B,aAAa,EAAE,IAAA,CAAA,CAAA;aACpE,MAAA;gBACL,IAAI,CAACnE,EAAE,CAACqE,OAAO,GAAGnG,GAAGoG,SAAS,CAAC,IAAI,CAAChC,GAAG,CAAA;AACvC,gBAAA,IAAI,CAACtC,EAAE,CAACuE,MAAM,GAAGrG,EAAAA,CAAGiB,GAAG,CACrB,IAAI,CAACkF,OAAO,EACZnG,GAAGkB,GAAG,CAAClB,GAAGkB,GAAG,CAAClB,GAAGsG,GAAG,CAAC,IAAI,CAACH,OAAO,CAAC7J,CAAC,CAAA,EAAG0D,GAAGsG,GAAG,CAAC,IAAI,CAACH,OAAO,CAAC9J,CAAC,CAAA,CAAA,EAAI2D,GAAGsG,GAAG,CAAC,IAAI,CAACH,OAAO,CAACpC,CAAC,CAAA,CAAA,CAAA;AAEtF,gBAAA,IAAI,CAACjC,EAAE,CAACyE,MAAM,GAAG,IAAI,CAACC,OAAO,CAC3BxG,EAAGyG,CAAAA,QAAQ,CAACzG,EAAAA,CAAGsG,GAAG,CAAC,IAAI,CAACH,OAAO,CAAC9J,CAAC,CAAG,EAAA,IAAA,CAAA,EACpC2D,GAAG2B,IAAI,CAAC,CAAG,EAAA,CAAA,EAAG,CACd3B,CAAAA,EAAAA,EAAAA,CAAG2B,IAAI,CAAC,GAAG,CAAG,EAAA,CAAA,CAAA,CAAA;AAEhB,gBAAA,IAAI,CAACG,EAAE,CAAC4E,IAAI,GAAG1G,GAAGoG,SAAS,CAACpG,EAAG2G,CAAAA,KAAK,CAAC,IAAI,CAACJ,MAAM,EAAE,IAAI,CAACJ,OAAO,CAAA,CAAA;AAC9D,gBAAA,IAAI,CAACrE,EAAE,CAAC8E,EAAE,GAAG5G,EAAG2G,CAAAA,KAAK,CAAC,IAAI,CAACR,OAAO,EAAE,IAAI,CAACO,IAAI,CAAA;AAC7C,gBAAA,IAAI,CAAC5E,EAAE,CAAC4D,SAAS,GAAG1F,EAAGiB,CAAAA,GAAG,CAAC,CAAA,EAAGsB,YAAaoD,CAAAA,qBAAqB,CAAC,IAAI,EAAE5B,CAAC,CAAA;AACxE,gBAAA,IAAI,CAACjC,EAAE,CAAC8D,GAAG,GAAG5F,EAAAA,CAAG4B,KAAK,CAAC,CAAA,CAAA;AACvB,gBAAA,IAAI,CAACE,EAAE,CAAC+E,MAAM,GAAG7G,GAAG2B,IAAI,EAAA;AACxB,gBAAA,MAAMoE,MAAS,GAACP,CAAAA,IAAAA,GAAO,CAAA,IAAK,CAAA;AAC5B,gBAAA,IAAK,IAAInJ,CAAI,GAAA,CAAC0J,MAAQ1J,EAAAA,CAAAA,IAAK0J,QAAQ1J,CAAK,EAAA,CAAA;AACtC,oBAAA,IAAK,IAAIC,CAAI,GAAA,CAACyJ,MAAQzJ,EAAAA,CAAAA,IAAKyJ,QAAQzJ,CAAK,EAAA,CAAA;AACtC,wBAAA,IAAI,CAACuK,MAAM,GAAG7G,EAAAA,CAAGgG,GAAG,CAClB,IAAI,CAACK,MAAM,EACXrG,EAAGgD,CAAAA,GAAG,CAAChD,EAAAA,CAAGgG,GAAG,CAAChG,EAAAA,CAAGgD,GAAG,CAAC,IAAI,CAAC0D,IAAI,EAAEpK,IAAI0D,EAAGgD,CAAAA,GAAG,CAAC,IAAI,CAAC4D,EAAE,EAAEvK,CAAK,CAAA,CAAA,EAAA,IAAI,CAACqJ,SAAS,CAAA,CAAA;wBAEzE,IAAI,CAACE,GAAG,GAAG5F,EAAAA,CAAGgG,GAAG,CAAC,IAAI,CAACJ,GAAG,EAAEtE,IAAAA,CAAK4E,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAACW,MAAM,EAAE,IAAI,CAACZ,aAAa,EAAE,IAAA,CAAA,CAAA;AAC7F;AACF;gBACA,IAAI,CAACjE,OAAO,CAAChC,EAAGiB,CAAAA,GAAG,CAAC,IAAI,CAAC2E,GAAG,EAAEJ,IAAOA,GAAAA,IAAAA,CAAAA,CAAAA;AACvC;AACF,SAAA,CAAA;AACA,QAAA,OAAOxF,GAAGkD,cAAc,EAAE,CAACzB,QAAAA,CAAS,CAAC2C,GAAK6B,EAAAA,aAAAA,CAAAA;AAC5C;AACA;;;AAGC,MACD,gBACElG,CAAAA,KAA4B,EAC5B+G,EAAe,EACfb,aAA0B,EACb;AACb,QAAA,OAAO,IAAI,CAACC,kBAAkB,CAACnG,KAAAA,EAAO+G,IAAIb,aAAe,EAAA,KAAA,CAAA;AAC3D;AACA;;;;MAKQC,mBACNnG,KAA4B,EAC5BgH,KAAkB,EAClBd,aAA0B,EAC1BnF,MAAe,EACF;QACb,MAAMd,EAAAA,GAAKD,MAAME,QAAQ;AACzB,QAAA,MAAMqB,OAAO,IAAI;QACjB,MAAMG,QAAAA,GAAWX,SAAS,gBAAmB,GAAA,YAAA;QAC7Cd,EAAG6B,CAAAA,IAAI,CAACJ,QAAU,EAAA;AAACX,YAAAA,MAAAA,GAASd,GAAG2B,IAAI,CAAC,OAAW3B,CAAAA,GAAAA,EAAAA,CAAG8F,IAAI,CAAC,OAAA,CAAA;AAAU9F,YAAAA,EAAAA,CAAG4B,KAAK,CAAC,eAAA;SAAiB,EAAE,WAAA;AAC3F,YAAA,IAAI,CAACE,EAAE,CAACkF,KAAK,GAAGhH,GAAGiH,kBAAkB,CAAC1E,YAAapE,CAAAA,YAAY,CAAC,IAAI,CAAA,EAAG,IAAI,CAAC4I,KAAK,EAAE,CAAA,CAAA;YACnF,IAAI,CAACjF,EAAE,CAACoF,MAAM,GAAG,IAAI,CAACF,KAAK,CAACG,GAAG;YAC/B,IAAI,CAACrF,EAAE,CAAClB,EAAE,GAAG,IAAI,CAACoG,KAAK,CAACI,CAAC;YACzB,IAAI,CAACtF,EAAE,CAACjB,SAAS,GAAG0B,aAAaC,mBAAmB,CAAC,IAAI,CAAA,CAAElG,CAAC;YAC5D,IAAI,CAACwF,EAAE,CAAC1H,OAAO,GAAGmI,aAAaC,mBAAmB,CAAC,IAAI,CAAA,CAAEnG,CAAC;YAC1D,IAAI,CAACyF,EAAE,CAACW,CAAC,GAAGnB,IAAKZ,CAAAA,UAAU,CAAC,IAAI,EAAE,IAAI,CAACuF,aAAa,EAAE,IAAI,CAACrF,EAAE,EAAE,IAAI,CAACC,SAAS,EAAEC,MAAAA,CAAAA;;;;AAI/E,YAAA,IAAI,CAACgB,EAAE,CAACuF,MAAM,GAAGrH,GAAGuD,KAAK,CAACvD,EAAGgD,CAAAA,GAAG,CAAC,IAAI,CAACP,CAAC,EAAE3I,kBAAkB,CAAGA,EAAAA,eAAAA,CAAAA;YAC9D,IAAI,CAACgI,EAAE,CAACwF,KAAK,GAAGtH,GAAGuH,KAAK,CAAC,IAAI,CAACF,MAAM,CAAA;AACpC,YAAA,IAAI,CAACvF,EAAE,CAAC0F,IAAI,GAAGxH,EAAGgB,CAAAA,GAAG,CAAC,IAAI,CAACqG,MAAM,EAAE,IAAI,CAACC,KAAK,CAAA;;;AAG7C,YAAA,IAAI,CAACxF,EAAE,CAAC2F,IAAI,GAAGzH,EAAAA,CAAG4B,KAAK,CAAC,CAAA,CAAA;YACxB,IAAI,CAACE,EAAE,CAAC4F,GAAG,GAAG,IAAI,CAACR,MAAM,CAAC5K,CAAC;YAC3B,IAAI,CAACgI,GAAG,CAACtE,EAAGmF,CAAAA,gBAAgB,CAAC,IAAI,CAACmC,KAAK,EAAE,CAAI,CAAA,EAAA,WAAA;AAC3C,gBAAA,IAAI,CAACG,IAAI,GAAG,IAAI,CAACP,MAAM,CAAC7K,CAAC;AACzB,gBAAA,IAAI,CAACqL,GAAG,GAAG,IAAI,CAACR,MAAM,CAACnD,CAAC;aACvB4D,CAAAA,CAAAA,OAAO,CAAC3H,EAAGmF,CAAAA,gBAAgB,CAAC,IAAI,CAACmC,KAAK,EAAE,CAAI,CAAA,EAAA,WAAA;AAC7C,gBAAA,IAAI,CAACG,IAAI,GAAG,IAAI,CAACP,MAAM,CAAC5K,CAAC;AACzB,gBAAA,IAAI,CAACoL,GAAG,GAAG,IAAI,CAACR,MAAM,CAAC7K,CAAC;AAC1B,aAAA,CAAA;;;;AAIA,YAAA,IAAI,CAACyF,EAAE,CAAC8F,UAAU,GAAG5H,EAAAA,CAAG6H,GAAG,CAAC,IAAI,CAACJ,IAAI,EAAE,IAAI,CAACC,GAAG,EAAE,IAAI,CAACF,IAAI,CAAA;;;;;AAK1D,YAAA,IAAI,CAACxF,OAAO,CAAChC,GAAG8H,GAAG,CAAC9H,GAAG8C,GAAG,CAAC9C,EAAGgD,CAAAA,GAAG,CAAC,IAAI,CAAC4E,UAAU,EAAE,IAAI,CAACxN,OAAO,CAAA,CAAA,CAAA,CAAA;AACjE,SAAA,CAAA;AACA,QAAA,OAAO4F,GAAGkD,cAAc,EAAE,CAACzB,QAAAA,CAAS,CAACsF,KAAOd,EAAAA,aAAAA,CAAAA;AAC9C;AACF;AAEA,qFACA,SAAS/J,MAAAA,CAAOJ,eAAgC,EAAA;IAC9C,OAAOA,eAAAA,CAAgBqH,SAAS,KAAKC,gBAAAA;AACvC;;;;"}
|
package/dist/shadow/esm.js
CHANGED
|
@@ -204,7 +204,7 @@ class BlurBlitter extends GaussianBlurBlitter {
|
|
|
204
204
|
}
|
|
205
205
|
/** @internal */ fetchTemporalFramebuffer(autoRelease, lightType, numCascades, width, height, colorFormat, depthFormat, mipmapping) {
|
|
206
206
|
const device = getDevice();
|
|
207
|
-
const useTextureArray = numCascades > 1
|
|
207
|
+
const useTextureArray = numCascades > 1;
|
|
208
208
|
const colorAttachments = colorFormat ? useTextureArray ? [
|
|
209
209
|
device.pool.fetchTemporalTexture2DArray(false, colorFormat, width, height, numCascades, mipmapping)
|
|
210
210
|
] : lightType === LIGHT_TYPE_POINT ? [
|
|
@@ -212,7 +212,7 @@ class BlurBlitter extends GaussianBlurBlitter {
|
|
|
212
212
|
] : [
|
|
213
213
|
device.pool.fetchTemporalTexture2D(false, colorFormat, width, height, mipmapping)
|
|
214
214
|
] : null;
|
|
215
|
-
const depthAttachment = depthFormat ? useTextureArray ? device.pool.fetchTemporalTexture2DArray(false, depthFormat, width, height, numCascades, false) :
|
|
215
|
+
const depthAttachment = depthFormat ? useTextureArray ? device.pool.fetchTemporalTexture2DArray(false, depthFormat, width, height, numCascades, false) : lightType === LIGHT_TYPE_POINT ? device.pool.fetchTemporalTextureCube(false, depthFormat, width, false) : device.pool.fetchTemporalTexture2D(false, depthFormat, width, height, false) : null;
|
|
216
216
|
const fb = device.pool.createTemporalFramebuffer(autoRelease, colorAttachments, depthAttachment);
|
|
217
217
|
if (colorAttachments) {
|
|
218
218
|
device.pool.releaseTexture(colorAttachments[0]);
|
|
@@ -276,7 +276,7 @@ class BlurBlitter extends GaussianBlurBlitter {
|
|
|
276
276
|
}
|
|
277
277
|
getShadowMapColorFormat(_shadowMapParams) {
|
|
278
278
|
const device = getDevice();
|
|
279
|
-
return device.getDeviceCaps().textureCaps.supportFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearFloatTexture ?
|
|
279
|
+
return device.getDeviceCaps().textureCaps.supportFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearFloatTexture ? 'rg32f' : device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? 'rg16f' : 'rgba8unorm';
|
|
280
280
|
}
|
|
281
281
|
getShadowMapDepthFormat(_shadowMapParams) {
|
|
282
282
|
return 'd24s8';
|