@woosh/meep-engine 3.52.0 → 3.54.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/package.json +1 -1
- package/src/core/math/noise/worley_noise_2d.d.ts +14 -0
- package/src/core/math/noise/worley_noise_2d.d.ts.map +1 -0
- package/src/core/math/noise/worley_noise_2d.js +74 -0
- package/src/engine/ecs/animation/Animation.d.ts +4 -25
- package/src/engine/ecs/animation/Animation.d.ts.map +1 -1
- package/src/engine/ecs/animation/Animation.js +9 -41
- package/src/engine/ecs/ik/IKGoalSystem.d.ts +4 -5
- package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
- package/src/engine/ecs/ik/IKGoalSystem.js +4 -6
- package/src/engine/graphics/ecs/mesh/assetTypeByPath.js +1 -1
- package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts +6 -1
- package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/CachingTextureAtlas.js +363 -325
- package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.d.ts +93 -14
- package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.js +322 -183
- package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.d.ts +9 -0
- package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +110 -83
- package/src/engine/graphics/texture/atlas/SpriteAtlas.d.ts +42 -0
- package/src/engine/graphics/texture/atlas/SpriteAtlas.d.ts.map +1 -0
- package/src/engine/{graphics3/decal/DecalAtlas.js → graphics/texture/atlas/SpriteAtlas.js} +202 -194
- package/src/engine/graphics/texture/atlas/SpriteAtlasFill.d.ts +12 -0
- package/src/engine/graphics/texture/atlas/SpriteAtlasFill.d.ts.map +1 -0
- package/src/engine/graphics/texture/atlas/SpriteAtlasFill.js +30 -0
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts +7 -0
- package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
- package/src/engine/graphics/texture/atlas/TextureAtlas.js +11 -1
- package/src/engine/graphics/texture/atlas/sprite_atlas_border.d.ts +52 -0
- package/src/engine/graphics/texture/atlas/sprite_atlas_border.d.ts.map +1 -0
- package/src/engine/{graphics3/decal/decal_atlas_border.js → graphics/texture/atlas/sprite_atlas_border.js} +69 -69
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +9 -22
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +58 -203
- package/src/engine/graphics3/AnimationSystem.d.ts +7 -18
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +62 -243
- package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DecalSystem.js +447 -450
- package/src/engine/graphics3/FoliageWindSystem.d.ts +67 -0
- package/src/engine/graphics3/FoliageWindSystem.d.ts.map +1 -0
- package/src/engine/graphics3/FoliageWindSystem.js +257 -0
- package/src/engine/graphics3/GPUFluidSystem.d.ts +7 -0
- package/src/engine/graphics3/GPUFluidSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUFluidSystem.js +39 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +9 -23
- package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/GPUParticleEmitterSystem.js +904 -949
- package/src/engine/graphics3/animation/AnimationClips.d.ts +107 -13
- package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -1
- package/src/engine/graphics3/animation/AnimationClips.js +207 -10
- package/src/engine/graphics3/animation/AnimationClipsSink.d.ts +89 -0
- package/src/engine/graphics3/animation/AnimationClipsSink.d.ts.map +1 -0
- package/src/engine/graphics3/animation/AnimationClipsSink.js +205 -0
- package/src/engine/graphics3/animation/FoliageWindRigs.d.ts +43 -0
- package/src/engine/graphics3/animation/FoliageWindRigs.d.ts.map +1 -0
- package/src/engine/graphics3/animation/FoliageWindRigs.js +69 -0
- package/src/engine/graphics3/animation/write_clip_playback.d.ts +17 -11
- package/src/engine/graphics3/animation/write_clip_playback.d.ts.map +1 -1
- package/src/engine/graphics3/animation/write_clip_playback.js +36 -27
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +8 -6
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +11 -5
- package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +7 -7
- package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -1
- package/src/engine/graphics3/pose/collect_entity_playbacks.js +14 -15
- package/src/engine/graphics3/prefab/Prefab.d.ts +6 -0
- package/src/engine/graphics3/prefab/Prefab.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/Prefab.js +169 -162
- package/src/engine/graphics3/prefab/prefab_compile.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_compile.js +369 -334
- package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_instantiate.js +43 -2
- package/src/engine/graphics3/terrain/chunk_terrain_material_surface.js +2 -2
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts +2 -3
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/ContactProbeSystem.js +2 -4
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/sound/simulation/PROBE_PLACEMENT.md +4 -4
- package/src/engine/sound/simulation/README.md +1 -1
- package/src/engine/sound/simulation/probe/bakeProbeField.d.ts +22 -8
- package/src/engine/sound/simulation/probe/bakeProbeField.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeProbeField.js +60 -15
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +19 -23
- package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts +63 -17
- package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts.map +1 -1
- package/src/engine/sound/simulation/probe/probe_sdf_grid.js +67 -17
- package/src/generation/foliage/FOLIAGE_DESIGN.md +319 -0
- package/src/generation/foliage/FOLIAGE_PLAN.md +198 -0
- package/src/generation/foliage/animation/build_tree_wind_rig.d.ts +20 -0
- package/src/generation/foliage/animation/build_tree_wind_rig.d.ts.map +1 -0
- package/src/generation/foliage/animation/build_tree_wind_rig.js +108 -0
- package/src/generation/foliage/asset/TreeAsset.d.ts +86 -0
- package/src/generation/foliage/asset/TreeAsset.d.ts.map +1 -0
- package/src/generation/foliage/asset/TreeAsset.js +111 -0
- package/src/generation/foliage/asset/TreeLODAsset.d.ts +115 -0
- package/src/generation/foliage/asset/TreeLODAsset.d.ts.map +1 -0
- package/src/generation/foliage/asset/TreeLODAsset.js +346 -0
- package/src/generation/foliage/asset/generate_tree.d.ts +15 -0
- package/src/generation/foliage/asset/generate_tree.d.ts.map +1 -0
- package/src/generation/foliage/asset/generate_tree.js +93 -0
- package/src/generation/foliage/asset/place_tree.d.ts +82 -0
- package/src/generation/foliage/asset/place_tree.d.ts.map +1 -0
- package/src/generation/foliage/asset/place_tree.js +194 -0
- package/src/generation/foliage/config/BarkMaterialConfig.d.ts +121 -0
- package/src/generation/foliage/config/BarkMaterialConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/BarkMaterialConfig.js +250 -0
- package/src/generation/foliage/config/BranchLevelConfig.d.ts +288 -0
- package/src/generation/foliage/config/BranchLevelConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/BranchLevelConfig.js +536 -0
- package/src/generation/foliage/config/CrownConfig.d.ts +100 -0
- package/src/generation/foliage/config/CrownConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/CrownConfig.js +186 -0
- package/src/generation/foliage/config/CrownEnvelopeType.d.ts +16 -0
- package/src/generation/foliage/config/CrownEnvelopeType.d.ts.map +1 -0
- package/src/generation/foliage/config/CrownEnvelopeType.js +17 -0
- package/src/generation/foliage/config/FoliageBarkType.d.ts +11 -0
- package/src/generation/foliage/config/FoliageBarkType.d.ts.map +1 -0
- package/src/generation/foliage/config/FoliageBarkType.js +16 -0
- package/src/generation/foliage/config/FoliageCardType.d.ts +12 -0
- package/src/generation/foliage/config/FoliageCardType.d.ts.map +1 -0
- package/src/generation/foliage/config/FoliageCardType.js +18 -0
- package/src/generation/foliage/config/FoliageConfig.d.ts +151 -0
- package/src/generation/foliage/config/FoliageConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/FoliageConfig.js +283 -0
- package/src/generation/foliage/config/FoliageMaterialConfig.d.ts +143 -0
- package/src/generation/foliage/config/FoliageMaterialConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/FoliageMaterialConfig.js +279 -0
- package/src/generation/foliage/config/PhyllotaxisMode.d.ts +13 -0
- package/src/generation/foliage/config/PhyllotaxisMode.d.ts.map +1 -0
- package/src/generation/foliage/config/PhyllotaxisMode.js +20 -0
- package/src/generation/foliage/config/TreeLODConfig.d.ts +87 -0
- package/src/generation/foliage/config/TreeLODConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/TreeLODConfig.js +211 -0
- package/src/generation/foliage/config/TreePreset.d.ts +16 -0
- package/src/generation/foliage/config/TreePreset.d.ts.map +1 -0
- package/src/generation/foliage/config/TreePreset.js +17 -0
- package/src/generation/foliage/config/TreeSpeciesConfig.d.ts +109 -0
- package/src/generation/foliage/config/TreeSpeciesConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/TreeSpeciesConfig.js +400 -0
- package/src/generation/foliage/config/TreeWindConfig.d.ts +84 -0
- package/src/generation/foliage/config/TreeWindConfig.d.ts.map +1 -0
- package/src/generation/foliage/config/TreeWindConfig.js +157 -0
- package/src/generation/foliage/index.d.ts +39 -0
- package/src/generation/foliage/index.d.ts.map +1 -0
- package/src/generation/foliage/index.js +44 -0
- package/src/generation/foliage/material/make_bark_material.d.ts +37 -0
- package/src/generation/foliage/material/make_bark_material.d.ts.map +1 -0
- package/src/generation/foliage/material/make_bark_material.js +730 -0
- package/src/generation/foliage/material/make_foliage_material.d.ts +40 -0
- package/src/generation/foliage/material/make_foliage_material.d.ts.map +1 -0
- package/src/generation/foliage/material/make_foliage_material.js +605 -0
- package/src/generation/foliage/mesh/branch_collar_project.d.ts +42 -0
- package/src/generation/foliage/mesh/branch_collar_project.d.ts.map +1 -0
- package/src/generation/foliage/mesh/branch_collar_project.js +205 -0
- package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts +35 -0
- package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts.map +1 -0
- package/src/generation/foliage/mesh/branch_ring_triangulate.js +72 -0
- package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts +95 -0
- package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts.map +1 -0
- package/src/generation/foliage/mesh/foliage_collect_attachments.js +569 -0
- package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts +19 -0
- package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts.map +1 -0
- package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.js +150 -0
- package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts +55 -0
- package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -0
- package/src/generation/foliage/mesh/tree_mesh_build_bark.js +1049 -0
- package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts +22 -0
- package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts.map +1 -0
- package/src/generation/foliage/mesh/tree_mesh_build_foliage.js +454 -0
- package/src/generation/foliage/presets/make_tree_species_preset.d.ts +13 -0
- package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -0
- package/src/generation/foliage/presets/make_tree_species_preset.js +870 -0
- package/src/generation/foliage/skeleton/TreeSkeleton.d.ts +443 -0
- package/src/generation/foliage/skeleton/TreeSkeleton.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/TreeSkeleton.js +1100 -0
- package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts +27 -0
- package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/crown_envelope_evaluate.js +121 -0
- package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts +32 -0
- package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/spine_frame_double_reflection.js +87 -0
- package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts +33 -0
- package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.js +205 -0
- package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts +17 -0
- package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.js +206 -0
- package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts +18 -0
- package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -0
- package/src/generation/foliage/skeleton/tree_skeleton_grow.js +1871 -0
- package/src/shade/playground/additive_blending/index.html +197 -0
- package/src/shade/playground/additive_blending/main.d.ts +2 -0
- package/src/shade/playground/additive_blending/main.d.ts.map +1 -0
- package/src/shade/playground/additive_blending/main.js +529 -0
- package/src/shade/playground/foliage_wind/README.md +18 -0
- package/src/shade/playground/foliage_wind/foliage_world.d.ts +133 -0
- package/src/shade/playground/foliage_wind/foliage_world.d.ts.map +1 -0
- package/src/shade/playground/foliage_wind/foliage_world.js +602 -0
- package/src/shade/playground/foliage_wind/index.html +260 -0
- package/src/shade/playground/foliage_wind/main.d.ts +2 -0
- package/src/shade/playground/foliage_wind/main.d.ts.map +1 -0
- package/src/shade/playground/foliage_wind/main.js +275 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +45 -16
- package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +145 -0
- package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts +9 -1
- package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.js +53 -1
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts +8 -0
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.js +71 -0
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts +11 -0
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.js +32 -0
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +30 -3
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +532 -79
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +19 -12
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +20 -13
- package/src/shade/renderer/animation/ShadeAnimationClip.d.ts +35 -8
- package/src/shade/renderer/animation/ShadeAnimationClip.d.ts.map +1 -1
- package/src/shade/renderer/animation/ShadeAnimationClip.js +433 -2
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +40 -32
- package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts +97 -0
- package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts.map +1 -0
- package/src/shade/renderer/animation/foliage/FoliageWindJoint.js +161 -0
- package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts +65 -0
- package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts.map +1 -0
- package/src/shade/renderer/animation/foliage/FoliageWindRig.js +89 -0
- package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts +19 -0
- package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts.map +1 -0
- package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.js +143 -0
- package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts +14 -0
- package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts.map +1 -0
- package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.js +116 -0
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_local.js +39 -29
- package/src/shade/renderer/animation/shader_animation_pose_resolve.js +37 -37
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +2 -2
- package/src/shade/renderer/extension/RenderExtension.d.ts +7 -0
- package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
- package/src/shade/renderer/extension/RenderExtension.js +9 -0
- package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts +6 -0
- package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts.map +1 -1
- package/src/shade/renderer/extension/RenderExtensionRegistry.js +15 -0
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +10 -3
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts.map +1 -1
- package/src/shade/renderer/fluid/GPUFluidCascade.js +15 -0
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +8 -1
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +11 -0
- package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.d.ts.map +1 -1
- package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.js +51 -48
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts +6 -0
- package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts.map +1 -1
- package/src/shade/renderer/fluid/mac/FluidMacPasses.js +16 -0
- package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.d.ts.map +1 -1
- package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.js +15 -3
- package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.d.ts.map +1 -1
- package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.js +102 -96
- package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +12 -12
- package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.js +12 -12
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +8 -1
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts.map +1 -1
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.js +16 -0
- package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts +7 -0
- package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts.map +1 -1
- package/src/shade/renderer/fluid/publish/FluidWindPublish.js +10 -0
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.js +2 -2
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +3 -3
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +350 -294
- package/src/shade/renderer/hiz/generate_downsampler_code.d.ts +0 -2
- package/src/shade/renderer/hiz/generate_downsampler_code.d.ts.map +1 -1
- package/src/shade/renderer/hiz/generate_downsampler_code.js +99 -100
- package/src/shade/renderer/hiz/hzb_pick_alignment.d.ts +15 -0
- package/src/shade/renderer/hiz/hzb_pick_alignment.d.ts.map +1 -0
- package/src/shade/renderer/hiz/hzb_pick_alignment.js +148 -0
- package/src/shade/renderer/hiz/hzb_plan_reduction_steps.d.ts +28 -0
- package/src/shade/renderer/hiz/hzb_plan_reduction_steps.d.ts.map +1 -0
- package/src/shade/renderer/hiz/hzb_plan_reduction_steps.js +58 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +5 -5
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +57 -67
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +3 -3
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +111 -112
- package/src/shade/renderer/hiz/shader_hzb_spd.d.ts +5 -0
- package/src/shade/renderer/hiz/shader_hzb_spd.d.ts.map +1 -0
- package/src/shade/renderer/hiz/shader_hzb_spd.js +160 -0
- package/src/shade/renderer/light/GPULightCollection.d.ts +8 -0
- package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
- package/src/shade/renderer/light/GPULightCollection.js +67 -0
- package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.d.ts +7 -0
- package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.js +13 -0
- package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.d.ts +10 -0
- package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.d.ts.map +1 -0
- package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.js +72 -0
- package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts +39 -0
- package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts.map +1 -0
- package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.js +90 -0
- package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts +12 -0
- package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts.map +1 -0
- package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.js +56 -0
- package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts +31 -0
- package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts.map +1 -0
- package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.js +196 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts +10 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts.map +1 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.js +163 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.d.ts +4 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.d.ts.map +1 -0
- package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.js +137 -0
- package/src/shade/renderer/loader/SceneBundle.d.ts +7 -0
- package/src/shade/renderer/loader/SceneBundle.d.ts.map +1 -1
- package/src/shade/renderer/loader/SceneBundle.js +119 -111
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +4 -0
- package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
- package/src/shade/renderer/material/standard/fragment_gbuffer.js +6 -5
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +8 -7
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +9 -8
- package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
- package/src/shade/renderer/particles/GPUParticleSystem.js +4 -1
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts +4 -3
- package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles_avboit.js +28 -11
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +9 -13
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +25 -20
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
- package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +22 -34
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +9 -7
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.js +15 -7
- package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +6 -4
- package/src/shade/renderer/rasterize/native/oit/oit_resolve_fragment_body.js +3 -3
- package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +8 -5
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +4 -3
- package/src/shade/renderer/shader/chunk/depth/chunk_query_depth_from_screen_space_bb.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/depth/chunk_query_depth_from_screen_space_bb.js +62 -62
- package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.d.ts +6 -0
- package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.js +19 -0
- package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_get_mip_resolution.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_get_mip_resolution.js +16 -10
- package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_hierarchical_raymarch.d.ts.map +1 -1
- package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_hierarchical_raymarch.js +118 -117
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1 -1
- package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts +9 -0
- package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts.map +1 -0
- package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.js +17 -0
- package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts +8 -0
- package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts.map +1 -1
- package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.js +28 -20
- package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts +8 -0
- package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts.map +1 -0
- package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.js +15 -0
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts +41 -7
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts.map +1 -1
- package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.js +162 -58
- package/src/shade/renderer/view/chunk_view_mip_bias.d.ts +21 -0
- package/src/shade/renderer/view/chunk_view_mip_bias.d.ts.map +1 -0
- package/src/shade/renderer/view/chunk_view_mip_bias.js +44 -0
- package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +10 -12
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +583 -606
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_sample.d.ts +24 -0
- package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_sample.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi_sample.d.ts.map +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +1 -1
- package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +640 -640
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +113 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +484 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts +50 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.js +60 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts +25 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.js +47 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.d.ts +74 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.js +173 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +26 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +83 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.d.ts +31 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.js +113 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.d.ts +121 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.js +356 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.d.ts +16 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.js +191 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_classify_froxels.d.ts +16 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_classify_froxels.d.ts.map +1 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_lighting_regimes.d.ts +23 -0
- package/src/shade/renderer/volumetrics/shader_volumetrics_lighting_regimes.d.ts.map +1 -0
- package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
- package/src/shade/renderer/wind/GPUSceneWind.js +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +105 -26
- package/src/engine/graphics/composit/CompositingStages.d.ts +0 -6
- package/src/engine/graphics/composit/CompositingStages.d.ts.map +0 -1
- package/src/engine/graphics/composit/CompositingStages.js +0 -8
- package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts +0 -7
- package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts.map +0 -1
- package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.js +0 -24
- package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts +0 -8
- package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts.map +0 -1
- package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.js +0 -17
- package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts +0 -8
- package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts.map +0 -1
- package/src/engine/graphics/geometry/buffered/computeGeometryEquality.js +0 -60
- package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts +0 -7
- package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts.map +0 -1
- package/src/engine/graphics/geometry/buffered/computeGeometryHash.js +0 -26
- package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts +0 -7
- package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts.map +0 -1
- package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.js +0 -23
- package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts +0 -7
- package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts.map +0 -1
- package/src/engine/graphics/geometry/instancing/geometry_copy.js +0 -15
- package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts +0 -2
- package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts.map +0 -1
- package/src/engine/graphics/geometry/instancing/rewriteMaterial.js +0 -57
- package/src/engine/graphics/geometry/ribbon/Quad.d.ts +0 -96
- package/src/engine/graphics/geometry/ribbon/Quad.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/Quad.js +0 -213
- package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts +0 -9
- package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/copyAttributeV3.js +0 -12
- package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts +0 -10
- package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/copyAttributeValue.js +0 -17
- package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts +0 -10
- package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/equalAttributeV3.js +0 -13
- package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts +0 -11
- package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/equalAttributeValue.js +0 -24
- package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts +0 -6
- package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/rotateRibbon.js +0 -37
- package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts +0 -9
- package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts.map +0 -1
- package/src/engine/graphics/geometry/ribbon/updateTipPosition.js +0 -52
- package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts +0 -8
- package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts.map +0 -1
- package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.js +0 -54
- package/src/engine/graphics/render/RenderPassType.d.ts +0 -6
- package/src/engine/graphics/render/RenderPassType.d.ts.map +0 -1
- package/src/engine/graphics/render/RenderPassType.js +0 -8
- package/src/engine/graphics/render/layers/RenderLayer.d.ts +0 -78
- package/src/engine/graphics/render/layers/RenderLayer.d.ts.map +0 -1
- package/src/engine/graphics/render/layers/RenderLayer.js +0 -95
- package/src/engine/graphics/render/layers/RenderLayerManager.d.ts +0 -72
- package/src/engine/graphics/render/layers/RenderLayerManager.d.ts.map +0 -1
- package/src/engine/graphics/render/layers/RenderLayerManager.js +0 -160
- package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts +0 -18
- package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts.map +0 -1
- package/src/engine/graphics/render/layers/RenderLayerManagerState.js +0 -48
- package/src/engine/graphics/render/layers/RenderLayerState.d.ts +0 -18
- package/src/engine/graphics/render/layers/RenderLayerState.d.ts.map +0 -1
- package/src/engine/graphics/render/layers/RenderLayerState.js +0 -27
- package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts +0 -8
- package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts.map +0 -1
- package/src/engine/graphics/render/layers/RenderLayerUtils.js +0 -103
- package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts +0 -10
- package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts.map +0 -1
- package/src/engine/graphics/render/make_bvh_visibility_builder.js +0 -64
- package/src/engine/graphics/render/view/CameraViewFlags.d.ts +0 -7
- package/src/engine/graphics/render/view/CameraViewFlags.d.ts.map +0 -1
- package/src/engine/graphics/render/view/CameraViewFlags.js +0 -9
- package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +0 -143
- package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts.map +0 -1
- package/src/engine/graphics/render/visibility/IncrementalDeltaSet.js +0 -328
- package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts +0 -39
- package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts.map +0 -1
- package/src/engine/graphics/render/visibility/VisibilityComputer.js +0 -80
- package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts +0 -29
- package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts.map +0 -1
- package/src/engine/graphics/render/visibility/VisibilityFilter.js +0 -37
- package/src/engine/graphics3/animation/write_graph_playback.d.ts +0 -24
- package/src/engine/graphics3/animation/write_graph_playback.d.ts.map +0 -1
- package/src/engine/graphics3/animation/write_graph_playback.js +0 -48
- package/src/engine/graphics3/decal/DecalAtlasFill.js +0 -32
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.js +0 -49
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +0 -50
- package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi_sample.js +0 -105
- package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +0 -80
- package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi.js +0 -51
- package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.js +0 -39
- package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +0 -121
- package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.js +0 -237
|
@@ -1,949 +1,904 @@
|
|
|
1
|
-
import { assert } from "../../core/assert.js";
|
|
2
|
-
import { warn_limited } from "../../shade/util/warn_limited.js";
|
|
3
|
-
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
4
|
-
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
5
|
-
import { ParticleEmitter } from "../../shade/renderer/particles/runtime/ParticleEmitter.js";
|
|
6
|
-
import { GPUTextureContext } from "../../shade/renderer/texture/GPUTextureContext.js";
|
|
7
|
-
import { System } from "../ecs/System.js";
|
|
8
|
-
import Name from "../ecs/name/Name.js";
|
|
9
|
-
import { Transform64 } from "../ecs/transform/Transform64.js";
|
|
10
|
-
import { TRANSFORM64_EVENT_CHANGE } from "../ecs/transform/TRANSFORM64_EVENT_CHANGE.js";
|
|
11
|
-
import { row_of_entity } from "../../shade/renderer/scene/rows/GPUSceneRows.js";
|
|
12
|
-
import { GameAssetType } from "../asset/GameAssetType.js";
|
|
13
|
-
import { ImageRGBADataLoader } from "../asset/loaders/image/ImageRGBADataLoader.js";
|
|
14
|
-
import { ParticleEffect } from "../graphics/ecs/particles/ParticleEffect.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* @
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* @
|
|
35
|
-
* @property {
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* @property {
|
|
39
|
-
* @property {
|
|
40
|
-
*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
* @param {import("
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
this.#
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* @
|
|
205
|
-
*
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
* @param {number}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
* @
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
this.#extension
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
this.#texture
|
|
299
|
-
this.#
|
|
300
|
-
this.#
|
|
301
|
-
this.#
|
|
302
|
-
this.#
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this.#
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
* @param {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
transform
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
* @param {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
this.#
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
*
|
|
388
|
-
*
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
this.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
The
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this.#
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
this.#
|
|
461
|
-
|
|
462
|
-
this.#
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
region[
|
|
526
|
-
region[
|
|
527
|
-
|
|
528
|
-
region[
|
|
529
|
-
|
|
530
|
-
region[
|
|
531
|
-
region[
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
*
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
*
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
//
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
*
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
*
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
white.
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
if (emitter.render_frame !== effect.render_frame) {
|
|
907
|
-
emitter.render_frame = effect.render_frame;
|
|
908
|
-
changed = true;
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
if (emitter.render_velocity !== effect.render_velocity) {
|
|
912
|
-
emitter.render_velocity = effect.render_velocity;
|
|
913
|
-
changed = true;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
const flipbook = emitter.flipbook;
|
|
917
|
-
|
|
918
|
-
if (flipbook[0] !== effect.flipbook[0] || flipbook[1] !== effect.flipbook[1]) {
|
|
919
|
-
flipbook.set(effect.flipbook);
|
|
920
|
-
|
|
921
|
-
changed = true;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
return changed;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
class GPUParticleAtlasExtension extends RenderExtension {
|
|
928
|
-
/** @type {string} */
|
|
929
|
-
name = "gpu particle atlas";
|
|
930
|
-
/** @type {FramePhase} */
|
|
931
|
-
phase = FramePhase.FrameStart;
|
|
932
|
-
/** @type {GPUParticleEmitterSystem} */
|
|
933
|
-
#system;
|
|
934
|
-
|
|
935
|
-
/** @param {GPUParticleEmitterSystem} system */
|
|
936
|
-
constructor(system) {
|
|
937
|
-
super();
|
|
938
|
-
|
|
939
|
-
this.#system = system;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
944
|
-
* @returns {void}
|
|
945
|
-
*/
|
|
946
|
-
record(frame) {
|
|
947
|
-
this.#system.prepare(frame);
|
|
948
|
-
}
|
|
949
|
-
}
|
|
1
|
+
import { assert } from "../../core/assert.js";
|
|
2
|
+
import { warn_limited } from "../../shade/util/warn_limited.js";
|
|
3
|
+
import { FramePhase } from "../../shade/renderer/extension/FramePhase.js";
|
|
4
|
+
import { RenderExtension } from "../../shade/renderer/extension/RenderExtension.js";
|
|
5
|
+
import { ParticleEmitter } from "../../shade/renderer/particles/runtime/ParticleEmitter.js";
|
|
6
|
+
import { GPUTextureContext } from "../../shade/renderer/texture/GPUTextureContext.js";
|
|
7
|
+
import { System } from "../ecs/System.js";
|
|
8
|
+
import Name from "../ecs/name/Name.js";
|
|
9
|
+
import { Transform64 } from "../ecs/transform/Transform64.js";
|
|
10
|
+
import { TRANSFORM64_EVENT_CHANGE } from "../ecs/transform/TRANSFORM64_EVENT_CHANGE.js";
|
|
11
|
+
import { row_of_entity } from "../../shade/renderer/scene/rows/GPUSceneRows.js";
|
|
12
|
+
import { GameAssetType } from "../asset/GameAssetType.js";
|
|
13
|
+
import { ImageRGBADataLoader } from "../asset/loaders/image/ImageRGBADataLoader.js";
|
|
14
|
+
import { ParticleEffect } from "../graphics/ecs/particles/ParticleEffect.js";
|
|
15
|
+
import { ManagedAtlas } from "../graphics/texture/atlas/ManagedTextureAtlas.js";
|
|
16
|
+
import { SpriteAtlas } from "../graphics/texture/atlas/SpriteAtlas.js";
|
|
17
|
+
import { SpriteAtlasFill } from "../graphics/texture/atlas/SpriteAtlasFill.js";
|
|
18
|
+
import { TextureFilterType } from "../../shade/renderer/texture/TextureFilterType.js";
|
|
19
|
+
import { Sampler2D } from "../graphics/texture/sampler/Sampler2D.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Bursts {@link GPUParticleEmitterSystem#burst} will hold before it starts dropping them. Reached
|
|
23
|
+
* only when frames have stopped arriving — see the call site.
|
|
24
|
+
*
|
|
25
|
+
* @type {number}
|
|
26
|
+
*/
|
|
27
|
+
const BURST_QUEUE_LIMIT = 256;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {object} ParticleEmitterEntry
|
|
31
|
+
* @property {number} entity
|
|
32
|
+
* @property {ParticleEffect} effect the entity's component — what to emit
|
|
33
|
+
* @property {Transform64} transform the entity's transform — where to emit it
|
|
34
|
+
* @property {ParticleEmitter|null} emitter the emitter, once the effect has a program to run
|
|
35
|
+
* @property {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext|null} context
|
|
36
|
+
* the scene context the emitter is registered with, at the entity's row; null until a frame has
|
|
37
|
+
* registered it, or after a device restart took that context away
|
|
38
|
+
* @property {function():void} on_transform_changed
|
|
39
|
+
* @property {string|null} url last observed {@link ParticleEffect#texture}
|
|
40
|
+
* @property {import("../graphics/texture/atlas/ManagedTextureAtlas.js").ManagedAtlasReference|null} texture shared image reference, or null for an untextured effect
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Draws the game's GPU particle effects: one emitter per entity carrying
|
|
45
|
+
* {@link ../graphics/ecs/particles/ParticleEffect.js ParticleEffect} and
|
|
46
|
+
* {@link ../ecs/transform/Transform64.js Transform64}.
|
|
47
|
+
*
|
|
48
|
+
* ```js
|
|
49
|
+
* entityManager.addSystem(new GPUParticleEmitterSystem(graphics, scene, assetManager));
|
|
50
|
+
*
|
|
51
|
+
* new Entity()
|
|
52
|
+
* .add(new Transform64())
|
|
53
|
+
* .add(ParticleEffect.from({ ...create_particle_effect({ layout, init, update }), spawn_rate: 400 }))
|
|
54
|
+
* .build(dataset);
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* **The entity is the emitter.** The component says what it emits and the transform says where, the
|
|
58
|
+
* same division every other placed thing in this engine uses — a `Decal`, an `SGMesh`, a `Light`.
|
|
59
|
+
* Which means an emitter is spawned, moved, parented, attached to a bone, saved and destroyed by
|
|
60
|
+
* exactly the machinery that does those things for everything else, and a particle effect stops
|
|
61
|
+
* being a special case that needs its own scene-graph call.
|
|
62
|
+
*
|
|
63
|
+
* ## What this system does with the pair
|
|
64
|
+
*
|
|
65
|
+
* It builds a {@link ParticleEmitter} per entity and owns it: the emitter is registered with the
|
|
66
|
+
* scene's particle system at the entity's row when the component has a compiled effect, so it
|
|
67
|
+
* stands where the entity stands, carries whatever the component currently says, and is retired
|
|
68
|
+
* when the entity goes. The emitter is not hidden — {@link emitter_of} hands it out — but it is
|
|
69
|
+
* not the interface either: write to the component and the next frame carries it.
|
|
70
|
+
*
|
|
71
|
+
* Changes are found by **comparison** rather than announced. Once a frame each entity's
|
|
72
|
+
* fields are compared against what was last written to its emitter, and the emitter is marked dirty only
|
|
73
|
+
* where they differ; `EmitterRegistry` then restages exactly the rows that moved. A component nobody
|
|
74
|
+
* touched costs a run of integer comparisons and no upload, so there is no change signal to fire and
|
|
75
|
+
* none to forget. What that buys is that gameplay can write `effect.spawn_rate = 0` anywhere,
|
|
76
|
+
* including from code that has never heard of this system.
|
|
77
|
+
*
|
|
78
|
+
* ## It owns the scene's sprite atlas
|
|
79
|
+
*
|
|
80
|
+
* Every {@link ParticleEffect#texture} is loaded through the supplied `AssetManager` and packed into
|
|
81
|
+
* one {@link SpriteAtlas} shared by the scene, one patch per distinct URL however many entities
|
|
82
|
+
* name it, reference-counted through {@link ManagedAtlas} so unreferenced sprites remain in the
|
|
83
|
+
* atlas graveyard and are only reaped when incoming sprites need the space. A `FrameStart`
|
|
84
|
+
* extension publishes the pixels and every current patch region before the renderer records the
|
|
85
|
+
* particle passes — every repack moves UVs that nothing else changed, so the regions are rewritten
|
|
86
|
+
* whole rather than when a URL changes. Pending and failed images sample a transparent texel;
|
|
87
|
+
* effects with no image sample a white one.
|
|
88
|
+
*
|
|
89
|
+
* An emitter in this scene that this system did not build — one registered with the particle
|
|
90
|
+
* system directly — gets the white texel. The atlas is the scene's and that emitter has nothing in
|
|
91
|
+
* it, so the alternative is not "its own texture" but a UV rectangle from somebody else's image.
|
|
92
|
+
*
|
|
93
|
+
* ## What it is not
|
|
94
|
+
*
|
|
95
|
+
* It does not simulate anything and does not record a particle pass. `GPUParticleSystem` does both,
|
|
96
|
+
* inside the renderer, driven from the emitter table these rows are in — see
|
|
97
|
+
* `shade/renderer/particles/DESIGN.md`. This system's whole contribution is membership, placement,
|
|
98
|
+
* the fields, and the sprite sheet.
|
|
99
|
+
*/
|
|
100
|
+
export class GPUParticleEmitterSystem extends System {
|
|
101
|
+
dependencies = [ParticleEffect, Transform64];
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* CPU atlas, exposed for inspection. Owned by this system.
|
|
105
|
+
* @type {SpriteAtlas}
|
|
106
|
+
*/
|
|
107
|
+
atlas = new SpriteAtlas(SpriteAtlasFill.EdgeExtend, 64);
|
|
108
|
+
|
|
109
|
+
/** @type {import("./GraphicsEngine.js").GraphicsEngine} */
|
|
110
|
+
#graphics;
|
|
111
|
+
/** @type {import("../../shade/renderer/scene/Scene.js").Scene} */
|
|
112
|
+
#scene;
|
|
113
|
+
/** @type {import("../asset/AssetManager.js").AssetManager} */
|
|
114
|
+
#assets;
|
|
115
|
+
/** @type {Map<number, ParticleEmitterEntry>} */
|
|
116
|
+
#entries = new Map();
|
|
117
|
+
/**
|
|
118
|
+
* The same entries by the emitter they own, so that the emitters this system did not build can
|
|
119
|
+
* be told apart from the ones it did without a linear search per emitter per frame.
|
|
120
|
+
* @type {Map<ParticleEmitter, ParticleEmitterEntry>}
|
|
121
|
+
*/
|
|
122
|
+
#by_emitter = new Map();
|
|
123
|
+
/** @type {ManagedAtlas} */
|
|
124
|
+
#managed_atlas;
|
|
125
|
+
/**
|
|
126
|
+
* Bursts asked for through {@link burst} and not yet handed to the particle system. Flat pairs
|
|
127
|
+
* of `entity, count`, drained every frame.
|
|
128
|
+
* @type {number[]}
|
|
129
|
+
*/
|
|
130
|
+
#bursts = [];
|
|
131
|
+
/** @type {import("../graphics/texture/atlas/AtlasPatch.js").AtlasPatch} */
|
|
132
|
+
#white;
|
|
133
|
+
/** @type {import("../graphics/texture/atlas/AtlasPatch.js").AtlasPatch} */
|
|
134
|
+
#transparent;
|
|
135
|
+
/** @type {GPUParticleAtlasExtension|null} */
|
|
136
|
+
#extension = null;
|
|
137
|
+
/** @type {GPUTextureContext|null} */
|
|
138
|
+
#texture = null;
|
|
139
|
+
/** @type {GPUTextureView|null} */
|
|
140
|
+
#view = null;
|
|
141
|
+
/** @type {GPUDevice|null} */
|
|
142
|
+
#device = null;
|
|
143
|
+
/** @type {number} */
|
|
144
|
+
#uploaded_version = -1;
|
|
145
|
+
/** @type {import("../../shade/renderer/particles/GPUParticleSystem.js").GPUParticleSystem|null} */
|
|
146
|
+
#particles = null;
|
|
147
|
+
/** @type {GPUTextureView|null} */
|
|
148
|
+
#previous_atlas = null;
|
|
149
|
+
/** @type {Float32Array} */
|
|
150
|
+
#region = new Float32Array(4);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @param {import("./GraphicsEngine.js").GraphicsEngine} graphics
|
|
154
|
+
* @param {import("../../shade/renderer/scene/Scene.js").Scene} scene scene the emitters are put
|
|
155
|
+
* in, and whose particle atlas this system owns
|
|
156
|
+
* @param {import("../asset/AssetManager.js").AssetManager} assets
|
|
157
|
+
*/
|
|
158
|
+
constructor(graphics, scene, assets) {
|
|
159
|
+
super();
|
|
160
|
+
|
|
161
|
+
assert.defined(graphics, "graphics");
|
|
162
|
+
assert.equal(scene.isScene, true, "scene.isScene !== true");
|
|
163
|
+
assert.defined(assets, "assets");
|
|
164
|
+
|
|
165
|
+
this.#graphics = graphics;
|
|
166
|
+
this.#scene = scene;
|
|
167
|
+
this.#assets = assets;
|
|
168
|
+
this.#managed_atlas = new ManagedAtlas({
|
|
169
|
+
assetManager: this.#assets,
|
|
170
|
+
atlas: this.atlas
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
this.#create_defaults();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The scene the emitters are put in. Received rather than created: meshes and lights come from
|
|
178
|
+
* systems of their own, and all of them have to be writing into one scene for any of it to be
|
|
179
|
+
* visible together.
|
|
180
|
+
*
|
|
181
|
+
* @returns {import("../../shade/renderer/scene/Scene.js").Scene}
|
|
182
|
+
*/
|
|
183
|
+
get scene() {
|
|
184
|
+
return this.#scene;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The emitters this system currently holds, in no particular order. Read-only — they follow
|
|
189
|
+
* the entities.
|
|
190
|
+
*
|
|
191
|
+
* @returns {ParticleEmitter[]}
|
|
192
|
+
*/
|
|
193
|
+
get emitters() {
|
|
194
|
+
return Array.from(this.#by_emitter.keys());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The emitter built for an entity.
|
|
199
|
+
*
|
|
200
|
+
* Handed out for what an entity reference cannot express — asking the particle system about
|
|
201
|
+
* it — and for nothing routine: the component is how an effect is changed, and an emitter
|
|
202
|
+
* written to behind the component's back is overwritten by the next comparison.
|
|
203
|
+
*
|
|
204
|
+
* @param {number} entity
|
|
205
|
+
* @returns {ParticleEmitter|null} `null` for an entity this system has not linked, or one whose
|
|
206
|
+
* component has no compiled effect yet
|
|
207
|
+
*/
|
|
208
|
+
emitter_of(entity) {
|
|
209
|
+
const entry = this.#entries.get(entity);
|
|
210
|
+
|
|
211
|
+
if (entry === undefined) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return entry.emitter;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Ask an entity's emitter for `count` particles on top of its rate, on the next frame.
|
|
220
|
+
*
|
|
221
|
+
* The one-shot half of the API, and the only thing here the CPU asks for rather than describes:
|
|
222
|
+
* an impact, a footfall, a muzzle flash. It goes through the same GPU path as continuous
|
|
223
|
+
* emission — the tick pass folds the burst into the emitter's accumulator, and the pool budget
|
|
224
|
+
* and the culling apply — so it is a request rather than a guarantee, and an entity whose
|
|
225
|
+
* emitter is not live by the time the frame starts is silently skipped.
|
|
226
|
+
*
|
|
227
|
+
* @param {number} entity
|
|
228
|
+
* @param {number} count
|
|
229
|
+
*/
|
|
230
|
+
burst(entity, count) {
|
|
231
|
+
assert.isNonNegativeInteger(count, "count");
|
|
232
|
+
|
|
233
|
+
if (count === 0) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (this.#bursts.length >= BURST_QUEUE_LIMIT * 2) {
|
|
238
|
+
/*
|
|
239
|
+
The queue is drained by a frame, so it only grows without bound when frames have stopped
|
|
240
|
+
arriving — a scene nobody draws, or a device that never came up — and gameplay carries on
|
|
241
|
+
asking. Dropping is right either way: nothing is going to spawn these, and a burst is a
|
|
242
|
+
request about the moment it was made.
|
|
243
|
+
|
|
244
|
+
The text is the key `warn_limited` counts on, so it carries no entity: one message per
|
|
245
|
+
limit, not one per caller that happens to be unlucky.
|
|
246
|
+
*/
|
|
247
|
+
warn_limited(
|
|
248
|
+
`GPUParticleEmitterSystem: ${BURST_QUEUE_LIMIT} bursts are queued and no frame has `
|
|
249
|
+
+ "drained them; dropping the rest"
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
this.#bursts.push(entity, count);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {import("../ecs/EntityManager.js").EntityManager} entityManager
|
|
260
|
+
* @returns {Promise<void>}
|
|
261
|
+
*/
|
|
262
|
+
async startup(entityManager) {
|
|
263
|
+
this.entityManager = entityManager;
|
|
264
|
+
|
|
265
|
+
// the scene's rows are this dataset's entities; the first system to place one says so
|
|
266
|
+
const dataset = entityManager.dataset;
|
|
267
|
+
const scene = this.#scene;
|
|
268
|
+
|
|
269
|
+
assert.ok(
|
|
270
|
+
scene.dataset === null || scene.dataset === undefined || scene.dataset === dataset,
|
|
271
|
+
'the scene is bound to another dataset'
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
scene.dataset = dataset;
|
|
275
|
+
|
|
276
|
+
if (!this.#assets.hasLoaderForType(GameAssetType.Image)) {
|
|
277
|
+
await this.#assets.registerLoader(GameAssetType.Image, new ImageRGBADataLoader());
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.#extension = new GPUParticleAtlasExtension(this);
|
|
281
|
+
|
|
282
|
+
this.#graphics.add_extension(this.#extension);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** @returns {Promise<void>} */
|
|
286
|
+
async shutdown() {
|
|
287
|
+
if (this.#extension !== null) {
|
|
288
|
+
this.#graphics.remove_extension(this.#extension);
|
|
289
|
+
this.#extension = null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
for (const entity of Array.from(this.#entries.keys())) {
|
|
293
|
+
this.#drop(entity);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
this.#detach();
|
|
297
|
+
|
|
298
|
+
this.#texture?.destroy();
|
|
299
|
+
this.#texture = null;
|
|
300
|
+
this.#view = null;
|
|
301
|
+
this.#device = null;
|
|
302
|
+
this.#uploaded_version = -1;
|
|
303
|
+
this.#bursts.length = 0;
|
|
304
|
+
|
|
305
|
+
this.#managed_atlas.reset();
|
|
306
|
+
this.#create_defaults();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @param {ParticleEffect} effect
|
|
311
|
+
* @param {Transform64} transform
|
|
312
|
+
* @param {number} entity
|
|
313
|
+
*/
|
|
314
|
+
link(effect, transform, entity) {
|
|
315
|
+
/** @type {ParticleEmitterEntry} */
|
|
316
|
+
const entry = {
|
|
317
|
+
entity,
|
|
318
|
+
effect,
|
|
319
|
+
transform,
|
|
320
|
+
emitter: null,
|
|
321
|
+
context: null,
|
|
322
|
+
on_transform_changed: null,
|
|
323
|
+
url: null,
|
|
324
|
+
texture: null
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
this.#entries.set(entity, entry);
|
|
328
|
+
|
|
329
|
+
/*
|
|
330
|
+
The emitter is placed the moment its transform moves rather than on a poll. A Transform64
|
|
331
|
+
has no signals of its own, so the announcement comes from the dataset: whoever wrote the
|
|
332
|
+
transform sends TRANSFORM64_EVENT_CHANGE and this wakes on it. Coarser than watching
|
|
333
|
+
position, rotation and scale separately — a scale write wakes a placement that reads the
|
|
334
|
+
whole transform anyway — and that is the trade the type makes everywhere.
|
|
335
|
+
*/
|
|
336
|
+
entry.on_transform_changed = () => this.#place(entry);
|
|
337
|
+
|
|
338
|
+
this.entityManager.dataset.addEntityEventListener(
|
|
339
|
+
entity, TRANSFORM64_EVENT_CHANGE, entry.on_transform_changed
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
// Everything else — building the emitter, acquiring the texture — is what a frame does
|
|
343
|
+
// anyway, and doing it here as well would be a second copy of it that has to stay in step.
|
|
344
|
+
this.#sync(entry);
|
|
345
|
+
|
|
346
|
+
// Registered now when there is a context to register with, so an entity spawned mid-level
|
|
347
|
+
// stands where it should from its first frame.
|
|
348
|
+
this.#register_all();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* @param {ParticleEffect} effect
|
|
353
|
+
* @param {Transform64} transform
|
|
354
|
+
* @param {number} entity
|
|
355
|
+
*/
|
|
356
|
+
unlink(effect, transform, entity) {
|
|
357
|
+
this.#drop(entity);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Bring every emitter in line with its entity: build emitters for effects that have arrived,
|
|
362
|
+
* retire emitters for effects that have gone, copy changed fields onto the ones that stay, and
|
|
363
|
+
* follow the texture URLs.
|
|
364
|
+
*
|
|
365
|
+
* @param {number} [time_delta_seconds]
|
|
366
|
+
* @returns {void}
|
|
367
|
+
*/
|
|
368
|
+
update(time_delta_seconds) {
|
|
369
|
+
for (const entry of this.#entries.values()) {
|
|
370
|
+
this.#sync(entry);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/*
|
|
374
|
+
Registered here as well as at FrameStart, so an emitter whose effect arrived during a
|
|
375
|
+
simulation tick has its row written by the next frame's build rather than the one after:
|
|
376
|
+
a frame builds the scene context before FrameStart runs, so a row acquired at FrameStart
|
|
377
|
+
is not written until the frame after.
|
|
378
|
+
*/
|
|
379
|
+
this.#register_all();
|
|
380
|
+
|
|
381
|
+
this.#managed_atlas.update();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* The particle system a scene context's frames run, or null while there is no renderer.
|
|
386
|
+
*
|
|
387
|
+
* @param {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext} context
|
|
388
|
+
* @returns {import("../../shade/renderer/particles/GPUParticleSystem.js").GPUParticleSystem|null}
|
|
389
|
+
*/
|
|
390
|
+
#particles_of(context) {
|
|
391
|
+
const renderer = this.#graphics.renderer;
|
|
392
|
+
|
|
393
|
+
if (renderer === null || renderer === undefined) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return renderer.particles(context);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* {@link #register} against whatever context and particle system the scene has right now, if
|
|
402
|
+
* it has any.
|
|
403
|
+
*/
|
|
404
|
+
#register_all() {
|
|
405
|
+
const context = this.#graphics.scene_context(this.#scene);
|
|
406
|
+
|
|
407
|
+
if (context === null) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const particles = this.#particles_of(context);
|
|
412
|
+
|
|
413
|
+
if (particles !== null) {
|
|
414
|
+
this.#register(particles, context);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Publish the atlas at FrameStart — after the scene context has established transform rows, and
|
|
420
|
+
* before the renderer records the particle passes that read the emitter table.
|
|
421
|
+
*
|
|
422
|
+
* {@link update} is called from here as well as by the entity manager, because a frame must not
|
|
423
|
+
* depend on a simulation tick having preceded it: an editor draws on demand, and a paused game
|
|
424
|
+
* still renders. It is idempotent and costs a comparison per emitter when nothing has changed,
|
|
425
|
+
* which is what makes running it twice a frame the cheap way to be right rather than a saving
|
|
426
|
+
* worth chasing.
|
|
427
|
+
*
|
|
428
|
+
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
429
|
+
* @returns {void}
|
|
430
|
+
*/
|
|
431
|
+
prepare(frame) {
|
|
432
|
+
if (frame.view.scene.scene !== this.#scene) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
this.update();
|
|
437
|
+
|
|
438
|
+
const renderer = this.#graphics.renderer;
|
|
439
|
+
|
|
440
|
+
/*
|
|
441
|
+
The renderer's GPU particle feature is this system's to turn on, and it is turned on every
|
|
442
|
+
frame rather than once, because a device restart builds a renderer that has never heard of
|
|
443
|
+
it. The consequence is worth stating: while this system is in the profile there is no way to
|
|
444
|
+
switch GPU particles off through the renderer, because this would switch them back on at the
|
|
445
|
+
next FrameStart. Switching them off means taking the system out — or, for one effect,
|
|
446
|
+
`ParticleEffect#emitting`.
|
|
447
|
+
*/
|
|
448
|
+
renderer.feature_particles_enabled = true;
|
|
449
|
+
|
|
450
|
+
const particles = renderer.particles(frame.view.scene);
|
|
451
|
+
|
|
452
|
+
if (particles !== this.#particles) {
|
|
453
|
+
this.#detach();
|
|
454
|
+
this.#particles = particles;
|
|
455
|
+
this.#previous_atlas = particles.atlas;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
this.#register(particles, frame.view.scene);
|
|
459
|
+
|
|
460
|
+
this.#upload(renderer.graphics);
|
|
461
|
+
|
|
462
|
+
particles.atlas = this.#view;
|
|
463
|
+
|
|
464
|
+
this.#publish_regions(particles);
|
|
465
|
+
this.#drain_bursts(particles);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Register every emitter not yet registered with this context, at its entity's row.
|
|
470
|
+
*
|
|
471
|
+
* From {@link update} and {@link prepare} rather than at link, because a row needs a scene
|
|
472
|
+
* context and the context needs a device, and neither is a system's to wait for: a level loads
|
|
473
|
+
* before the device is up, and a device restart replaces the context under every entry. An
|
|
474
|
+
* entry registered with a context that is no longer this one is registered again with the one
|
|
475
|
+
* that is. Idempotent, and a comparison per entry when nothing has changed.
|
|
476
|
+
*
|
|
477
|
+
* @param {import("../../shade/renderer/particles/GPUParticleSystem.js").GPUParticleSystem} particles
|
|
478
|
+
* @param {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext} scene_context
|
|
479
|
+
*/
|
|
480
|
+
#register(particles, scene_context) {
|
|
481
|
+
const rows = scene_context.rows;
|
|
482
|
+
|
|
483
|
+
for (const entry of this.#entries.values()) {
|
|
484
|
+
if (entry.emitter === null || entry.context === scene_context) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
rows.acquire(entry.entity);
|
|
489
|
+
|
|
490
|
+
particles.add_emitter(entry.emitter, row_of_entity(entry.entity));
|
|
491
|
+
|
|
492
|
+
entry.context = scene_context;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Point every emitter of this scene at its patch in the atlas.
|
|
498
|
+
*
|
|
499
|
+
* Every region, every frame: growth also moves the UVs of images that did not change, and there
|
|
500
|
+
* is no signal for that which an emitter could subscribe to.
|
|
501
|
+
*
|
|
502
|
+
* @param {import("../../shade/renderer/particles/GPUParticleSystem.js").GPUParticleSystem} particles
|
|
503
|
+
*/
|
|
504
|
+
#publish_regions(particles) {
|
|
505
|
+
const registry = particles.registry;
|
|
506
|
+
const emitters = registry.emitters;
|
|
507
|
+
const region = this.#region;
|
|
508
|
+
|
|
509
|
+
for (let i = 0; i < emitters.length; i++) {
|
|
510
|
+
const emitter = emitters[i];
|
|
511
|
+
const entry = this.#by_emitter.get(emitter);
|
|
512
|
+
|
|
513
|
+
// Not ours: it has nothing in this atlas, so it gets the one patch that is true for
|
|
514
|
+
// everybody — a white texel, which draws it as a flat quad of its own colour.
|
|
515
|
+
const patch = entry === undefined || entry.texture === null
|
|
516
|
+
? this.#white
|
|
517
|
+
: entry.texture.getValue() ?? this.#transparent;
|
|
518
|
+
|
|
519
|
+
const uv = patch.uv;
|
|
520
|
+
|
|
521
|
+
if (patch === this.#white || patch === this.#transparent) {
|
|
522
|
+
// Sample the texel centre everywhere, avoiding interpolation into the gutter.
|
|
523
|
+
region[0] = uv.position.x + uv.size.x * 0.5;
|
|
524
|
+
region[1] = uv.position.y + uv.size.y * 0.5;
|
|
525
|
+
region[2] = 0;
|
|
526
|
+
region[3] = 0;
|
|
527
|
+
} else {
|
|
528
|
+
region[0] = uv.position.x;
|
|
529
|
+
region[1] = uv.position.y;
|
|
530
|
+
region[2] = uv.size.x;
|
|
531
|
+
region[3] = uv.size.y;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
registry.set_atlas_region(emitter, region);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Hand this frame's bursts to the particle system, now that membership has been swept and every
|
|
540
|
+
* emitter that can have a row has one.
|
|
541
|
+
*
|
|
542
|
+
* The queue is emptied whether or not each burst could be delivered. A burst is a request about
|
|
543
|
+
* *this* moment — a footfall, an impact — and holding one for an emitter that is not live yet
|
|
544
|
+
* would deliver it seconds late, at whatever unrelated moment the emitter finally arrived.
|
|
545
|
+
*
|
|
546
|
+
* @param {import("../../shade/renderer/particles/GPUParticleSystem.js").GPUParticleSystem} particles
|
|
547
|
+
*/
|
|
548
|
+
#drain_bursts(particles) {
|
|
549
|
+
const bursts = this.#bursts;
|
|
550
|
+
|
|
551
|
+
for (let i = 0; i < bursts.length; i += 2) {
|
|
552
|
+
const entry = this.#entries.get(bursts[i]);
|
|
553
|
+
|
|
554
|
+
if (entry === undefined || entry.emitter === null) {
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
if (particles.registry.context(entry.emitter) === undefined) {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
particles.spawn(entry.emitter, bursts[i + 1]);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
bursts.length = 0;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* One entity's emitter, brought in line with its component.
|
|
570
|
+
*
|
|
571
|
+
* @param {ParticleEmitterEntry} entry
|
|
572
|
+
*/
|
|
573
|
+
#sync(entry) {
|
|
574
|
+
const effect = entry.effect;
|
|
575
|
+
|
|
576
|
+
/*
|
|
577
|
+
Ahead of everything the effect gates, and deliberately: an image takes a fetch and a decode
|
|
578
|
+
to arrive, and an entity that names one has said what it wants to draw with whether or not
|
|
579
|
+
its program has finished compiling. Waiting would mean a first frame of transparent
|
|
580
|
+
particles for every effect that arrives with its texture.
|
|
581
|
+
*/
|
|
582
|
+
if (entry.url !== effect.texture) {
|
|
583
|
+
entry.texture?.release();
|
|
584
|
+
|
|
585
|
+
entry.url = effect.texture;
|
|
586
|
+
entry.texture = entry.url === null ? null : this.#managed_atlas.acquire(entry.url);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (effect.layout === null || effect.program === null) {
|
|
590
|
+
// No effect (yet, or any more). An entity whose effect is still compiling is ordinary,
|
|
591
|
+
// and so is one whose effect was cleared — both mean "emits nothing", and the emitter
|
|
592
|
+
// is retired rather than keeping the last program it happened to have.
|
|
593
|
+
this.#detach_emitter(entry);
|
|
594
|
+
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (entry.emitter === null) {
|
|
599
|
+
const emitter = new ParticleEmitter();
|
|
600
|
+
|
|
601
|
+
/*
|
|
602
|
+
The emitter takes the entity's name when it has one, exactly as `ShadedGeometrySystem`
|
|
603
|
+
does for a primitive. Nothing draws differently for it: what it buys is that a walk over
|
|
604
|
+
the registry is readable in a debugger.
|
|
605
|
+
*/
|
|
606
|
+
const name = this.entityManager.dataset.getComponent(entry.entity, Name);
|
|
607
|
+
|
|
608
|
+
emitter.name = name === undefined || name === null
|
|
609
|
+
? `particles/entity ${entry.entity}`
|
|
610
|
+
: name.getValue();
|
|
611
|
+
|
|
612
|
+
entry.emitter = emitter;
|
|
613
|
+
|
|
614
|
+
apply_particle_effect(emitter, effect);
|
|
615
|
+
|
|
616
|
+
// registered at the entity's row by the next frame — see #register
|
|
617
|
+
this.#by_emitter.set(emitter, entry);
|
|
618
|
+
} else if (apply_particle_effect(entry.emitter, effect)) {
|
|
619
|
+
// The emitter's own change counter, which is what EmitterRegistry restages a row from.
|
|
620
|
+
entry.emitter.needsUpdate = true;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* The entity moved: its row is rewritten from its transform by the context that holds it.
|
|
626
|
+
*
|
|
627
|
+
* @param {ParticleEmitterEntry} entry
|
|
628
|
+
*/
|
|
629
|
+
#place(entry) {
|
|
630
|
+
const context = entry.context;
|
|
631
|
+
|
|
632
|
+
if (context === null || context !== this.#graphics.scene_context(this.#scene)) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
context.rows.mark_world(entry.entity);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Retire an entity's emitter and let go of its row, leaving the entry linked.
|
|
641
|
+
*
|
|
642
|
+
* @param {ParticleEmitterEntry} entry
|
|
643
|
+
*/
|
|
644
|
+
#detach_emitter(entry) {
|
|
645
|
+
const emitter = entry.emitter;
|
|
646
|
+
|
|
647
|
+
if (emitter === null) {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const context = entry.context;
|
|
652
|
+
|
|
653
|
+
// A context that has been replaced took its rows and its particle system with it; only the
|
|
654
|
+
// one that is running is handed anything back.
|
|
655
|
+
if (context !== null && context === this.#graphics.scene_context(this.#scene)) {
|
|
656
|
+
const particles = this.#particles_of(context);
|
|
657
|
+
|
|
658
|
+
if (particles !== null && particles.registry.context(emitter) !== undefined) {
|
|
659
|
+
particles.remove_emitter(emitter);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
context.rows.release(entry.entity);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
entry.context = null;
|
|
666
|
+
|
|
667
|
+
this.#by_emitter.delete(emitter);
|
|
668
|
+
|
|
669
|
+
entry.emitter = null;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* @param {number} entity
|
|
674
|
+
*/
|
|
675
|
+
#drop(entity) {
|
|
676
|
+
const entry = this.#entries.get(entity);
|
|
677
|
+
|
|
678
|
+
if (entry === undefined) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (entry.on_transform_changed !== null) {
|
|
683
|
+
this.entityManager.dataset.removeEntityEventListener(
|
|
684
|
+
entity, TRANSFORM64_EVENT_CHANGE, entry.on_transform_changed
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
entry.on_transform_changed = null;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
this.#detach_emitter(entry);
|
|
691
|
+
entry.texture?.release();
|
|
692
|
+
|
|
693
|
+
entry.url = null;
|
|
694
|
+
entry.texture = null;
|
|
695
|
+
|
|
696
|
+
this.#entries.delete(entity);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/** @returns {void} */
|
|
700
|
+
#create_defaults() {
|
|
701
|
+
const white = Sampler2D.uint8(4, 1, 1);
|
|
702
|
+
|
|
703
|
+
white.data.fill(255);
|
|
704
|
+
|
|
705
|
+
this.#white = this.atlas.add(white);
|
|
706
|
+
this.#transparent = this.atlas.add(Sampler2D.uint8(4, 1, 1));
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* @param {import("../../shade/renderer/GPUDeviceContext.js").GPUDeviceContext} graphics
|
|
711
|
+
* @returns {void}
|
|
712
|
+
*/
|
|
713
|
+
#upload(graphics) {
|
|
714
|
+
const device = graphics.device;
|
|
715
|
+
const source = this.atlas.sampler;
|
|
716
|
+
|
|
717
|
+
if (this.#device !== device || this.#texture === null) {
|
|
718
|
+
this.#texture?.destroy();
|
|
719
|
+
|
|
720
|
+
this.#device = device;
|
|
721
|
+
this.#texture = new GPUTextureContext(device);
|
|
722
|
+
|
|
723
|
+
const descriptor = this.#texture.descriptor;
|
|
724
|
+
|
|
725
|
+
descriptor.label = "particles/sprite atlas";
|
|
726
|
+
descriptor.format = "rgba8unorm";
|
|
727
|
+
descriptor.usage = GPUTextureUsage.TEXTURE_BINDING
|
|
728
|
+
| GPUTextureUsage.COPY_DST
|
|
729
|
+
| GPUTextureUsage.RENDER_ATTACHMENT;
|
|
730
|
+
|
|
731
|
+
this.#uploaded_version = -1;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
const texture = this.#texture;
|
|
735
|
+
|
|
736
|
+
if (texture.width !== source.width || texture.height !== source.height) {
|
|
737
|
+
texture.descriptor.mipLevelCount = 1 + Math.floor(Math.log2(Math.max(source.width, source.height)));
|
|
738
|
+
texture.resize(source.width, source.height);
|
|
739
|
+
|
|
740
|
+
this.#uploaded_version = -1;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (this.#uploaded_version !== source.version) {
|
|
744
|
+
device.queue.writeTexture({ texture: texture.gpu_texture }, source.data,
|
|
745
|
+
{ bytesPerRow: source.width * 4 }, [source.width, source.height]);
|
|
746
|
+
|
|
747
|
+
if (texture.descriptor.mipLevelCount > 1) {
|
|
748
|
+
graphics.textures.mipmaps.generateMipmap(
|
|
749
|
+
texture.gpu_texture,
|
|
750
|
+
texture.descriptor,
|
|
751
|
+
TextureFilterType.Linear
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
texture.incrementVersion();
|
|
756
|
+
|
|
757
|
+
this.#uploaded_version = source.version;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
this.#view = texture.obtainView();
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/** @returns {void} */
|
|
764
|
+
#detach() {
|
|
765
|
+
if (this.#particles !== null && this.#particles.atlas === this.#view) {
|
|
766
|
+
this.#particles.atlas = this.#previous_atlas;
|
|
767
|
+
|
|
768
|
+
for (const emitter of this.#particles.emitters) {
|
|
769
|
+
this.#particles.registry.set_atlas_region(emitter, [0, 0, 1, 1]);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
this.#particles = null;
|
|
774
|
+
this.#previous_atlas = null;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Copy a component onto the emitter built for it, reporting whether anything actually moved.
|
|
780
|
+
*
|
|
781
|
+
* Comparing while assigning rather than in a pass of its own is what makes change detection cost
|
|
782
|
+
* nothing extra: the fields have to be read to be written, and the only addition is an `||` per
|
|
783
|
+
* field. What it answers is whether the emitter's GPU row has to be restaged, and restaging one that
|
|
784
|
+
* has not changed is an upload per emitter per frame.
|
|
785
|
+
*
|
|
786
|
+
* `spawn_rate` comes from {@link ParticleEffect#effective_spawn_rate}, so an effect switched off
|
|
787
|
+
* with `emitting = false` reaches the GPU as a rate of zero and keeps its authored rate to come back
|
|
788
|
+
* to. Layout and program are shared by reference, never copied — two entities of one effect belong
|
|
789
|
+
* on one program id in the heap.
|
|
790
|
+
*
|
|
791
|
+
* Every field is compared by name, and that is load-bearing rather than style. Through a shared
|
|
792
|
+
* `assign(target, field, value)` the one `target[field]` access saw all thirteen names, went
|
|
793
|
+
* megamorphic, and read numbers back boxed, while the call boxed the value it was handed: 228 B and
|
|
794
|
+
* ~120 ns per emitter per call, against nothing and ~9 ns written out like this
|
|
795
|
+
* (`GPUParticleEmitterSystem.allocation.spec.js`). This runs for every live emitter twice a frame.
|
|
796
|
+
*
|
|
797
|
+
* @param {ParticleEmitter} emitter
|
|
798
|
+
* @param {ParticleEffect} effect
|
|
799
|
+
* @returns {boolean} whether the emitter differs from what it held before
|
|
800
|
+
*/
|
|
801
|
+
export function apply_particle_effect(emitter, effect) {
|
|
802
|
+
let changed = false;
|
|
803
|
+
|
|
804
|
+
if (emitter.layout !== effect.layout) {
|
|
805
|
+
emitter.layout = effect.layout;
|
|
806
|
+
changed = true;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (emitter.program !== effect.program) {
|
|
810
|
+
emitter.program = effect.program;
|
|
811
|
+
changed = true;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (emitter.texture !== effect.texture) {
|
|
815
|
+
emitter.texture = effect.texture;
|
|
816
|
+
changed = true;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (emitter.seed !== effect.seed) {
|
|
820
|
+
emitter.seed = effect.seed;
|
|
821
|
+
changed = true;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const spawn_rate = effect.effective_spawn_rate;
|
|
825
|
+
|
|
826
|
+
if (emitter.spawn_rate !== spawn_rate) {
|
|
827
|
+
emitter.spawn_rate = spawn_rate;
|
|
828
|
+
changed = true;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (emitter.prewarm !== effect.prewarm) {
|
|
832
|
+
emitter.prewarm = effect.prewarm;
|
|
833
|
+
changed = true;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (emitter.flags !== effect.flags) {
|
|
837
|
+
emitter.flags = effect.flags;
|
|
838
|
+
changed = true;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
if (emitter.render_position !== effect.render_position) {
|
|
842
|
+
emitter.render_position = effect.render_position;
|
|
843
|
+
changed = true;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
if (emitter.render_size !== effect.render_size) {
|
|
847
|
+
emitter.render_size = effect.render_size;
|
|
848
|
+
changed = true;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
if (emitter.render_color !== effect.render_color) {
|
|
852
|
+
emitter.render_color = effect.render_color;
|
|
853
|
+
changed = true;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
if (emitter.render_orientation !== effect.render_orientation) {
|
|
857
|
+
emitter.render_orientation = effect.render_orientation;
|
|
858
|
+
changed = true;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (emitter.render_frame !== effect.render_frame) {
|
|
862
|
+
emitter.render_frame = effect.render_frame;
|
|
863
|
+
changed = true;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
if (emitter.render_velocity !== effect.render_velocity) {
|
|
867
|
+
emitter.render_velocity = effect.render_velocity;
|
|
868
|
+
changed = true;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const flipbook = emitter.flipbook;
|
|
872
|
+
|
|
873
|
+
if (flipbook[0] !== effect.flipbook[0] || flipbook[1] !== effect.flipbook[1]) {
|
|
874
|
+
flipbook.set(effect.flipbook);
|
|
875
|
+
|
|
876
|
+
changed = true;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
return changed;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
class GPUParticleAtlasExtension extends RenderExtension {
|
|
883
|
+
/** @type {string} */
|
|
884
|
+
name = "gpu particle atlas";
|
|
885
|
+
/** @type {FramePhase} */
|
|
886
|
+
phase = FramePhase.FrameStart;
|
|
887
|
+
/** @type {GPUParticleEmitterSystem} */
|
|
888
|
+
#system;
|
|
889
|
+
|
|
890
|
+
/** @param {GPUParticleEmitterSystem} system */
|
|
891
|
+
constructor(system) {
|
|
892
|
+
super();
|
|
893
|
+
|
|
894
|
+
this.#system = system;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* @param {import("../../shade/renderer/extension/FrameContext.js").FrameContext} frame
|
|
899
|
+
* @returns {void}
|
|
900
|
+
*/
|
|
901
|
+
record(frame) {
|
|
902
|
+
this.#system.prepare(frame);
|
|
903
|
+
}
|
|
904
|
+
}
|