@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
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { applyMixins, DRef, randomUUID, Vector3, Vector4 } from '@zephyr3d/base';
|
|
1
|
+
import { applyMixins, DRef, randomUUID, Vector3, half2float, Vector4, nextPowerOf2 } from '@zephyr3d/base';
|
|
2
2
|
import { GraphNode } from '../graph_node.js';
|
|
3
3
|
import { mixinDrawable } from '../../render/drawable_mixin.js';
|
|
4
|
-
import { MAX_TERRAIN_MIPMAP_LEVELS, QUEUE_OPAQUE,
|
|
5
|
-
import '../../render/render_queue.js';
|
|
4
|
+
import { MAX_TERRAIN_MIPMAP_LEVELS, QUEUE_OPAQUE, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_OBJECT_COLOR } from '../../values.js';
|
|
6
5
|
import { getDevice } from '../../app/api.js';
|
|
6
|
+
import { warnUnsupported } from '../../utility/unsupported.js';
|
|
7
|
+
import '../../render/render_queue.js';
|
|
7
8
|
import '../../render/primitive.js';
|
|
8
9
|
import '@zephyr3d/device';
|
|
9
10
|
import { CopyBlitter } from '../../blitter/copy.js';
|
|
@@ -11,11 +12,12 @@ import '../../material/shader/helper.js';
|
|
|
11
12
|
import '../../material/lambert.js';
|
|
12
13
|
import '../../material/blinn.js';
|
|
13
14
|
import '../../material/unlit.js';
|
|
15
|
+
import '../../material/meshmaterial.js';
|
|
14
16
|
import '../../material/particle.js';
|
|
15
17
|
import '../../material/subsurfaceprofile.js';
|
|
16
|
-
import '../../material/
|
|
18
|
+
import '../../material/sssprofile.js';
|
|
19
|
+
import '../../material/sss.js';
|
|
17
20
|
import '../../material/eye.js';
|
|
18
|
-
import '../../material/meshmaterial.js';
|
|
19
21
|
import '../../material/hair.js';
|
|
20
22
|
import '../../material/hairstrand.js';
|
|
21
23
|
import '../../material/grassmaterial.js';
|
|
@@ -33,18 +35,49 @@ import '../../render/lightpass.js';
|
|
|
33
35
|
import '../../render/sky.js';
|
|
34
36
|
import { Clipmap } from '../../render/clipmap.js';
|
|
35
37
|
import '../../render/envlight.js';
|
|
38
|
+
import '../../render/lod.js';
|
|
36
39
|
import '../../render/dualdepthpeeling_oit.js';
|
|
37
40
|
import '../../shaders/atmosphere.js';
|
|
41
|
+
import '../../render/water_interaction.js';
|
|
38
42
|
import '../../render/rendergraph/scene_render_context.js';
|
|
43
|
+
import '../../render/sdf/scene_sdf.js';
|
|
44
|
+
import '../../render/sdf/global_sdf.js';
|
|
45
|
+
import '../../render/gi/voxelize_pass.js';
|
|
39
46
|
import { BoundingBox } from '../../utility/bounding_volume.js';
|
|
40
47
|
import { RenderMipmap } from '../../utility/rendermipmap.js';
|
|
41
48
|
import { GrassRenderer } from './grass.js';
|
|
49
|
+
import { TerrainVirtualTexture } from './terrain_rvt.js';
|
|
50
|
+
import { TerrainGIAlbedo } from './terrain_gi_albedo.js';
|
|
42
51
|
|
|
43
52
|
class HeightMinMaxBlitter extends CopyBlitter {
|
|
44
53
|
filter(scope, type, srcTex, srcUV, srcLayer, sampleType) {
|
|
45
54
|
return this.readTexel(scope, type, srcTex, srcUV, srcLayer, sampleType).xxxx;
|
|
46
55
|
}
|
|
47
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Copies the height map into the top-left of a power-of-two target, repeating the last row and
|
|
59
|
+
* column into the padding. The min/max reduction halves each level with a 2x2 footprint, which
|
|
60
|
+
* drops the last row or column of an odd sized level; padding with edge copies avoids that
|
|
61
|
+
* without affecting either extreme.
|
|
62
|
+
*/ class HeightPadBlitter extends CopyBlitter {
|
|
63
|
+
/** (dest width, dest height, source width, source height) */ sizes = new Vector4();
|
|
64
|
+
setup(scope, _type) {
|
|
65
|
+
const pb = scope.$builder;
|
|
66
|
+
if (pb.shaderKind === 'fragment') {
|
|
67
|
+
scope.padSizes = pb.vec4().uniform(0);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
setUniforms(bindGroup, _sourceTex) {
|
|
71
|
+
bindGroup.setValue('padSizes', this.sizes);
|
|
72
|
+
}
|
|
73
|
+
filter(scope, type, srcTex, srcUV, srcLayer, sampleType) {
|
|
74
|
+
const pb = scope.$builder;
|
|
75
|
+
const sizes = scope.padSizes;
|
|
76
|
+
const texel = pb.min(pb.floor(pb.mul(srcUV, sizes.xy)), pb.sub(sizes.zw, pb.vec2(1)));
|
|
77
|
+
const uv = pb.div(pb.add(texel, pb.vec2(0.5)), sizes.zw);
|
|
78
|
+
return this.readTexel(scope, type, srcTex, uv, srcLayer, sampleType).xxxx;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
48
81
|
class HeightBoundingGenerator extends RenderMipmap {
|
|
49
82
|
renderPixel(scope, leftTop, rightTop, leftBottom, rightBottom) {
|
|
50
83
|
const pb = scope.$builder;
|
|
@@ -70,11 +103,22 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
70
103
|
*/ class ClipmapTerrain extends applyMixins(GraphNode, mixinDrawable) {
|
|
71
104
|
static _heightBoundingGenerator = new HeightBoundingGenerator();
|
|
72
105
|
static _copyBlitter = new HeightMinMaxBlitter();
|
|
106
|
+
static _padBlitter = new HeightPadBlitter();
|
|
73
107
|
static _tmpBuffer = new Float32Array(MAX_TERRAIN_MIPMAP_LEVELS * 2 * 4);
|
|
74
108
|
_pickTarget;
|
|
75
109
|
_clipmap;
|
|
110
|
+
_shadowClipmap;
|
|
76
111
|
_renderData;
|
|
112
|
+
_shadowRenderData;
|
|
113
|
+
_shadowGatherContext;
|
|
77
114
|
_gridScale;
|
|
115
|
+
/**
|
|
116
|
+
* World position of clipmap grid point (0, 0): the centre of the first height map texel.
|
|
117
|
+
* Texel i holds the height at the centre of cell i (the convention the height sampling,
|
|
118
|
+
* brushes and grass placement all share), so this is what puts the finest level's vertices
|
|
119
|
+
* on the samples instead of halfway between them.
|
|
120
|
+
*/ _gridOriginX;
|
|
121
|
+
_gridOriginZ;
|
|
78
122
|
_material;
|
|
79
123
|
_grassRenderer;
|
|
80
124
|
_castShadow;
|
|
@@ -85,7 +129,13 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
85
129
|
_grassAssetId;
|
|
86
130
|
_minHeight;
|
|
87
131
|
_maxHeight;
|
|
132
|
+
/** Bumped by every height range update, so a read back overtaken by a newer one is dropped */ _heightRangeSerial;
|
|
133
|
+
_heightData;
|
|
134
|
+
_heightReadBack;
|
|
135
|
+
_heightVersion;
|
|
88
136
|
_tmpTexture;
|
|
137
|
+
_virtualTexture;
|
|
138
|
+
_giAlbedo;
|
|
89
139
|
/**
|
|
90
140
|
* Creates a new clipmap terrain instance.
|
|
91
141
|
*
|
|
@@ -103,9 +153,16 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
103
153
|
this._clipmap = new Clipmap(clipMapTileSize, [
|
|
104
154
|
'tex1_f32'
|
|
105
155
|
], MAX_TERRAIN_MIPMAP_LEVELS);
|
|
156
|
+
this._shadowClipmap = new Clipmap(clipMapTileSize, [
|
|
157
|
+
'tex1_f32'
|
|
158
|
+
], MAX_TERRAIN_MIPMAP_LEVELS);
|
|
106
159
|
this._renderData = null;
|
|
160
|
+
this._shadowRenderData = null;
|
|
161
|
+
this._shadowGatherContext = null;
|
|
107
162
|
this._grassRenderer = new DRef(new GrassRenderer(this));
|
|
108
163
|
this._gridScale = 1;
|
|
164
|
+
this._gridOriginX = 0;
|
|
165
|
+
this._gridOriginZ = 0;
|
|
109
166
|
this._castShadow = true;
|
|
110
167
|
this._sizeX = sizeX;
|
|
111
168
|
this._sizeZ = sizeZ;
|
|
@@ -114,9 +171,16 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
114
171
|
this._splatMapAssetId = `assets/.embedded.dir/${this.persistentId}-splatmap.bin`;
|
|
115
172
|
this._minHeight = 0;
|
|
116
173
|
this._maxHeight = 0;
|
|
174
|
+
this._heightRangeSerial = 0;
|
|
175
|
+
this._heightData = null;
|
|
176
|
+
this._heightReadBack = null;
|
|
177
|
+
this._heightVersion = 0;
|
|
117
178
|
this._material = new DRef(new ClipmapTerrainMaterial(this.createHeightMapTexture(this._sizeX, this._sizeZ)));
|
|
118
179
|
this._tmpTexture = new DRef();
|
|
180
|
+
this._virtualTexture = null;
|
|
181
|
+
this._giAlbedo = null;
|
|
119
182
|
this.updateRegion();
|
|
183
|
+
this.updateHeightPyramid();
|
|
120
184
|
scene.queuePerCameraUpdateNode(this);
|
|
121
185
|
}
|
|
122
186
|
/**
|
|
@@ -209,6 +273,83 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
209
273
|
this.resizeHeightMap(this._sizeX, this._sizeZ);
|
|
210
274
|
}
|
|
211
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Whether the detail layers are blended into a runtime virtual texture instead of per pixel.
|
|
278
|
+
* Pages are blended once, as the camera needs them, so shading costs the same whatever the
|
|
279
|
+
* number of layers. WebGPU only, ignored elsewhere; has no effect without detail layers.
|
|
280
|
+
*
|
|
281
|
+
* Code writing into the splat map or the height map directly must call
|
|
282
|
+
* {@link ClipmapTerrain.invalidateRuntimeVirtualTexture} for the area it changed.
|
|
283
|
+
*/ get runtimeVirtualTexture() {
|
|
284
|
+
return !!this._virtualTexture;
|
|
285
|
+
}
|
|
286
|
+
set runtimeVirtualTexture(val) {
|
|
287
|
+
if (!!val !== this.runtimeVirtualTexture) {
|
|
288
|
+
this.setRuntimeVirtualTexture(val ? {} : null);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Enables the runtime virtual texture with the given options, or disables it with null.
|
|
293
|
+
* See {@link ClipmapTerrain.runtimeVirtualTexture}.
|
|
294
|
+
*/ setRuntimeVirtualTexture(options) {
|
|
295
|
+
if (options && getDevice().type !== 'webgpu') {
|
|
296
|
+
warnUnsupported('Terrain runtime virtual texture (ClipmapTerrain.runtimeVirtualTexture)', 'WebGPU', 'the terrain is shaded directly every frame');
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (options && !this.scene) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (this._virtualTexture && options) {
|
|
303
|
+
this._virtualTexture.setOptions(options);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (this._virtualTexture) {
|
|
307
|
+
this.scene?.removeVirtualTextureClient(this._virtualTexture);
|
|
308
|
+
this._virtualTexture.dispose();
|
|
309
|
+
this._virtualTexture = null;
|
|
310
|
+
if (this.material) {
|
|
311
|
+
this.material.virtualTexture = null;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (options && this.material) {
|
|
315
|
+
this._virtualTexture = new TerrainVirtualTexture(this, options);
|
|
316
|
+
this.material.virtualTexture = this._virtualTexture.virtualTexture;
|
|
317
|
+
this.scene.addVirtualTextureClient(this._virtualTexture);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Refills the runtime virtual texture over a world XZ rectangle, or everywhere without
|
|
322
|
+
* arguments, and recaptures the albedo global illumination reads there. Needed after writing
|
|
323
|
+
* into the splat map or the height map directly (brushes); replacing textures or changing
|
|
324
|
+
* layer parameters through the material is picked up automatically.
|
|
325
|
+
*/ invalidateRuntimeVirtualTexture(x0, z0, x1, z1) {
|
|
326
|
+
this._giAlbedo?.invalidate(x0, z0, x1, z1);
|
|
327
|
+
if (!this._virtualTexture) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (x0 === undefined || z0 === undefined || x1 === undefined || z1 === undefined) {
|
|
331
|
+
this._virtualTexture.invalidate();
|
|
332
|
+
} else {
|
|
333
|
+
this._virtualTexture.invalidateWorldRegion(x0, z0, x1, z1);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Top-down capture of the material albedo read by global illumination, created on first use.
|
|
338
|
+
* WebGPU only.
|
|
339
|
+
* @internal
|
|
340
|
+
*/ get giAlbedo() {
|
|
341
|
+
if (!this._giAlbedo) {
|
|
342
|
+
this._giAlbedo = new TerrainGIAlbedo(this);
|
|
343
|
+
}
|
|
344
|
+
return this._giAlbedo;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The virtual texture behind {@link ClipmapTerrain.runtimeVirtualTexture}, null when disabled.
|
|
348
|
+
* For inspection: {@link VirtualTexture.stats}, {@link VirtualTexture.renderDebugTexture}.
|
|
349
|
+
* It is recreated when the terrain aspect or the options change.
|
|
350
|
+
*/ get runtimeVirtualTextureData() {
|
|
351
|
+
return this._virtualTexture?.virtualTexture ?? null;
|
|
352
|
+
}
|
|
212
353
|
/** Wether the mesh node casts shadows */ get castShadow() {
|
|
213
354
|
return this._castShadow;
|
|
214
355
|
}
|
|
@@ -239,8 +380,162 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
239
380
|
set heightMap(val) {
|
|
240
381
|
if (this.material && val) {
|
|
241
382
|
this.material.heightMap = val;
|
|
383
|
+
this._heightData = null;
|
|
242
384
|
this.updateRegion();
|
|
385
|
+
this.updateHeightPyramid();
|
|
386
|
+
this._heightVersion++;
|
|
387
|
+
this.readBackHeightData();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Goes up whenever the heights change: a new height map, or edits to the
|
|
392
|
+
* current one once {@link ClipmapTerrain.updateBoundingBox} is called after
|
|
393
|
+
* them. Lets CPU-side users such as physics notice they are out of date.
|
|
394
|
+
*/ get heightVersion() {
|
|
395
|
+
return this._heightVersion;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* CPU copy of the heights, half floats row by row (height map texel values, before the terrain
|
|
399
|
+
* scale and translation); null while unknown.
|
|
400
|
+
*
|
|
401
|
+
* @remarks
|
|
402
|
+
* Lets CPU-side users such as physics and prop placement read heights without a GPU read back.
|
|
403
|
+
* Known at once when loaded or set with {@link ClipmapTerrain.setHeights}; after other edits
|
|
404
|
+
* it is null until a read back started by {@link ClipmapTerrain.updateBoundingBox} lands, which
|
|
405
|
+
* {@link ClipmapTerrain.whenHeightDataReady} waits for.
|
|
406
|
+
*/ get heightData() {
|
|
407
|
+
return this._heightData;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Records the CPU copy of the heights just uploaded to the height map.
|
|
411
|
+
* @internal
|
|
412
|
+
*/ setHeightData(data, width, height) {
|
|
413
|
+
this._heightData = {
|
|
414
|
+
data,
|
|
415
|
+
width,
|
|
416
|
+
height
|
|
417
|
+
};
|
|
418
|
+
this._heightVersion++;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Resolves once {@link ClipmapTerrain.heightData} is known, reading the heights back from the
|
|
422
|
+
* GPU if needed. Resolves to null when the height map format cannot be read back.
|
|
423
|
+
*/ whenHeightDataReady() {
|
|
424
|
+
if (this._heightData) {
|
|
425
|
+
return Promise.resolve(this._heightData);
|
|
426
|
+
}
|
|
427
|
+
return this.readBackHeightData() ?? Promise.resolve(null);
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* World height of the terrain surface at a world position, bilinearly interpolated, or null
|
|
431
|
+
* outside the terrain or while {@link ClipmapTerrain.heightData} is unknown.
|
|
432
|
+
*/ getHeightAt(x, z) {
|
|
433
|
+
const data = this._heightData;
|
|
434
|
+
const region = this.worldRegion;
|
|
435
|
+
if (!data || region.z <= region.x || region.w <= region.y) {
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
const u = (x - region.x) / (region.z - region.x);
|
|
439
|
+
const v = (z - region.y) / (region.w - region.y);
|
|
440
|
+
if (u < 0 || u > 1 || v < 0 || v > 1) {
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
return this.sampleHeightTexel(data, u, v) * this.scale.y + this.worldMatrix.m13;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Unit surface normal of the terrain at a world position, from central differences one height
|
|
447
|
+
* map texel apart, or null where {@link ClipmapTerrain.getHeightAt} is.
|
|
448
|
+
*/ getNormalAt(x, z, out) {
|
|
449
|
+
const data = this._heightData;
|
|
450
|
+
const region = this.worldRegion;
|
|
451
|
+
if (!data || region.z <= region.x || region.w <= region.y) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
const rw = region.z - region.x;
|
|
455
|
+
const rh = region.w - region.y;
|
|
456
|
+
const u = (x - region.x) / rw;
|
|
457
|
+
const v = (z - region.y) / rh;
|
|
458
|
+
if (u < 0 || u > 1 || v < 0 || v > 1) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const du = 1 / data.width;
|
|
462
|
+
const dv = 1 / data.height;
|
|
463
|
+
const sy = this.scale.y;
|
|
464
|
+
const dx = (this.sampleHeightTexel(data, u + du, v) - this.sampleHeightTexel(data, u - du, v)) * sy;
|
|
465
|
+
const dz = (this.sampleHeightTexel(data, u, v + dv) - this.sampleHeightTexel(data, u, v - dv)) * sy;
|
|
466
|
+
out = out ?? new Vector3();
|
|
467
|
+
out.setXYZ(-dx / (2 * du * rw), 1, -dz / (2 * dv * rh));
|
|
468
|
+
return out.inplaceNormalize();
|
|
469
|
+
}
|
|
470
|
+
sampleHeightTexel(data, u, v) {
|
|
471
|
+
// Texel i holds the height at the centre of cell i, at u = (i + 0.5) / width
|
|
472
|
+
const w = data.width;
|
|
473
|
+
const h = data.height;
|
|
474
|
+
const fx = Math.min(Math.max(u * w - 0.5, 0), w - 1);
|
|
475
|
+
const fz = Math.min(Math.max(v * h - 0.5, 0), h - 1);
|
|
476
|
+
const x0 = Math.floor(fx);
|
|
477
|
+
const z0 = Math.floor(fz);
|
|
478
|
+
const x1 = Math.min(x0 + 1, w - 1);
|
|
479
|
+
const z1 = Math.min(z0 + 1, h - 1);
|
|
480
|
+
const tx = fx - x0;
|
|
481
|
+
const tz = fz - z0;
|
|
482
|
+
const d = data.data;
|
|
483
|
+
const h00 = half2float(d[z0 * w + x0]);
|
|
484
|
+
const h10 = half2float(d[z0 * w + x1]);
|
|
485
|
+
const h01 = half2float(d[z1 * w + x0]);
|
|
486
|
+
const h11 = half2float(d[z1 * w + x1]);
|
|
487
|
+
const a = h00 + (h10 - h00) * tx;
|
|
488
|
+
const b = h01 + (h11 - h01) * tx;
|
|
489
|
+
return a + (b - a) * tz;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Reads the half float heights back from the GPU into {@link ClipmapTerrain.heightData}.
|
|
493
|
+
* A read back overtaken by another height change is dropped.
|
|
494
|
+
*/ readBackHeightData() {
|
|
495
|
+
const map = this.heightMap;
|
|
496
|
+
if (!map || map.format !== 'r16f' && map.format !== 'rgba16f') {
|
|
497
|
+
return null;
|
|
243
498
|
}
|
|
499
|
+
if (this._heightReadBack && this._heightReadBack.version === this._heightVersion) {
|
|
500
|
+
return this._heightReadBack.promise;
|
|
501
|
+
}
|
|
502
|
+
const version = this._heightVersion;
|
|
503
|
+
const w = map.width;
|
|
504
|
+
const h = map.height;
|
|
505
|
+
const channels = map.format === 'r16f' ? 1 : 4;
|
|
506
|
+
const buffer = new Uint16Array(w * h * channels);
|
|
507
|
+
const promise = map.readPixels(0, 0, w, h, 0, 0, buffer).then(()=>{
|
|
508
|
+
if (version !== this._heightVersion || this.heightMap !== map) {
|
|
509
|
+
return this._heightData;
|
|
510
|
+
}
|
|
511
|
+
let data = buffer;
|
|
512
|
+
if (channels !== 1) {
|
|
513
|
+
// The height is in the red channel
|
|
514
|
+
data = new Uint16Array(w * h);
|
|
515
|
+
for(let i = 0; i < data.length; i++){
|
|
516
|
+
data[i] = buffer[i * channels];
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
// Same heights as on the GPU: the version stays, physics need not rebuild
|
|
520
|
+
this._heightData = {
|
|
521
|
+
data,
|
|
522
|
+
width: w,
|
|
523
|
+
height: h
|
|
524
|
+
};
|
|
525
|
+
return this._heightData;
|
|
526
|
+
}).catch((err)=>{
|
|
527
|
+
console.error(`Terrain height read back failed: ${err}`);
|
|
528
|
+
return null;
|
|
529
|
+
}).finally(()=>{
|
|
530
|
+
if (this._heightReadBack?.promise === promise) {
|
|
531
|
+
this._heightReadBack = null;
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
this._heightReadBack = {
|
|
535
|
+
version,
|
|
536
|
+
promise
|
|
537
|
+
};
|
|
538
|
+
return promise;
|
|
244
539
|
}
|
|
245
540
|
/** The splat map texture */ get splatMap() {
|
|
246
541
|
return this.material?.getSplatMap() ?? null;
|
|
@@ -253,6 +548,7 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
253
548
|
}
|
|
254
549
|
set wireframe(val) {
|
|
255
550
|
this._clipmap.wireframe = val;
|
|
551
|
+
this._shadowClipmap.wireframe = val;
|
|
256
552
|
}
|
|
257
553
|
/**
|
|
258
554
|
* {@inheritDoc Drawable.getPickTarget }
|
|
@@ -363,37 +659,125 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
363
659
|
* terrain.updateBoundingBox();
|
|
364
660
|
* ```
|
|
365
661
|
*/ updateBoundingBox() {
|
|
662
|
+
// Called after the heights changed on the GPU: a CPU copy is stale now.
|
|
663
|
+
this._heightData = null;
|
|
664
|
+
this._heightVersion++;
|
|
665
|
+
this.readBackHeightData();
|
|
666
|
+
const tmp = this.updateHeightPyramid();
|
|
667
|
+
if (!tmp) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
const data = new Float32Array(4);
|
|
671
|
+
const serial = ++this._heightRangeSerial;
|
|
672
|
+
tmp.readPixels(0, 0, 1, 1, 0, tmp.mipLevelCount - 1, data).then(()=>{
|
|
673
|
+
// Loading sets the range synchronously right after a resize has started a read back of
|
|
674
|
+
// the empty height map; that stale result must not land on top of it.
|
|
675
|
+
if (serial !== this._heightRangeSerial) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
// The reduction stores (max, min) in (r, g)
|
|
679
|
+
this._maxHeight = data[0];
|
|
680
|
+
this._minHeight = data[1];
|
|
681
|
+
this.invalidateWorldBoundingVolume(false);
|
|
682
|
+
}).catch((_err)=>{
|
|
683
|
+
console.error('Read pixels failed');
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Replaces every height of an r16f height map with heights from the CPU.
|
|
688
|
+
*
|
|
689
|
+
* Unlike writing into {@link ClipmapTerrain.heightMap} and calling
|
|
690
|
+
* {@link ClipmapTerrain.updateBoundingBox}, the bounds are right at once and the heights stay
|
|
691
|
+
* available as {@link ClipmapTerrain.heightData}, so physics colliders need no GPU read back.
|
|
692
|
+
*
|
|
693
|
+
* @param data - Half float heights, one per height map texel, row by row
|
|
694
|
+
*/ setHeights(data) {
|
|
366
695
|
const heightMap = this.heightMap;
|
|
367
|
-
if (!heightMap) {
|
|
696
|
+
if (!heightMap || heightMap.format !== 'r16f' || data.length !== heightMap.width * heightMap.height) {
|
|
697
|
+
console.error('setHeights() needs one half float per texel of an r16f height map');
|
|
368
698
|
return;
|
|
369
699
|
}
|
|
700
|
+
heightMap.update(data, 0, 0, heightMap.width, heightMap.height);
|
|
701
|
+
this.updateHeightPyramid();
|
|
702
|
+
this.setHeightRangeFromHalfData(data);
|
|
703
|
+
this.setHeightData(data, heightMap.width, heightMap.height);
|
|
704
|
+
this.invalidateRuntimeVirtualTexture();
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* The min/max height pyramid of the height map: (max, min) in (r, g), mip 0 padded to a power
|
|
708
|
+
* of two by repeating the last row and column, so texel j of mip m covers height map texels
|
|
709
|
+
* [j * 2^m, (j + 1) * 2^m). Null until built.
|
|
710
|
+
* @internal
|
|
711
|
+
*/ get heightPyramid() {
|
|
712
|
+
return this._tmpTexture.get() ?? null;
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Tile resolution of the clipmap, in grid cells
|
|
716
|
+
* @internal
|
|
717
|
+
*/ get clipmapTileResolution() {
|
|
718
|
+
return this._clipmap.tileResolution;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Rebuilds the min/max height pyramid from the current height map.
|
|
722
|
+
* Called when the height map is replaced and by {@link ClipmapTerrain.updateBoundingBox}; code
|
|
723
|
+
* that writes into the height map directly must call one of them afterwards.
|
|
724
|
+
* @internal
|
|
725
|
+
*/ updateHeightPyramid() {
|
|
726
|
+
const heightMap = this.heightMap;
|
|
727
|
+
if (!heightMap) {
|
|
728
|
+
return null;
|
|
729
|
+
}
|
|
370
730
|
const device = getDevice();
|
|
731
|
+
const width = nextPowerOf2(heightMap.width);
|
|
732
|
+
const height = nextPowerOf2(heightMap.height);
|
|
371
733
|
let tmp = this._tmpTexture.get();
|
|
372
|
-
if (tmp && (tmp.width !==
|
|
734
|
+
if (tmp && (tmp.width !== width || tmp.height !== height)) {
|
|
373
735
|
this._tmpTexture.dispose();
|
|
374
736
|
}
|
|
375
737
|
if (!this._tmpTexture.get()) {
|
|
376
|
-
tmp = getDevice().createTexture2D(
|
|
738
|
+
tmp = getDevice().createTexture2D('rg32f', width, height);
|
|
377
739
|
tmp.name = 'TerrainBoundingBoxTexture';
|
|
378
740
|
this._tmpTexture.set(tmp);
|
|
379
741
|
}
|
|
380
742
|
const tmpFB = device.createFrameBuffer([
|
|
381
743
|
tmp
|
|
382
744
|
], null);
|
|
383
|
-
ClipmapTerrain.
|
|
745
|
+
ClipmapTerrain._padBlitter.sizes.setXYZW(width, height, heightMap.width, heightMap.height);
|
|
746
|
+
ClipmapTerrain._padBlitter.blit(heightMap, tmpFB, fetchSampler('clamp_nearest_nomip'));
|
|
384
747
|
tmpFB.dispose();
|
|
385
748
|
ClipmapTerrain._heightBoundingGenerator.render(tmp);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
749
|
+
return tmp;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Sets the height range from height map data already on the CPU, e.g. when loading.
|
|
753
|
+
*
|
|
754
|
+
* {@link ClipmapTerrain.updateBoundingBox} reads the range back from the GPU, which lands a
|
|
755
|
+
* few frames later; until then the bounds would stay flat and cull the terrain wrongly.
|
|
756
|
+
*
|
|
757
|
+
* @param data - Half float heights, one per texel
|
|
758
|
+
* @param stride - Number of half floats per texel, the height being the first
|
|
759
|
+
* @internal
|
|
760
|
+
*/ setHeightRangeFromHalfData(data, stride = 1) {
|
|
761
|
+
let minHeight = Number.POSITIVE_INFINITY;
|
|
762
|
+
let maxHeight = Number.NEGATIVE_INFINITY;
|
|
763
|
+
for(let i = 0; i < data.length; i += stride){
|
|
764
|
+
const h = half2float(data[i]);
|
|
765
|
+
if (h < minHeight) {
|
|
766
|
+
minHeight = h;
|
|
767
|
+
}
|
|
768
|
+
if (h > maxHeight) {
|
|
769
|
+
maxHeight = h;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
if (minHeight <= maxHeight) {
|
|
773
|
+
this._heightRangeSerial++;
|
|
774
|
+
this._minHeight = minHeight;
|
|
775
|
+
this._maxHeight = maxHeight;
|
|
390
776
|
this.invalidateWorldBoundingVolume(false);
|
|
391
|
-
}
|
|
392
|
-
console.error('Read pixels failed');
|
|
393
|
-
});
|
|
777
|
+
}
|
|
394
778
|
}
|
|
395
779
|
/** @internal */ createHeightMapTexture(width, height) {
|
|
396
|
-
return getDevice().createTexture2D(
|
|
780
|
+
return getDevice().createTexture2D('r16f', width, height);
|
|
397
781
|
}
|
|
398
782
|
/** @internal */ _onTransformChanged(invalidateLocal) {
|
|
399
783
|
super._onTransformChanged(invalidateLocal);
|
|
@@ -404,29 +788,51 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
404
788
|
if (!mat) {
|
|
405
789
|
return;
|
|
406
790
|
}
|
|
407
|
-
const
|
|
408
|
-
const
|
|
791
|
+
const bv = this.getWorldBoundingVolume()?.toAABB() ?? null;
|
|
792
|
+
const originY = this.worldMatrix.m13;
|
|
793
|
+
const calcAABB = (_userData, minX, maxX, minZ, maxZ, outAABB)=>{
|
|
794
|
+
outAABB.minPoint.setXYZ(minX, bv ? bv.minPoint.y : originY - 9999, minZ);
|
|
795
|
+
outAABB.maxPoint.setXYZ(maxX, bv ? bv.maxPoint.y : originY + 9999, maxZ);
|
|
796
|
+
};
|
|
797
|
+
// Passes rendered from this camera only need the tiles inside its frustum. Shadow passes
|
|
798
|
+
// render from the light and need casters outside of it too, so they get an unculled set
|
|
799
|
+
// built around the same camera (same levels, so the level data below serves both).
|
|
409
800
|
this._renderData = this._clipmap.gather({
|
|
410
801
|
camera: camera,
|
|
411
802
|
minMaxWorldPos: mat.region,
|
|
412
803
|
gridScale: this._gridScale,
|
|
804
|
+
gridOriginX: this._gridOriginX,
|
|
805
|
+
gridOriginZ: this._gridOriginZ,
|
|
413
806
|
userData: this,
|
|
414
|
-
frustumCulling:
|
|
415
|
-
calcAABB
|
|
416
|
-
const p = that.worldMatrix.transformPointAffine(Vector3.zero());
|
|
417
|
-
outAABB.minPoint.setXYZ(minX, bv ? bv.minPoint.y : p.y - 9999, minZ);
|
|
418
|
-
outAABB.maxPoint.setXYZ(maxX, bv ? bv.maxPoint.y : p.y + 9999, maxZ);
|
|
419
|
-
}
|
|
807
|
+
frustumCulling: true,
|
|
808
|
+
calcAABB
|
|
420
809
|
});
|
|
810
|
+
// Each shadow map camera (cascade, cube face) culls this set again in draw()
|
|
811
|
+
this._shadowGatherContext = this.castShadow ? {
|
|
812
|
+
camera: camera,
|
|
813
|
+
minMaxWorldPos: mat.region,
|
|
814
|
+
gridScale: this._gridScale,
|
|
815
|
+
gridOriginX: this._gridOriginX,
|
|
816
|
+
gridOriginZ: this._gridOriginZ,
|
|
817
|
+
userData: this,
|
|
818
|
+
frustumCulling: false,
|
|
819
|
+
calcAABB
|
|
820
|
+
} : null;
|
|
821
|
+
this._shadowRenderData = this._shadowGatherContext ? this._shadowClipmap.gather(this._shadowGatherContext) : null;
|
|
421
822
|
let maxMipLevel = 0;
|
|
422
|
-
for (const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
823
|
+
for (const renderData of [
|
|
824
|
+
this._renderData,
|
|
825
|
+
this._shadowRenderData
|
|
826
|
+
]){
|
|
827
|
+
for (const info of renderData ?? []){
|
|
828
|
+
const buffer = info.primitive.getVertexBuffer('texCoord1');
|
|
829
|
+
buffer.bufferSubData(0, info.mipLevels, 0, info.numInstances);
|
|
830
|
+
if (info.maxMiplevel > maxMipLevel) {
|
|
831
|
+
maxMipLevel = info.maxMiplevel;
|
|
832
|
+
}
|
|
427
833
|
}
|
|
428
834
|
}
|
|
429
|
-
const levelAABB = this._clipmap.calcLevelAABB(camera, mat.region, this._gridScale);
|
|
835
|
+
const levelAABB = this._clipmap.calcLevelAABB(camera, mat.region, this._gridScale, this._gridOriginX, this._gridOriginZ);
|
|
430
836
|
const cameraPos = camera.getWorldPosition();
|
|
431
837
|
const tmpBuffer = ClipmapTerrain._tmpBuffer;
|
|
432
838
|
for(let i = 0; i <= maxMipLevel; i++){
|
|
@@ -449,6 +855,8 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
449
855
|
tmpBuffer[i * 8 + 7] = 1 / (currentAABB.maxPoint.z - tmpBuffer[i * 8 + 3]);
|
|
450
856
|
}
|
|
451
857
|
mat.setLevelData(tmpBuffer, 8 * (maxMipLevel + 1));
|
|
858
|
+
// Grass placed on the GPU is generated around this camera, outside of any render pass
|
|
859
|
+
this.grassRenderer.updatePerCamera(camera);
|
|
452
860
|
this.scene?.queuePerCameraUpdateNode(this);
|
|
453
861
|
}
|
|
454
862
|
/**
|
|
@@ -460,7 +868,11 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
460
868
|
const z = Math.abs(this.scale.z);
|
|
461
869
|
const px = this.position.x + (this.parent?.worldMatrix.m03 ?? 0);
|
|
462
870
|
const pz = this.position.z + (this.parent?.worldMatrix.m23 ?? 0);
|
|
463
|
-
|
|
871
|
+
const cellX = x * this._sizeX / this.material.heightMap.width;
|
|
872
|
+
const cellZ = z * this._sizeZ / this.material.heightMap.height;
|
|
873
|
+
this._gridScale = Math.max(cellX, cellZ);
|
|
874
|
+
this._gridOriginX = px + cellX * 0.5;
|
|
875
|
+
this._gridOriginZ = pz + cellZ * 0.5;
|
|
464
876
|
this.material.update(new Vector4(px, pz, px + x * this._sizeX, pz + z * this._sizeZ), this.scale);
|
|
465
877
|
this.grassRenderer.updateMaterial();
|
|
466
878
|
}
|
|
@@ -469,12 +881,24 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
469
881
|
const mat = this._material?.get();
|
|
470
882
|
if (mat) {
|
|
471
883
|
this.bind(ctx, renderQueue);
|
|
472
|
-
|
|
884
|
+
// The shader places vertices at grid * gridScale - offset, then adds the world translation
|
|
885
|
+
mat.setClipmapGridInfo(this._gridScale, this.worldMatrix.m03 - this._gridOriginX, this.worldMatrix.m23 - this._gridOriginZ);
|
|
473
886
|
mat.apply(ctx);
|
|
474
|
-
|
|
887
|
+
const isShadowPass = ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP;
|
|
888
|
+
let renderData = isShadowPass ? this._shadowRenderData : this._renderData;
|
|
889
|
+
const cullCamera = renderQueue?.cullCamera;
|
|
890
|
+
if (isShadowPass && renderData && cullCamera && this._shadowGatherContext) {
|
|
891
|
+
this._shadowGatherContext.camera = cullCamera;
|
|
892
|
+
renderData = this._shadowClipmap.cullInstances(renderData, this._shadowGatherContext);
|
|
893
|
+
for (const info of renderData){
|
|
894
|
+
info.primitive.getVertexBuffer('texCoord1').bufferSubData(0, info.mipLevels, 0, info.numInstances);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
for (const info of renderData ?? []){
|
|
475
898
|
mat.draw(info.primitive, ctx, info.numInstances);
|
|
476
899
|
}
|
|
477
|
-
|
|
900
|
+
// In shadow map passes the grass renderer draws the blades that cast shadows only
|
|
901
|
+
if (ctx.renderPass.type !== RENDER_PASS_TYPE_OBJECT_COLOR) {
|
|
478
902
|
this.grassRenderer.draw(ctx);
|
|
479
903
|
}
|
|
480
904
|
}
|
|
@@ -487,7 +911,7 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
487
911
|
sizeX = Math.min(Math.max(sizeX, 1), maxTextureSize) >> 0;
|
|
488
912
|
sizeZ = Math.min(Math.max(sizeZ, 1), maxTextureSize) >> 0;
|
|
489
913
|
if (sizeX !== oldHeightMap.width || sizeZ !== oldHeightMap.height) {
|
|
490
|
-
const newHeightMap = device.createTexture2D(
|
|
914
|
+
const newHeightMap = device.createTexture2D('r16f', sizeX, sizeZ);
|
|
491
915
|
const fb = device.createFrameBuffer([
|
|
492
916
|
newHeightMap
|
|
493
917
|
], null);
|
|
@@ -554,9 +978,14 @@ class HeightBoundingGenerator extends RenderMipmap {
|
|
|
554
978
|
* Should be called when the terrain is no longer needed.
|
|
555
979
|
*/ onDispose() {
|
|
556
980
|
super.onDispose();
|
|
981
|
+
this.setRuntimeVirtualTexture(null);
|
|
982
|
+
this._giAlbedo?.dispose();
|
|
983
|
+
this._giAlbedo = null;
|
|
557
984
|
this._clipmap?.dispose();
|
|
985
|
+
this._shadowClipmap?.dispose();
|
|
558
986
|
this._material?.dispose();
|
|
559
987
|
this._grassRenderer?.dispose();
|
|
988
|
+
this._tmpTexture.dispose();
|
|
560
989
|
}
|
|
561
990
|
}
|
|
562
991
|
|