@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
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { Disposable, DRef, AABB,
|
|
2
|
-
import '../../values.js';
|
|
3
|
-
import '../../render/render_queue.js';
|
|
1
|
+
import { Disposable, DRef, AABB, Vector3, Vector4, ClipState, DWeakRef, nextPowerOf2 } from '@zephyr3d/base';
|
|
2
|
+
import { RENDER_PASS_TYPE_SHADOWMAP } from '../../values.js';
|
|
4
3
|
import { getDevice } from '../../app/api.js';
|
|
4
|
+
import { warnUnsupported } from '../../utility/unsupported.js';
|
|
5
|
+
import '../../render/render_queue.js';
|
|
5
6
|
import { Primitive } from '../../render/primitive.js';
|
|
6
7
|
import '@zephyr3d/device';
|
|
7
8
|
import '../../material/shader/helper.js';
|
|
8
9
|
import '../../material/lambert.js';
|
|
9
10
|
import '../../material/blinn.js';
|
|
10
11
|
import '../../material/unlit.js';
|
|
12
|
+
import '../../material/meshmaterial.js';
|
|
11
13
|
import '../../material/particle.js';
|
|
12
14
|
import '../../material/subsurfaceprofile.js';
|
|
13
|
-
import '../../material/
|
|
15
|
+
import '../../material/sssprofile.js';
|
|
16
|
+
import '../../material/sss.js';
|
|
14
17
|
import '../../material/eye.js';
|
|
15
|
-
import '../../material/meshmaterial.js';
|
|
16
18
|
import '../../material/hair.js';
|
|
17
19
|
import '../../material/hairstrand.js';
|
|
18
20
|
import '../../material/grassmaterial.js';
|
|
@@ -29,25 +31,60 @@ import '../../render/lightpass.js';
|
|
|
29
31
|
import '../../render/sky.js';
|
|
30
32
|
import '../../render/clipmap.js';
|
|
31
33
|
import '../../render/envlight.js';
|
|
34
|
+
import '../../render/lod.js';
|
|
32
35
|
import '../../render/dualdepthpeeling_oit.js';
|
|
33
36
|
import '../../shaders/atmosphere.js';
|
|
37
|
+
import '../../render/water_interaction.js';
|
|
34
38
|
import '../../render/rendergraph/scene_render_context.js';
|
|
39
|
+
import '../../render/sdf/scene_sdf.js';
|
|
40
|
+
import '../../render/sdf/global_sdf.js';
|
|
41
|
+
import '../../render/gi/voxelize_pass.js';
|
|
35
42
|
import { ClipmapGrassMaterial } from './grassmaterial.js';
|
|
43
|
+
import { GrassGpuPlacement, grassHash, GrassOcclusionMode, GRASS_CULL_PLANES } from './grass_gpu.js';
|
|
44
|
+
import { DirectionalLight } from '../light.js';
|
|
45
|
+
import { ClipmapBladeGrassMaterial, createBladeIndices, BLADE_LOD_INDEX_COUNTS } from './bladegrassmaterial.js';
|
|
36
46
|
|
|
37
47
|
const INSTANCE_BYTES = 4 * 4;
|
|
38
48
|
/** Number of placement cells along each axis of a grass tile */ const TILE_CELLS = 64;
|
|
39
49
|
/** Default number of placement cells per density map texel along each axis */ const DEFAULT_CELLS_PER_TEXEL = 2;
|
|
40
50
|
const MAX_CELLS_PER_TEXEL = 8;
|
|
51
|
+
/** Default distance from the camera beyond which grass is not drawn */ const DEFAULT_DRAW_DISTANCE = 150;
|
|
52
|
+
/** Default fraction of blades kept at the draw distance */ const DEFAULT_FAR_DENSITY = 0.25;
|
|
53
|
+
/**
|
|
54
|
+
* Number of the nearest cascades of the sun's shadow map procedural blades cast shadows into.
|
|
55
|
+
* Farther cascades have texels too coarse for single blades.
|
|
56
|
+
*/ const GRASS_SHADOW_CASCADES = 2;
|
|
57
|
+
/** Default shape and clumping of procedural blades, see GrassBladeShape */ const DEFAULT_BLADE_SHAPE = [
|
|
58
|
+
1.5,
|
|
59
|
+
0.3,
|
|
60
|
+
0.08,
|
|
61
|
+
0.2,
|
|
62
|
+
0.25,
|
|
63
|
+
0.2,
|
|
64
|
+
0.15,
|
|
65
|
+
0.1,
|
|
66
|
+
1.9,
|
|
67
|
+
0.48,
|
|
68
|
+
0.2,
|
|
69
|
+
0.3,
|
|
70
|
+
0.2,
|
|
71
|
+
0.5,
|
|
72
|
+
0.15,
|
|
73
|
+
80
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* Default width of procedural blades
|
|
77
|
+
* @internal
|
|
78
|
+
*/ const DEFAULT_BLADE_WIDTH = 0.08;
|
|
41
79
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return (h >>> 0) / 4294967296;
|
|
80
|
+
* Default height of procedural blades
|
|
81
|
+
* @internal
|
|
82
|
+
*/ const DEFAULT_BLADE_HEIGHT = 1.5;
|
|
83
|
+
function distanceSqToAABB(x, y, z, aabb) {
|
|
84
|
+
const dx = Math.max(aabb.minPoint.x - x, 0, x - aabb.maxPoint.x);
|
|
85
|
+
const dy = Math.max(aabb.minPoint.y - y, 0, y - aabb.maxPoint.y);
|
|
86
|
+
const dz = Math.max(aabb.minPoint.z - z, 0, z - aabb.maxPoint.z);
|
|
87
|
+
return dx * dx + dy * dy + dz * dz;
|
|
51
88
|
}
|
|
52
89
|
/**
|
|
53
90
|
* Grass blade instance buffer for a single tile
|
|
@@ -121,10 +158,15 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
121
158
|
* @public
|
|
122
159
|
*/ class GrassLayer extends Disposable {
|
|
123
160
|
static _indexBuffer = new DRef();
|
|
161
|
+
static _bladeIndexBuffer = new DRef();
|
|
162
|
+
static _bladeVertexBuffer = new DRef();
|
|
124
163
|
static _cullAABB = new AABB();
|
|
164
|
+
static _cameraPos = new Vector3();
|
|
125
165
|
static _visibleTiles = [];
|
|
126
166
|
static _instanceData = new Float32Array(TILE_CELLS * TILE_CELLS * 4);
|
|
167
|
+
_kind;
|
|
127
168
|
_material;
|
|
169
|
+
_bladeShape;
|
|
128
170
|
_seed;
|
|
129
171
|
_bladeWidth;
|
|
130
172
|
_bladeHeight;
|
|
@@ -137,19 +179,33 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
137
179
|
_tilesX;
|
|
138
180
|
_tilesZ;
|
|
139
181
|
_numBlades;
|
|
182
|
+
_drawDistance;
|
|
183
|
+
_farDensity;
|
|
184
|
+
/** Set on WebGPU with indirect draw: blades are placed on the GPU instead of in CPU tiles */ _gpu;
|
|
185
|
+
/** Number of shadow maps the blades were placed for by the last updatePerCamera() call */ _numShadowTargets;
|
|
140
186
|
/**
|
|
141
187
|
* Creates an instance of GrassLayer
|
|
142
188
|
* @param terrain - Clipmap terrain object
|
|
143
189
|
* @param seed - Seed for deterministic blade placement, usually the layer index
|
|
144
190
|
* @param bladeWidth - Grass blade width
|
|
145
191
|
* @param bladeHeight - Grass blade height
|
|
146
|
-
* @param albedoMap - Albedo texture for the blade
|
|
147
|
-
|
|
192
|
+
* @param albedoMap - Albedo texture for the blade, card layers only
|
|
193
|
+
* @param kind - Textured cards, or procedural blades (drawn on WebGPU only)
|
|
194
|
+
*/ constructor(terrain, seed, bladeWidth, bladeHeight, albedoMap, kind = 'card'){
|
|
148
195
|
super();
|
|
149
|
-
this.
|
|
150
|
-
this.
|
|
151
|
-
if (
|
|
152
|
-
|
|
196
|
+
this._kind = kind;
|
|
197
|
+
this._bladeShape = new Float32Array(DEFAULT_BLADE_SHAPE);
|
|
198
|
+
if (kind === 'blade') {
|
|
199
|
+
const material = new ClipmapBladeGrassMaterial(terrain);
|
|
200
|
+
material.colorMap = albedoMap ?? null;
|
|
201
|
+
this._material = new DRef(material);
|
|
202
|
+
} else {
|
|
203
|
+
const material = new ClipmapGrassMaterial(terrain);
|
|
204
|
+
material.albedoTexture = albedoMap ?? null;
|
|
205
|
+
if (albedoMap) {
|
|
206
|
+
material.setTextureSize(albedoMap.width, albedoMap.height);
|
|
207
|
+
}
|
|
208
|
+
this._material = new DRef(material);
|
|
153
209
|
}
|
|
154
210
|
this._seed = seed;
|
|
155
211
|
this._bladeWidth = bladeWidth;
|
|
@@ -163,27 +219,402 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
163
219
|
this._tilesX = 0;
|
|
164
220
|
this._tilesZ = 0;
|
|
165
221
|
this._numBlades = 0;
|
|
222
|
+
this._drawDistance = 0;
|
|
223
|
+
this._farDensity = 1;
|
|
224
|
+
this._numShadowTargets = 0;
|
|
225
|
+
if (!GrassGpuPlacement.isSupported()) {
|
|
226
|
+
this._gpu = null;
|
|
227
|
+
if (kind === 'blade') {
|
|
228
|
+
warnUnsupported("Procedural grass blades (grass layer kind 'blade')", 'WebGPU with indirect draw', 'blade layers are not drawn');
|
|
229
|
+
}
|
|
230
|
+
} else if (kind === 'blade') {
|
|
231
|
+
this._gpu = new GrassGpuPlacement('blade', GrassLayer._getBladeVertexBuffer(), GrassLayer._getBladeIndexBuffer(), BLADE_LOD_INDEX_COUNTS);
|
|
232
|
+
} else {
|
|
233
|
+
this._gpu = new GrassGpuPlacement('card', this._baseVertexBuffer.get(), GrassLayer._getIndexBuffer());
|
|
234
|
+
}
|
|
235
|
+
if (kind === 'blade') {
|
|
236
|
+
this._bladeShape[0] = bladeHeight;
|
|
237
|
+
this._bladeShape[2] = bladeWidth;
|
|
238
|
+
this.bladeMaterial.lodDistance = this._bladeShape[15];
|
|
239
|
+
}
|
|
240
|
+
this._gpu?.setDensity(this._densityWidth, this._densityHeight, this._densityMap);
|
|
241
|
+
this.drawDistance = DEFAULT_DRAW_DISTANCE;
|
|
242
|
+
this.farDensity = DEFAULT_FAR_DENSITY;
|
|
166
243
|
this.updateTileGrid();
|
|
167
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Distance from the camera beyond which blades of this layer are not drawn. Blades shrink
|
|
247
|
+
* into the ground over the last quarter of it. Zero draws the layer at any distance.
|
|
248
|
+
*/ get drawDistance() {
|
|
249
|
+
return this._drawDistance;
|
|
250
|
+
}
|
|
251
|
+
set drawDistance(val) {
|
|
252
|
+
val = Math.max(0, Number(val) || 0);
|
|
253
|
+
if (val !== this._drawDistance) {
|
|
254
|
+
this._drawDistance = val;
|
|
255
|
+
this._material.get().setDrawDistance(val);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Fraction of the blades of this layer still drawn at the draw distance, 1 to draw them all.
|
|
260
|
+
*
|
|
261
|
+
* From a quarter of the draw distance on, blades thin out towards this fraction, each leaving
|
|
262
|
+
* at its own fixed distance, and the remaining ones widen to keep the ground covered. Saves
|
|
263
|
+
* most of the distant grass geometry where blades are placed on the GPU (WebGPU); elsewhere
|
|
264
|
+
* the dropped blades are still drawn, only shrunk to nothing. Has no effect without a draw
|
|
265
|
+
* distance, nor on blade layers, which thin out by their detail levels (see
|
|
266
|
+
* {@link GrassLayer.lodDistance}).
|
|
267
|
+
*/ get farDensity() {
|
|
268
|
+
return this._farDensity;
|
|
269
|
+
}
|
|
270
|
+
set farDensity(val) {
|
|
271
|
+
val = Math.min(1, Math.max(0.01, Number(val) || 0));
|
|
272
|
+
if (val !== this._farDensity) {
|
|
273
|
+
this._farDensity = val;
|
|
274
|
+
this._material.get().setFarDensity(val);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/** Kind of the blades of this layer, fixed at creation */ get kind() {
|
|
278
|
+
return this._kind;
|
|
279
|
+
}
|
|
168
280
|
/** @internal */ updateMaterial() {
|
|
169
281
|
this._material.get().uniformChanged();
|
|
170
282
|
}
|
|
171
283
|
/**
|
|
172
|
-
* Sets the albedo texture of grass blades in this layer
|
|
284
|
+
* Sets the albedo texture of grass blades in this layer: the card texture of card layers, the
|
|
285
|
+
* color map of blade layers (see {@link GrassLayer.colorMap})
|
|
173
286
|
* @param albedoMap - Albedo texture to set
|
|
174
287
|
*/ setAlbedoMap(albedoMap) {
|
|
175
|
-
this._material.get()
|
|
176
|
-
if (
|
|
177
|
-
|
|
288
|
+
const material = this._material.get();
|
|
289
|
+
if (material instanceof ClipmapGrassMaterial) {
|
|
290
|
+
material.albedoTexture = albedoMap;
|
|
291
|
+
if (albedoMap) {
|
|
292
|
+
material.setTextureSize(albedoMap.width, albedoMap.height);
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
material.colorMap = albedoMap;
|
|
178
296
|
}
|
|
179
297
|
}
|
|
180
298
|
/**
|
|
181
299
|
* Gets the albedo texture of grass blades in this layer
|
|
182
|
-
* @returns -
|
|
300
|
+
* @returns - The card texture of card layers, the color map of blade layers
|
|
183
301
|
*/ getAlbedoMap() {
|
|
184
|
-
|
|
302
|
+
const material = this._material.get();
|
|
303
|
+
return material instanceof ClipmapGrassMaterial ? material.albedoTexture : material.colorMap;
|
|
304
|
+
}
|
|
305
|
+
/** @internal */ get bladeMaterial() {
|
|
306
|
+
const material = this._material.get();
|
|
307
|
+
return material instanceof ClipmapBladeGrassMaterial ? material : null;
|
|
308
|
+
}
|
|
309
|
+
/** @internal */ setShape(index, value) {
|
|
310
|
+
if (Number.isFinite(value)) {
|
|
311
|
+
this._bladeShape[index] = value;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* How much blade heights vary around the layer's blade height, as a fraction of it.
|
|
316
|
+
* Blade layers only.
|
|
317
|
+
*/ get heightRandomness() {
|
|
318
|
+
return this._bladeShape[1];
|
|
319
|
+
}
|
|
320
|
+
set heightRandomness(val) {
|
|
321
|
+
this.setShape(1, Math.min(1, Math.max(0, val)));
|
|
322
|
+
}
|
|
323
|
+
/** How much blade widths vary around the layer's blade width, as a fraction of it. Blade layers only. */ get widthRandomness() {
|
|
324
|
+
return this._bladeShape[3];
|
|
325
|
+
}
|
|
326
|
+
set widthRandomness(val) {
|
|
327
|
+
this.setShape(3, Math.min(1, Math.max(0, val)));
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* How far the blades lean over: 0 stands them upright, 1 lays their tips on the ground.
|
|
331
|
+
* Blade layers only.
|
|
332
|
+
*/ get tilt() {
|
|
333
|
+
return this._bladeShape[4];
|
|
334
|
+
}
|
|
335
|
+
set tilt(val) {
|
|
336
|
+
this.setShape(4, Math.min(1, Math.max(0, val)));
|
|
337
|
+
}
|
|
338
|
+
/** How much the lean varies from blade to blade. Blade layers only. */ get tiltRandomness() {
|
|
339
|
+
return this._bladeShape[5];
|
|
340
|
+
}
|
|
341
|
+
set tiltRandomness(val) {
|
|
342
|
+
this.setShape(5, Math.min(1, Math.max(0, val)));
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* How much the blades arch: 0 keeps them straight, higher values bow the middle up so the tips
|
|
346
|
+
* droop. Blade layers only.
|
|
347
|
+
*/ get bend() {
|
|
348
|
+
return this._bladeShape[6];
|
|
349
|
+
}
|
|
350
|
+
set bend(val) {
|
|
351
|
+
this.setShape(6, Math.min(1, Math.max(-1, val)));
|
|
352
|
+
}
|
|
353
|
+
/** How much the arch varies from blade to blade. Blade layers only. */ get bendRandomness() {
|
|
354
|
+
return this._bladeShape[7];
|
|
355
|
+
}
|
|
356
|
+
set bendRandomness(val) {
|
|
357
|
+
this.setShape(7, Math.min(1, Math.max(0, val)));
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Typical size of a clump of blades, in world units. Blades of a clump share their height,
|
|
361
|
+
* direction and color, so the field breaks up into patches this big. Blade layers only.
|
|
362
|
+
*/ get clumpSize() {
|
|
363
|
+
return this._bladeShape[8];
|
|
364
|
+
}
|
|
365
|
+
set clumpSize(val) {
|
|
366
|
+
this.setShape(8, Math.max(0.01, val));
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* How much the height changes from clump to clump: 0 keeps every patch the same height,
|
|
370
|
+
* higher values give taller and shorter patches. Blade layers only.
|
|
371
|
+
*/ get clumpHeightVariation() {
|
|
372
|
+
return this._bladeShape[9];
|
|
373
|
+
}
|
|
374
|
+
set clumpHeightVariation(val) {
|
|
375
|
+
this.setShape(9, Math.min(1, Math.max(0, val)));
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* How much the blades of a clump gather toward its center: 0 spreads them evenly, 1 bunches
|
|
379
|
+
* them into tufts. Blade layers only.
|
|
380
|
+
*/ get clumpPull() {
|
|
381
|
+
return this._bladeShape[10];
|
|
382
|
+
}
|
|
383
|
+
set clumpPull(val) {
|
|
384
|
+
this.setShape(10, Math.min(1, Math.max(0, val)));
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* How much the blades of a clump lean the same way: 0 lets each blade face its own random way,
|
|
388
|
+
* 1 combs the whole patch in one direction. Blade layers only.
|
|
389
|
+
*/ get clumpSameDirection() {
|
|
390
|
+
return this._bladeShape[11];
|
|
391
|
+
}
|
|
392
|
+
set clumpSameDirection(val) {
|
|
393
|
+
this.setShape(11, Math.min(1, Math.max(0, val)));
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* How much the blades lean out from the center of their clump, so each patch splays open like a
|
|
397
|
+
* tuft. Blade layers only.
|
|
398
|
+
*/ get clumpFaceAway() {
|
|
399
|
+
return this._bladeShape[12];
|
|
400
|
+
}
|
|
401
|
+
set clumpFaceAway(val) {
|
|
402
|
+
this.setShape(12, Math.min(1, Math.max(0, val)));
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* How much the brightness changes from clump to clump, giving the field a patchy look.
|
|
406
|
+
* Blade layers only.
|
|
407
|
+
*/ get clumpColorVariation() {
|
|
408
|
+
return this.bladeMaterial?.clumpColorVariation ?? 0;
|
|
409
|
+
}
|
|
410
|
+
set clumpColorVariation(val) {
|
|
411
|
+
const material = this.bladeMaterial;
|
|
412
|
+
if (material) {
|
|
413
|
+
material.clumpColorVariation = val;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Optional color texture of the blades: V runs from the root (0) to the tip (1), U picks a
|
|
418
|
+
* column per clump. Replaces the root and tip colors when set. Blade layers only.
|
|
419
|
+
*/ get colorMap() {
|
|
420
|
+
return this.bladeMaterial?.colorMap ?? null;
|
|
421
|
+
}
|
|
422
|
+
set colorMap(val) {
|
|
423
|
+
const material = this.bladeMaterial;
|
|
424
|
+
if (material) {
|
|
425
|
+
material.colorMap = val;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* How much the ambient light darkens toward the root, where the neighboring blades hide the
|
|
430
|
+
* sky: 0 lights the whole blade evenly, 1 leaves the root black. Blade layers only.
|
|
431
|
+
*/ get rootOcclusion() {
|
|
432
|
+
return this.bladeMaterial?.rootOcclusion ?? 0;
|
|
433
|
+
}
|
|
434
|
+
set rootOcclusion(val) {
|
|
435
|
+
const material = this.bladeMaterial;
|
|
436
|
+
if (material) {
|
|
437
|
+
material.rootOcclusion = val;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* How much the blades narrow toward the tip: 0 keeps them wide to the end, 1 narrows them evenly
|
|
442
|
+
* to a point. Blade layers only.
|
|
443
|
+
*/ get taper() {
|
|
444
|
+
return this.bladeMaterial?.taper ?? 0;
|
|
445
|
+
}
|
|
446
|
+
set taper(val) {
|
|
447
|
+
const material = this.bladeMaterial;
|
|
448
|
+
if (material) {
|
|
449
|
+
material.taper = val;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Spends more of each blade's vertices near the tip, where it curves most. 1 spaces them
|
|
454
|
+
* evenly; higher values give smoother drooping tips. Blade layers only.
|
|
455
|
+
*/ get tipDetail() {
|
|
456
|
+
return this.bladeMaterial?.tipDetail ?? 1;
|
|
457
|
+
}
|
|
458
|
+
set tipDetail(val) {
|
|
459
|
+
const material = this.bladeMaterial;
|
|
460
|
+
if (material) {
|
|
461
|
+
material.tipDetail = val;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* How much the blade normals tilt outward across the width, so flat blades shade as if
|
|
466
|
+
* curved. 0 shades them flat. Blade layers only.
|
|
467
|
+
*/ get roundness() {
|
|
468
|
+
return this.bladeMaterial?.roundness ?? 0;
|
|
469
|
+
}
|
|
470
|
+
set roundness(val) {
|
|
471
|
+
const material = this.bladeMaterial;
|
|
472
|
+
if (material) {
|
|
473
|
+
material.roundness = val;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* How much blades seen edge-on widen toward the viewer, keeping fields full from low
|
|
478
|
+
* angles. 0 disables it. Blade layers only.
|
|
479
|
+
*/ get viewThickening() {
|
|
480
|
+
return this.bladeMaterial?.viewThickening ?? 0;
|
|
481
|
+
}
|
|
482
|
+
set viewThickening(val) {
|
|
483
|
+
const material = this.bladeMaterial;
|
|
484
|
+
if (material) {
|
|
485
|
+
material.viewThickening = val;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Distance at which the blades start shading as one surface per clump, which calms the
|
|
490
|
+
* glitter of distant fields. Blade layers only.
|
|
491
|
+
*/ get farNormalStart() {
|
|
492
|
+
return this.bladeMaterial?.farNormalStart ?? 0;
|
|
493
|
+
}
|
|
494
|
+
set farNormalStart(val) {
|
|
495
|
+
const material = this.bladeMaterial;
|
|
496
|
+
if (material) {
|
|
497
|
+
material.farNormalStart = val;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Distance beyond which the blades shade fully as one surface per clump. Blade layers only.
|
|
502
|
+
*/ get farNormalEnd() {
|
|
503
|
+
return this.bladeMaterial?.farNormalEnd ?? 0;
|
|
504
|
+
}
|
|
505
|
+
set farNormalEnd(val) {
|
|
506
|
+
const material = this.bladeMaterial;
|
|
507
|
+
if (material) {
|
|
508
|
+
material.farNormalEnd = val;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* How dull the highlights of distant blades get, reached at the far normal end distance. Blade layers only.
|
|
513
|
+
*/ get farRoughness() {
|
|
514
|
+
return this.bladeMaterial?.farRoughness ?? 0;
|
|
515
|
+
}
|
|
516
|
+
set farRoughness(val) {
|
|
517
|
+
const material = this.bladeMaterial;
|
|
518
|
+
if (material) {
|
|
519
|
+
material.farRoughness = val;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Minimum width of a blade on screen, in pixels: distant blades are widened to it instead of
|
|
524
|
+
* thinning below a pixel, which makes them flicker. Larger values calm the flicker more but make
|
|
525
|
+
* distant fields look thicker. 0 disables it. Blade layers only.
|
|
526
|
+
*/ get minScreenWidth() {
|
|
527
|
+
return this.bladeMaterial?.minScreenWidth ?? 0;
|
|
528
|
+
}
|
|
529
|
+
set minScreenWidth(val) {
|
|
530
|
+
const material = this.bladeMaterial;
|
|
531
|
+
if (material) {
|
|
532
|
+
material.minScreenWidth = val;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* How much the wind turns the blades to lean downwind, per unit of wind push: 0 keeps their own
|
|
537
|
+
* directions, higher values comb the field along the wind. Blade layers only.
|
|
538
|
+
*/ get windFacing() {
|
|
539
|
+
return this._bladeShape[13];
|
|
540
|
+
}
|
|
541
|
+
set windFacing(val) {
|
|
542
|
+
this.setShape(13, Math.min(4, Math.max(0, val)));
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* How far the wind lays the blades over, per unit of wind push: 0 leaves them standing, higher
|
|
546
|
+
* values flatten them in strong gusts.
|
|
547
|
+
*/ get windLean() {
|
|
548
|
+
return this._material.get().windLean;
|
|
549
|
+
}
|
|
550
|
+
set windLean(val) {
|
|
551
|
+
this._material.get().windLean = val;
|
|
552
|
+
}
|
|
553
|
+
/** How far the blade tips bob in the wind, as a fraction of their height per unit of wind push */ get swayAmplitude() {
|
|
554
|
+
return this._material.get().swayAmplitude;
|
|
555
|
+
}
|
|
556
|
+
set swayAmplitude(val) {
|
|
557
|
+
const material = this._material.get();
|
|
558
|
+
material.swayAmplitude = val;
|
|
559
|
+
this.setShape(14, material.swayAmplitude);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Distance from the camera at which blades switch to their low detail level: a quarter as many
|
|
563
|
+
* blades, each four times as wide and with fewer vertices, blending in over the last quarter of this
|
|
564
|
+
* distance. 0 keeps every blade at high detail up to the draw distance. Blade layers only.
|
|
565
|
+
*/ get lodDistance() {
|
|
566
|
+
return this._bladeShape[15];
|
|
185
567
|
}
|
|
186
|
-
|
|
568
|
+
set lodDistance(val) {
|
|
569
|
+
val = Math.max(0, Number(val) || 0);
|
|
570
|
+
this.setShape(15, val);
|
|
571
|
+
const material = this.bladeMaterial;
|
|
572
|
+
if (material) {
|
|
573
|
+
material.lodDistance = val;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
/** How fast the blades bob in the wind, in radians per second */ get swaySpeed() {
|
|
577
|
+
return this._material.get().swaySpeed;
|
|
578
|
+
}
|
|
579
|
+
set swaySpeed(val) {
|
|
580
|
+
this._material.get().swaySpeed = val;
|
|
581
|
+
}
|
|
582
|
+
/** Color at the root of the blades. Blade layers only. */ get rootColor() {
|
|
583
|
+
return this.bladeMaterial?.rootColor ?? Vector4.one();
|
|
584
|
+
}
|
|
585
|
+
set rootColor(val) {
|
|
586
|
+
const material = this.bladeMaterial;
|
|
587
|
+
if (material) {
|
|
588
|
+
material.rootColor = val;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
/** Color at the tip of the blades. Blade layers only. */ get tipColor() {
|
|
592
|
+
return this.bladeMaterial?.tipColor ?? Vector4.one();
|
|
593
|
+
}
|
|
594
|
+
set tipColor(val) {
|
|
595
|
+
const material = this.bladeMaterial;
|
|
596
|
+
if (material) {
|
|
597
|
+
material.tipColor = val;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Color of the light the blades let through when lit from behind, strongest at the tips, so a
|
|
602
|
+
* field glows against a low sun. Black lets no light through. Blade layers only.
|
|
603
|
+
*/ get transmissionColor() {
|
|
604
|
+
return this.bladeMaterial?.transmissionColor ?? Vector4.zero();
|
|
605
|
+
}
|
|
606
|
+
set transmissionColor(val) {
|
|
607
|
+
const material = this.bladeMaterial;
|
|
608
|
+
if (material) {
|
|
609
|
+
material.transmissionColor = val;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* How many grass blades are currently generated in this layer.
|
|
614
|
+
*
|
|
615
|
+
* Only counts the CPU placement path. Where blades are placed on the GPU (WebGPU) they are
|
|
616
|
+
* generated around the camera every frame and this stays 0.
|
|
617
|
+
*/ get numBlades() {
|
|
187
618
|
return this._numBlades;
|
|
188
619
|
}
|
|
189
620
|
/**
|
|
@@ -237,6 +668,13 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
237
668
|
* @param maxTexelX - Maximum x texel of the region (exclusive)
|
|
238
669
|
* @param maxTexelZ - Maximum z texel of the region (exclusive)
|
|
239
670
|
*/ updateDensityRegion(minTexelX, minTexelZ, maxTexelX, maxTexelZ) {
|
|
671
|
+
if (this._kind === 'blade' && !this._gpu) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
if (this._gpu) {
|
|
675
|
+
this._gpu.updateDensityRegion(this._densityMap, this._densityWidth, Math.max(0, minTexelX), Math.max(0, minTexelZ), Math.min(this._densityWidth, maxTexelX), Math.min(this._densityHeight, maxTexelZ));
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
240
678
|
const k = this._cellsPerTexel;
|
|
241
679
|
// expand by one texel to cover the bilinear sampling footprint
|
|
242
680
|
const cx0 = Math.max(0, (minTexelX - 1) * k);
|
|
@@ -265,6 +703,13 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
265
703
|
this._tiles.clear();
|
|
266
704
|
this._numBlades = 0;
|
|
267
705
|
this.updateTileGrid();
|
|
706
|
+
if (this._gpu) {
|
|
707
|
+
this._gpu.setDensity(this._densityWidth, this._densityHeight, this._densityMap);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (this._kind === 'blade') {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
268
713
|
for(let tz = 0; tz < this._tilesZ; tz++){
|
|
269
714
|
for(let tx = 0; tx < this._tilesX; tx++){
|
|
270
715
|
this.generateTile(tx, tz);
|
|
@@ -291,10 +736,16 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
291
736
|
if (width !== this._bladeWidth || height !== this._bladeHeight) {
|
|
292
737
|
this._bladeWidth = width;
|
|
293
738
|
this._bladeHeight = height;
|
|
739
|
+
if (this._kind === 'blade') {
|
|
740
|
+
this._bladeShape[0] = height;
|
|
741
|
+
this._bladeShape[2] = width;
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
294
744
|
this._baseVertexBuffer.set(this.createBaseVertexBuffer(this._bladeWidth, this._bladeHeight));
|
|
295
745
|
for (const tile of this._tiles.values()){
|
|
296
746
|
tile.setBaseVertexBuffer(this._baseVertexBuffer.get());
|
|
297
747
|
}
|
|
748
|
+
this._gpu?.setBaseVertexBuffer(this._baseVertexBuffer.get());
|
|
298
749
|
}
|
|
299
750
|
}
|
|
300
751
|
/** @internal */ updateTileGrid() {
|
|
@@ -354,14 +805,15 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
354
805
|
let count = 0;
|
|
355
806
|
for(let cz = cz0; cz < cz1; cz++){
|
|
356
807
|
for(let cx = cx0; cx < cx1; cx++){
|
|
357
|
-
const u = (cx +
|
|
358
|
-
const v = (cz +
|
|
359
|
-
if (this.sampleDensity(u, v) >
|
|
360
|
-
const angle =
|
|
808
|
+
const u = (cx + grassHash(cx, cz, seed)) / cw;
|
|
809
|
+
const v = (cz + grassHash(cx, cz, seed + 1)) / ch;
|
|
810
|
+
if (this.sampleDensity(u, v) > grassHash(cx, cz, seed + 2)) {
|
|
811
|
+
const angle = grassHash(cx, cz, seed + 3) * Math.PI * 2;
|
|
361
812
|
data[count * 4 + 0] = u;
|
|
362
813
|
data[count * 4 + 1] = v;
|
|
363
|
-
data[count * 4 + 2] =
|
|
364
|
-
|
|
814
|
+
data[count * 4 + 2] = angle;
|
|
815
|
+
// Density LOD hash, see ClipmapGrassMaterial
|
|
816
|
+
data[count * 4 + 3] = grassHash(cx, cz, seed + 4);
|
|
365
817
|
count++;
|
|
366
818
|
}
|
|
367
819
|
}
|
|
@@ -405,6 +857,22 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
405
857
|
}
|
|
406
858
|
return this._indexBuffer.get();
|
|
407
859
|
}
|
|
860
|
+
/** @internal */ static _getBladeIndexBuffer() {
|
|
861
|
+
if (!this._bladeIndexBuffer.get()) {
|
|
862
|
+
this._bladeIndexBuffer.set(getDevice().createIndexBuffer(createBladeIndices()));
|
|
863
|
+
}
|
|
864
|
+
return this._bladeIndexBuffer.get();
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Procedural blades read nothing from their vertex buffer, but a draw still needs a vertex
|
|
868
|
+
* layout, which one vertex establishes
|
|
869
|
+
* @internal
|
|
870
|
+
*/ static _getBladeVertexBuffer() {
|
|
871
|
+
if (!this._bladeVertexBuffer.get()) {
|
|
872
|
+
this._bladeVertexBuffer.set(getDevice().createVertexBuffer('position_f32x3', new Float32Array(3)));
|
|
873
|
+
}
|
|
874
|
+
return this._bladeVertexBuffer.get();
|
|
875
|
+
}
|
|
408
876
|
/** @internal */ createBaseVertexBuffer(bladeWidth, bladeHeight) {
|
|
409
877
|
const device = getDevice();
|
|
410
878
|
const r = bladeWidth * 0.5;
|
|
@@ -478,7 +946,50 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
478
946
|
'tex0_f32x2'
|
|
479
947
|
], vertices);
|
|
480
948
|
}
|
|
949
|
+
/**
|
|
950
|
+
* Places the blades seen from a camera on the GPU path; nothing to do on the CPU one.
|
|
951
|
+
* @param shadowCullPlanes - For each shadow map the blades cast shadows into, the planes
|
|
952
|
+
* bounding where its casters can be (see GrassRenderer); blade layers only
|
|
953
|
+
* @param shadowFade - View depths over which the shadow casting blades thin out
|
|
954
|
+
* @internal
|
|
955
|
+
*/ updatePerCamera(camera, terrain, occlusionMode, shadowCullPlanes, shadowFade) {
|
|
956
|
+
if (!this._gpu) {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
const wind = terrain.scene?.env.wind.shaderParams ?? null;
|
|
960
|
+
const place = (target, mode, planes, fade)=>this._gpu.generate(camera, terrain, this._seed, this._cellsPerTexel, this._drawDistance, this._bladeWidth, this._bladeHeight, mode, this._farDensity, this._bladeShape, wind, target, planes, fade);
|
|
961
|
+
place(0, occlusionMode, null, null);
|
|
962
|
+
// Target i + 1 holds the casters of shadow map i. Blades hidden behind the terrain from the
|
|
963
|
+
// camera still cast shadows, so these skip the occlusion culling.
|
|
964
|
+
const numShadowTargets = this._kind === 'blade' ? shadowCullPlanes.length : 0;
|
|
965
|
+
for(let i = 0; i < numShadowTargets; i++){
|
|
966
|
+
place(i + 1, GrassOcclusionMode.Off, shadowCullPlanes[i], shadowFade);
|
|
967
|
+
}
|
|
968
|
+
this._gpu.trimTargets(numShadowTargets + 1);
|
|
969
|
+
this._numShadowTargets = numShadowTargets;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Draws the shadow casters of the shadow map the blades were placed for by the last
|
|
973
|
+
* updatePerCamera() call
|
|
974
|
+
* @param shadowMap - Index of the shadow map
|
|
975
|
+
* @internal
|
|
976
|
+
*/ drawShadow(ctx, shadowMap) {
|
|
977
|
+
if (shadowMap < this._numShadowTargets) {
|
|
978
|
+
this.drawGpu(ctx, shadowMap + 1);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
/** @internal */ setOcclusionDebug(val) {
|
|
982
|
+
this._material.get().occlusionDebug = val;
|
|
983
|
+
}
|
|
481
984
|
/** @internal */ draw(ctx, region, minY, maxY) {
|
|
985
|
+
if (this._kind === 'blade' && !this._gpu) {
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (this._gpu) {
|
|
989
|
+
this.drawGpu(ctx, 0);
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
const wind = ctx.scene?.env.wind ?? null;
|
|
482
993
|
const visible = GrassLayer._visibleTiles;
|
|
483
994
|
visible.length = 0;
|
|
484
995
|
const camera = ctx.camera;
|
|
@@ -489,6 +1000,10 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
489
1000
|
const rz = region.y;
|
|
490
1001
|
const rw = region.z - region.x;
|
|
491
1002
|
const rh = region.w - region.y;
|
|
1003
|
+
const cameraPos = camera.getWorldPosition(GrassLayer._cameraPos);
|
|
1004
|
+
const maxDistSq = this._drawDistance > 0 ? this._drawDistance * this._drawDistance : Infinity;
|
|
1005
|
+
// The wind can lay the cards over by up to their height
|
|
1006
|
+
const windPad = wind && wind.strength > 0 ? this._bladeHeight : 0;
|
|
492
1007
|
for (const [key, tile] of this._tiles){
|
|
493
1008
|
const tx = key % this._tilesX;
|
|
494
1009
|
const tz = (key - tx) / this._tilesX;
|
|
@@ -496,8 +1011,11 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
496
1011
|
const v0 = tz * TILE_CELLS / cellsH;
|
|
497
1012
|
const u1 = Math.min(1, (tx + 1) * TILE_CELLS / cellsW);
|
|
498
1013
|
const v1 = Math.min(1, (tz + 1) * TILE_CELLS / cellsH);
|
|
499
|
-
cullAABB.minPoint.setXYZ(rx + u0 * rw, minY, rz + v0 * rh);
|
|
500
|
-
cullAABB.maxPoint.setXYZ(rx + u1 * rw, maxY, rz + v1 * rh);
|
|
1014
|
+
cullAABB.minPoint.setXYZ(rx + u0 * rw - windPad, minY, rz + v0 * rh - windPad);
|
|
1015
|
+
cullAABB.maxPoint.setXYZ(rx + u1 * rw + windPad, maxY, rz + v1 * rh + windPad);
|
|
1016
|
+
if (distanceSqToAABB(cameraPos.x, cameraPos.y, cameraPos.z, cullAABB) > maxDistSq) {
|
|
1017
|
+
continue;
|
|
1018
|
+
}
|
|
501
1019
|
const clipState = camera.clipMask ? cullAABB.getClipStateWithFrustumMask(camera.frustum, camera.clipMask) : cullAABB.getClipStateWithFrustum(camera.frustum);
|
|
502
1020
|
if (clipState !== ClipState.NOT_CLIPPED) {
|
|
503
1021
|
visible.push(tile);
|
|
@@ -506,15 +1024,41 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
506
1024
|
if (visible.length === 0) {
|
|
507
1025
|
return;
|
|
508
1026
|
}
|
|
509
|
-
this._material.get()
|
|
510
|
-
|
|
511
|
-
|
|
1027
|
+
const material = this._material.get();
|
|
1028
|
+
material.prepareDraw(wind);
|
|
1029
|
+
material.apply(ctx);
|
|
1030
|
+
for(let pass = 0; pass < material.numPasses; pass++){
|
|
1031
|
+
material.bind(ctx.device, pass);
|
|
512
1032
|
for (const tile of visible){
|
|
513
1033
|
tile.draw();
|
|
514
1034
|
}
|
|
515
1035
|
}
|
|
516
1036
|
visible.length = 0;
|
|
517
1037
|
}
|
|
1038
|
+
/** Draws the blades placed on the GPU into a target, see GrassGpuPlacement */ drawGpu(ctx, target) {
|
|
1039
|
+
// From the scene, not ctx.env: the depth pass clears ctx.env, and the depth prepass and the
|
|
1040
|
+
// light pass must bend the grass by the same wind or the light pass's equal depth test
|
|
1041
|
+
// rejects it
|
|
1042
|
+
const wind = ctx.scene?.env.wind ?? null;
|
|
1043
|
+
const gpu = this._gpu;
|
|
1044
|
+
const material = this._material.get();
|
|
1045
|
+
if (material instanceof ClipmapBladeGrassMaterial) {
|
|
1046
|
+
const instances = gpu.getInstanceBuffer(target);
|
|
1047
|
+
if (!instances) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
material.setInstanceBuffer(instances, gpu.getLowListBase(target));
|
|
1051
|
+
// The camera the blades were placed for, also in the shadow map passes
|
|
1052
|
+
material.prepareDraw(ctx.camera, wind, ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP ? 0 : ctx.renderHeight);
|
|
1053
|
+
} else {
|
|
1054
|
+
material.prepareDraw(wind);
|
|
1055
|
+
}
|
|
1056
|
+
material.apply(ctx);
|
|
1057
|
+
for(let pass = 0; pass < material.numPasses; pass++){
|
|
1058
|
+
material.bind(ctx.device, pass);
|
|
1059
|
+
gpu.draw(target);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
518
1062
|
/** @internal */ onDispose() {
|
|
519
1063
|
super.onDispose();
|
|
520
1064
|
this._material.dispose();
|
|
@@ -523,14 +1067,43 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
523
1067
|
}
|
|
524
1068
|
this._tiles.clear();
|
|
525
1069
|
this._baseVertexBuffer.dispose();
|
|
1070
|
+
this._gpu?.dispose();
|
|
526
1071
|
}
|
|
527
1072
|
}
|
|
528
1073
|
/**
|
|
529
1074
|
* Grass renderer for clipmap terrain
|
|
530
1075
|
* @public
|
|
531
1076
|
*/ class GrassRenderer extends Disposable {
|
|
1077
|
+
static _lightDir = new Vector3();
|
|
1078
|
+
static _forward = new Vector3();
|
|
1079
|
+
static _eye = new Vector3();
|
|
1080
|
+
static _center = new Vector3();
|
|
1081
|
+
static _tmp = new Vector3();
|
|
1082
|
+
static _edge0 = new Vector3();
|
|
1083
|
+
static _edge1 = new Vector3();
|
|
1084
|
+
static _normal = new Vector3();
|
|
1085
|
+
static _corners = Array.from({
|
|
1086
|
+
length: 8
|
|
1087
|
+
}, ()=>new Vector3());
|
|
1088
|
+
static _faceDots = [
|
|
1089
|
+
0,
|
|
1090
|
+
0,
|
|
1091
|
+
0,
|
|
1092
|
+
0,
|
|
1093
|
+
0,
|
|
1094
|
+
0
|
|
1095
|
+
];
|
|
1096
|
+
static _facePlane = new Float32Array(4);
|
|
1097
|
+
static _shadowCullPlanes = [];
|
|
532
1098
|
_terrain;
|
|
533
1099
|
_layers;
|
|
1100
|
+
_occlusionCulling;
|
|
1101
|
+
_occlusionDebug;
|
|
1102
|
+
_suspendOcclusionCulling;
|
|
1103
|
+
_castShadow;
|
|
1104
|
+
_shadowFadeFraction;
|
|
1105
|
+
/** View depths over which the blades casting shadows thin out, see calcShadowCullPlanes */ _shadowFade;
|
|
1106
|
+
/** The light whose shadow map casters the blades were last placed for */ _shadowLight;
|
|
534
1107
|
/**
|
|
535
1108
|
* Creates an instance of GrassRenderer
|
|
536
1109
|
* @param terrain - Clipmap terrain object
|
|
@@ -538,12 +1111,226 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
538
1111
|
super();
|
|
539
1112
|
this._terrain = new DWeakRef(terrain);
|
|
540
1113
|
this._layers = [];
|
|
1114
|
+
this._occlusionCulling = true;
|
|
1115
|
+
this._occlusionDebug = false;
|
|
1116
|
+
this._suspendOcclusionCulling = false;
|
|
1117
|
+
this._castShadow = true;
|
|
1118
|
+
this._shadowFadeFraction = 0.5;
|
|
1119
|
+
this._shadowFade = null;
|
|
1120
|
+
this._shadowLight = new DWeakRef();
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Whether to skip grass hidden behind the terrain itself (WebGPU only).
|
|
1124
|
+
*
|
|
1125
|
+
* Tested against the terrain height field every frame, so it never culls grass that is
|
|
1126
|
+
* visible, but it does not see occluders other than the terrain.
|
|
1127
|
+
*/ get occlusionCulling() {
|
|
1128
|
+
return this._occlusionCulling;
|
|
1129
|
+
}
|
|
1130
|
+
set occlusionCulling(val) {
|
|
1131
|
+
this._occlusionCulling = !!val;
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Draws the grass the terrain occlusion culling would skip in red instead of skipping it
|
|
1135
|
+
*/ get occlusionDebug() {
|
|
1136
|
+
return this._occlusionDebug;
|
|
1137
|
+
}
|
|
1138
|
+
set occlusionDebug(val) {
|
|
1139
|
+
this._occlusionDebug = !!val;
|
|
1140
|
+
for (const layer of this._layers){
|
|
1141
|
+
layer.setOcclusionDebug(this._occlusionDebug);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Pauses the terrain occlusion culling while the height map is being edited, since the
|
|
1146
|
+
* height pyramid it relies on is only rebuilt afterwards.
|
|
1147
|
+
* @internal
|
|
1148
|
+
*/ get suspendOcclusionCulling() {
|
|
1149
|
+
return this._suspendOcclusionCulling;
|
|
1150
|
+
}
|
|
1151
|
+
set suspendOcclusionCulling(val) {
|
|
1152
|
+
this._suspendOcclusionCulling = !!val;
|
|
541
1153
|
}
|
|
542
1154
|
/** @internal */ updateMaterial() {
|
|
543
1155
|
for (const layer of this._layers){
|
|
544
1156
|
layer.updateMaterial();
|
|
545
1157
|
}
|
|
546
1158
|
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Whether procedural blades cast shadows from the sun into the nearest cascades of its shadow
|
|
1161
|
+
* map (WebGPU only). Also needs the terrain to cast shadows.
|
|
1162
|
+
*/ get castShadow() {
|
|
1163
|
+
return this._castShadow;
|
|
1164
|
+
}
|
|
1165
|
+
set castShadow(val) {
|
|
1166
|
+
this._castShadow = !!val;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Fraction of the last shadow cascade the blades cast shadows into over which their shadows
|
|
1170
|
+
* fade out toward its far end, blade by blade. 0 ends them on a line at the far end.
|
|
1171
|
+
*/ get shadowFadeFraction() {
|
|
1172
|
+
return this._shadowFadeFraction;
|
|
1173
|
+
}
|
|
1174
|
+
set shadowFadeFraction(val) {
|
|
1175
|
+
this._shadowFadeFraction = Math.min(1, Math.max(0, Number(val) || 0));
|
|
1176
|
+
}
|
|
1177
|
+
/** @internal */ updatePerCamera(camera) {
|
|
1178
|
+
const terrain = this._terrain.get();
|
|
1179
|
+
if (terrain) {
|
|
1180
|
+
const mode = !this._occlusionCulling || this._suspendOcclusionCulling ? GrassOcclusionMode.Off : this._occlusionDebug ? GrassOcclusionMode.Debug : GrassOcclusionMode.Cull;
|
|
1181
|
+
const shadowCullPlanes = this.calcShadowCullPlanes(camera, terrain);
|
|
1182
|
+
for (const layer of this._layers){
|
|
1183
|
+
layer.updatePerCamera(camera, terrain, mode, shadowCullPlanes, this._shadowFade);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Culling planes of the blades casting shadows into each of the nearest cascades of the sun's
|
|
1189
|
+
* shadow map, and remembers the sun as the light the blades were placed for.
|
|
1190
|
+
*/ calcShadowCullPlanes(camera, terrain) {
|
|
1191
|
+
this._shadowLight.set(null);
|
|
1192
|
+
this._shadowFade = null;
|
|
1193
|
+
const scene = terrain.scene;
|
|
1194
|
+
const sun = scene ? DirectionalLight.getSunLight(scene) : null;
|
|
1195
|
+
if (!this._castShadow || !terrain.castShadow || !sun || !sun.castShadow || !GrassGpuPlacement.isSupported() || !this._layers.some((layer)=>layer.kind === 'blade')) {
|
|
1196
|
+
return [];
|
|
1197
|
+
}
|
|
1198
|
+
this._shadowLight.set(sun);
|
|
1199
|
+
const distances = sun.shadow.getCascadeDistances(camera);
|
|
1200
|
+
const numCascades = Math.min(GRASS_SHADOW_CASCADES, distances.length - 1);
|
|
1201
|
+
// The blades thin out over the far part of the last cascade they cast shadows into, so the
|
|
1202
|
+
// shadowed ground does not end on a line at its far split
|
|
1203
|
+
const fadeEnd = distances[numCascades];
|
|
1204
|
+
const fadeStart = fadeEnd - (fadeEnd - distances[numCascades - 1]) * this._shadowFadeFraction;
|
|
1205
|
+
this._shadowFade = fadeEnd > fadeStart ? [
|
|
1206
|
+
fadeStart,
|
|
1207
|
+
fadeEnd
|
|
1208
|
+
] : null;
|
|
1209
|
+
// Direction the light travels in
|
|
1210
|
+
const lightDir = GrassRenderer._lightDir;
|
|
1211
|
+
lightDir.set(sun.directionAndCutoff.xyz());
|
|
1212
|
+
lightDir.inplaceNormalize();
|
|
1213
|
+
const m = camera.worldMatrix;
|
|
1214
|
+
// Camera forward, the view axis the split distances are measured along
|
|
1215
|
+
const forward = GrassRenderer._forward.setXYZ(-m.m02, -m.m12, -m.m22).inplaceNormalize();
|
|
1216
|
+
const eye = camera.getWorldPosition(GrassRenderer._eye);
|
|
1217
|
+
const perspective = camera.isPerspective();
|
|
1218
|
+
const nearCorners = camera.frustum.corners;
|
|
1219
|
+
const corners = GrassRenderer._corners;
|
|
1220
|
+
const center = GrassRenderer._center;
|
|
1221
|
+
const tmp = GrassRenderer._tmp;
|
|
1222
|
+
const result = [];
|
|
1223
|
+
for(let i = 0; i < numCascades; i++){
|
|
1224
|
+
// Corners of the slice, indexed as the frustum corners: x << 2 | y << 1 | far. Each lies on
|
|
1225
|
+
// the ray through the matching near plane corner, at the split distance along the view axis.
|
|
1226
|
+
center.setXYZ(0, 0, 0);
|
|
1227
|
+
for(let c = 0; c < 8; c++){
|
|
1228
|
+
const near = nearCorners[c & 6];
|
|
1229
|
+
const d = distances[i + (c & 1)];
|
|
1230
|
+
Vector3.sub(near, eye, tmp);
|
|
1231
|
+
const depth = Vector3.dot(tmp, forward);
|
|
1232
|
+
if (perspective) {
|
|
1233
|
+
Vector3.add(eye, Vector3.scale(tmp, d / depth, tmp), corners[c]);
|
|
1234
|
+
} else {
|
|
1235
|
+
Vector3.add(near, Vector3.scale(forward, d - depth, tmp), corners[c]);
|
|
1236
|
+
}
|
|
1237
|
+
Vector3.add(center, corners[c], center);
|
|
1238
|
+
}
|
|
1239
|
+
center.scaleBy(1 / 8);
|
|
1240
|
+
// Faces of the slice: the four corners sharing one bit, normals pointing inward
|
|
1241
|
+
const faceDots = GrassRenderer._faceDots;
|
|
1242
|
+
const planes = GrassRenderer._shadowCullPlanes[i] ??= new Float32Array(GRASS_CULL_PLANES * 4);
|
|
1243
|
+
let numPlanes = 0;
|
|
1244
|
+
const addPlane = (a, b, c)=>{
|
|
1245
|
+
if (numPlanes < GRASS_CULL_PLANES) {
|
|
1246
|
+
if (GrassRenderer.planeThrough(a, b, c, center, planes, numPlanes * 4)) {
|
|
1247
|
+
numPlanes++;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
};
|
|
1251
|
+
for(let face = 0; face < 6; face++){
|
|
1252
|
+
const bit = 1 << (face >> 1);
|
|
1253
|
+
const side = face & 1 ? bit : 0;
|
|
1254
|
+
const others = [
|
|
1255
|
+
0,
|
|
1256
|
+
1,
|
|
1257
|
+
2,
|
|
1258
|
+
3
|
|
1259
|
+
].map((k)=>{
|
|
1260
|
+
// The two free bits of the face, in order
|
|
1261
|
+
const free = [
|
|
1262
|
+
1,
|
|
1263
|
+
2,
|
|
1264
|
+
4
|
|
1265
|
+
].filter((b)=>b !== bit);
|
|
1266
|
+
return side | (k & 1 ? free[0] : 0) | (k & 2 ? free[1] : 0);
|
|
1267
|
+
});
|
|
1268
|
+
GrassRenderer.planeThrough(corners[others[0]], corners[others[1]], corners[others[3]], center, GrassRenderer._facePlane, 0);
|
|
1269
|
+
const facePlane = GrassRenderer._facePlane;
|
|
1270
|
+
faceDots[face] = facePlane[0] * lightDir.x + facePlane[1] * lightDir.y + facePlane[2] * lightDir.z;
|
|
1271
|
+
// Faces the light travels away from, or along, bound the swept slice
|
|
1272
|
+
if (faceDots[face] <= 0 && numPlanes < GRASS_CULL_PLANES) {
|
|
1273
|
+
planes.set(facePlane, numPlanes * 4);
|
|
1274
|
+
numPlanes++;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
// Silhouette edges: shared by a face kept and a face dropped. Two faces are adjacent when
|
|
1278
|
+
// they fix different corner bits; their edge is the two corners with both bits fixed.
|
|
1279
|
+
for(let fa = 0; fa < 6; fa++){
|
|
1280
|
+
for(let fb = fa + 1; fb < 6; fb++){
|
|
1281
|
+
const bitA = 1 << (fa >> 1);
|
|
1282
|
+
const bitB = 1 << (fb >> 1);
|
|
1283
|
+
const keptA = faceDots[fa] <= 0;
|
|
1284
|
+
const keptB = faceDots[fb] <= 0;
|
|
1285
|
+
if (bitA === bitB || keptA === keptB) {
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1288
|
+
const fixed = (fa & 1 ? bitA : 0) | (fb & 1 ? bitB : 0);
|
|
1289
|
+
const freeBit = 7 & ~bitA & ~bitB;
|
|
1290
|
+
const a = corners[fixed];
|
|
1291
|
+
const b = corners[fixed | freeBit];
|
|
1292
|
+
// The third point extends the edge along the light, scaled by the edge length for
|
|
1293
|
+
Vector3.add(a, Vector3.scale(lightDir, Vector3.distance(a, b), tmp), tmp);
|
|
1294
|
+
addPlane(a, b, tmp);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
// The rest are planes everything is inside of
|
|
1298
|
+
for(let k = numPlanes; k < GRASS_CULL_PLANES; k++){
|
|
1299
|
+
planes.set([
|
|
1300
|
+
0,
|
|
1301
|
+
0,
|
|
1302
|
+
0,
|
|
1303
|
+
1e30
|
|
1304
|
+
], k * 4);
|
|
1305
|
+
}
|
|
1306
|
+
result.push(planes);
|
|
1307
|
+
}
|
|
1308
|
+
return result;
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Writes the plane through three points, normal turned toward an inside point, as (a, b, c, d)
|
|
1312
|
+
* at an offset of an array
|
|
1313
|
+
* @returns false if the points are degenerate
|
|
1314
|
+
*/ static planeThrough(p0, p1, p2, inside, out, offset) {
|
|
1315
|
+
const e0 = Vector3.sub(p1, p0, GrassRenderer._edge0);
|
|
1316
|
+
const e1 = Vector3.sub(p2, p0, GrassRenderer._edge1);
|
|
1317
|
+
const n = Vector3.cross(e0, e1, GrassRenderer._normal);
|
|
1318
|
+
const len = n.magnitude;
|
|
1319
|
+
if (len < 1e-12) {
|
|
1320
|
+
return false;
|
|
1321
|
+
}
|
|
1322
|
+
n.scaleBy(1 / len);
|
|
1323
|
+
let d = -Vector3.dot(n, p0);
|
|
1324
|
+
if (Vector3.dot(n, inside) + d < 0) {
|
|
1325
|
+
n.scaleBy(-1);
|
|
1326
|
+
d = -d;
|
|
1327
|
+
}
|
|
1328
|
+
out[offset] = n.x;
|
|
1329
|
+
out[offset + 1] = n.y;
|
|
1330
|
+
out[offset + 2] = n.z;
|
|
1331
|
+
out[offset + 3] = d;
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
547
1334
|
/** How many grass blades */ get numGrassBlades() {
|
|
548
1335
|
return this._layers.reduce((sum, layer)=>sum + layer.numBlades, 0);
|
|
549
1336
|
}
|
|
@@ -561,10 +1348,12 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
561
1348
|
* Adds a grass layer
|
|
562
1349
|
* @param bladeWidth - Width of grass blades in this layer
|
|
563
1350
|
* @param bladeHeight - Height of grass blades in this layer
|
|
564
|
-
* @param albedoMap - Albedo texture of grass blades in this layer
|
|
1351
|
+
* @param albedoMap - Albedo texture of grass blades in this layer, card layers only
|
|
1352
|
+
* @param kind - Textured cards (default), or procedural blades drawn on WebGPU only
|
|
565
1353
|
* @returns Index of the added grass layer
|
|
566
|
-
*/ addLayer(bladeWidth, bladeHeight, albedoMap) {
|
|
567
|
-
const layer = new GrassLayer(this._terrain.get(), this._layers.length, bladeWidth, bladeHeight, albedoMap);
|
|
1354
|
+
*/ addLayer(bladeWidth, bladeHeight, albedoMap, kind = 'card') {
|
|
1355
|
+
const layer = new GrassLayer(this._terrain.get(), this._layers.length, bladeWidth, bladeHeight, albedoMap, kind);
|
|
1356
|
+
layer.setOcclusionDebug(this._occlusionDebug);
|
|
568
1357
|
this._layers.push(layer);
|
|
569
1358
|
return this._layers.length - 1;
|
|
570
1359
|
}
|
|
@@ -588,6 +1377,44 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
588
1377
|
}
|
|
589
1378
|
}
|
|
590
1379
|
/**
|
|
1380
|
+
* Gets the draw distance of the grass layer at given index
|
|
1381
|
+
* @param layer - Index of the grass layer
|
|
1382
|
+
* @returns Distance from the camera beyond which the layer is not drawn, 0 for unlimited
|
|
1383
|
+
*/ getDrawDistance(layer) {
|
|
1384
|
+
return this._layers[layer]?.drawDistance ?? 0;
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Sets the draw distance of the grass layer at given index
|
|
1388
|
+
* @param layer - Index of the grass layer
|
|
1389
|
+
* @param distance - Distance from the camera beyond which the layer is not drawn, 0 for unlimited
|
|
1390
|
+
*/ setDrawDistance(layer, distance) {
|
|
1391
|
+
const grassLayer = this._layers[layer];
|
|
1392
|
+
if (grassLayer) {
|
|
1393
|
+
grassLayer.drawDistance = distance;
|
|
1394
|
+
} else {
|
|
1395
|
+
console.error(`Invalid grass layer: ${layer}`);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Gets the fraction of blades kept at the draw distance for the grass layer at given index
|
|
1400
|
+
* @param layer - Index of the grass layer
|
|
1401
|
+
* @returns Fraction of blades drawn at the draw distance, see GrassLayer.farDensity
|
|
1402
|
+
*/ getFarDensity(layer) {
|
|
1403
|
+
return this._layers[layer]?.farDensity ?? 1;
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Sets the fraction of blades kept at the draw distance for the grass layer at given index
|
|
1407
|
+
* @param layer - Index of the grass layer
|
|
1408
|
+
* @param farDensity - Fraction of blades drawn at the draw distance, see GrassLayer.farDensity
|
|
1409
|
+
*/ setFarDensity(layer, farDensity) {
|
|
1410
|
+
const grassLayer = this._layers[layer];
|
|
1411
|
+
if (grassLayer) {
|
|
1412
|
+
grassLayer.farDensity = farDensity;
|
|
1413
|
+
} else {
|
|
1414
|
+
console.error(`Invalid grass layer: ${layer}`);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
591
1418
|
* Gets width of the grass blades in the grass layer at given index
|
|
592
1419
|
* @param layer - Index of the grass layer
|
|
593
1420
|
* @returns Width of the grass blades in the layer
|
|
@@ -615,6 +1442,17 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
615
1442
|
}
|
|
616
1443
|
}
|
|
617
1444
|
/** @internal */ draw(ctx) {
|
|
1445
|
+
if (ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP) {
|
|
1446
|
+
// Only into the cascades of the light the blades were placed for
|
|
1447
|
+
const light = ctx.renderPass.light;
|
|
1448
|
+
if (light && light === this._shadowLight.get()) {
|
|
1449
|
+
const cascade = ctx.shadowMapInfo?.get(light)?.cascadeIndex ?? 0;
|
|
1450
|
+
for (const layer of this._layers){
|
|
1451
|
+
layer.drawShadow(ctx, cascade);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
618
1456
|
const bv = this._terrain.get().getWorldBoundingVolume().toAABB();
|
|
619
1457
|
const minY = bv.minPoint.y;
|
|
620
1458
|
const maxY = bv.maxPoint.y;
|
|
@@ -625,11 +1463,12 @@ const MAX_CELLS_PER_TEXEL = 8;
|
|
|
625
1463
|
onDispose() {
|
|
626
1464
|
super.onDispose();
|
|
627
1465
|
this._terrain.dispose();
|
|
1466
|
+
this._shadowLight.dispose();
|
|
628
1467
|
for (const layer of this._layers){
|
|
629
1468
|
layer.dispose();
|
|
630
1469
|
}
|
|
631
1470
|
}
|
|
632
1471
|
}
|
|
633
1472
|
|
|
634
|
-
export { GrassInstances, GrassLayer, GrassRenderer };
|
|
1473
|
+
export { DEFAULT_BLADE_HEIGHT, DEFAULT_BLADE_WIDTH, GrassInstances, GrassLayer, GrassRenderer };
|
|
635
1474
|
//# sourceMappingURL=grass.js.map
|