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