@woosh/meep-engine 3.51.0 → 3.53.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.
Files changed (433) hide show
  1. package/package.json +1 -1
  2. package/src/engine/ecs/animation/Animation.d.ts +4 -25
  3. package/src/engine/ecs/animation/Animation.d.ts.map +1 -1
  4. package/src/engine/ecs/animation/Animation.js +9 -41
  5. package/src/engine/ecs/ik/IKGoalSystem.d.ts +4 -5
  6. package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
  7. package/src/engine/ecs/ik/IKGoalSystem.js +4 -6
  8. package/src/engine/graphics/ecs/mesh/assetTypeByPath.js +1 -1
  9. package/src/engine/graphics3/AnimationGraphSystem.d.ts +9 -22
  10. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  11. package/src/engine/graphics3/AnimationGraphSystem.js +58 -203
  12. package/src/engine/graphics3/AnimationSystem.d.ts +7 -18
  13. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  14. package/src/engine/graphics3/AnimationSystem.js +62 -243
  15. package/src/engine/graphics3/FoliageWindSystem.d.ts +67 -0
  16. package/src/engine/graphics3/FoliageWindSystem.d.ts.map +1 -0
  17. package/src/engine/graphics3/FoliageWindSystem.js +257 -0
  18. package/src/engine/graphics3/GPUFluidSystem.d.ts +7 -0
  19. package/src/engine/graphics3/GPUFluidSystem.d.ts.map +1 -1
  20. package/src/engine/graphics3/GPUFluidSystem.js +39 -1
  21. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +0 -1
  22. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  23. package/src/engine/graphics3/GPUParticleEmitterSystem.js +19 -5
  24. package/src/engine/graphics3/animation/AnimationClips.d.ts +107 -13
  25. package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -1
  26. package/src/engine/graphics3/animation/AnimationClips.js +207 -10
  27. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts +89 -0
  28. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts.map +1 -0
  29. package/src/engine/graphics3/animation/AnimationClipsSink.js +205 -0
  30. package/src/engine/graphics3/animation/FoliageWindRigs.d.ts +43 -0
  31. package/src/engine/graphics3/animation/FoliageWindRigs.d.ts.map +1 -0
  32. package/src/engine/graphics3/animation/FoliageWindRigs.js +69 -0
  33. package/src/engine/graphics3/animation/write_clip_playback.d.ts +17 -11
  34. package/src/engine/graphics3/animation/write_clip_playback.d.ts.map +1 -1
  35. package/src/engine/graphics3/animation/write_clip_playback.js +36 -27
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +8 -6
  38. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  39. package/src/engine/graphics3/decal/shader_decal_composite.js +11 -5
  40. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +7 -7
  41. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -1
  42. package/src/engine/graphics3/pose/collect_entity_playbacks.js +14 -15
  43. package/src/engine/graphics3/prefab/Prefab.d.ts +6 -0
  44. package/src/engine/graphics3/prefab/Prefab.d.ts.map +1 -1
  45. package/src/engine/graphics3/prefab/Prefab.js +169 -162
  46. package/src/engine/graphics3/prefab/prefab_compile.d.ts.map +1 -1
  47. package/src/engine/graphics3/prefab/prefab_compile.js +369 -334
  48. package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
  49. package/src/engine/graphics3/prefab/prefab_instantiate.js +43 -2
  50. package/src/engine/graphics3/terrain/chunk_terrain_material_surface.js +2 -2
  51. package/src/engine/physics/ecs/ContactProbeSystem.d.ts +2 -3
  52. package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
  53. package/src/engine/physics/ecs/ContactProbeSystem.js +2 -4
  54. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  55. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +4 -4
  56. package/src/engine/sound/simulation/README.md +1 -1
  57. package/src/engine/sound/simulation/probe/bakeProbeField.d.ts +22 -8
  58. package/src/engine/sound/simulation/probe/bakeProbeField.d.ts.map +1 -1
  59. package/src/engine/sound/simulation/probe/bakeProbeField.js +60 -15
  60. package/src/engine/sound/simulation/probe/bakeProbeReflectors.d.ts.map +1 -1
  61. package/src/engine/sound/simulation/probe/bakeProbeReflectors.js +19 -23
  62. package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts +63 -17
  63. package/src/engine/sound/simulation/probe/probe_sdf_grid.d.ts.map +1 -1
  64. package/src/engine/sound/simulation/probe/probe_sdf_grid.js +67 -17
  65. package/src/generation/foliage/FOLIAGE_DESIGN.md +318 -0
  66. package/src/generation/foliage/FOLIAGE_PLAN.md +198 -0
  67. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts +20 -0
  68. package/src/generation/foliage/animation/build_tree_wind_rig.d.ts.map +1 -0
  69. package/src/generation/foliage/animation/build_tree_wind_rig.js +108 -0
  70. package/src/generation/foliage/asset/TreeAsset.d.ts +86 -0
  71. package/src/generation/foliage/asset/TreeAsset.d.ts.map +1 -0
  72. package/src/generation/foliage/asset/TreeAsset.js +111 -0
  73. package/src/generation/foliage/asset/TreeLODAsset.d.ts +115 -0
  74. package/src/generation/foliage/asset/TreeLODAsset.d.ts.map +1 -0
  75. package/src/generation/foliage/asset/TreeLODAsset.js +346 -0
  76. package/src/generation/foliage/asset/generate_tree.d.ts +15 -0
  77. package/src/generation/foliage/asset/generate_tree.d.ts.map +1 -0
  78. package/src/generation/foliage/asset/generate_tree.js +93 -0
  79. package/src/generation/foliage/asset/place_tree.d.ts +82 -0
  80. package/src/generation/foliage/asset/place_tree.d.ts.map +1 -0
  81. package/src/generation/foliage/asset/place_tree.js +194 -0
  82. package/src/generation/foliage/config/BarkMaterialConfig.d.ts +120 -0
  83. package/src/generation/foliage/config/BarkMaterialConfig.d.ts.map +1 -0
  84. package/src/generation/foliage/config/BarkMaterialConfig.js +250 -0
  85. package/src/generation/foliage/config/BranchLevelConfig.d.ts +288 -0
  86. package/src/generation/foliage/config/BranchLevelConfig.d.ts.map +1 -0
  87. package/src/generation/foliage/config/BranchLevelConfig.js +536 -0
  88. package/src/generation/foliage/config/CrownConfig.d.ts +100 -0
  89. package/src/generation/foliage/config/CrownConfig.d.ts.map +1 -0
  90. package/src/generation/foliage/config/CrownConfig.js +186 -0
  91. package/src/generation/foliage/config/CrownEnvelopeType.d.ts +16 -0
  92. package/src/generation/foliage/config/CrownEnvelopeType.d.ts.map +1 -0
  93. package/src/generation/foliage/config/CrownEnvelopeType.js +17 -0
  94. package/src/generation/foliage/config/FoliageCardType.d.ts +12 -0
  95. package/src/generation/foliage/config/FoliageCardType.d.ts.map +1 -0
  96. package/src/generation/foliage/config/FoliageCardType.js +18 -0
  97. package/src/generation/foliage/config/FoliageConfig.d.ts +151 -0
  98. package/src/generation/foliage/config/FoliageConfig.d.ts.map +1 -0
  99. package/src/generation/foliage/config/FoliageConfig.js +283 -0
  100. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts +90 -0
  101. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts.map +1 -0
  102. package/src/generation/foliage/config/FoliageMaterialConfig.js +181 -0
  103. package/src/generation/foliage/config/PhyllotaxisMode.d.ts +13 -0
  104. package/src/generation/foliage/config/PhyllotaxisMode.d.ts.map +1 -0
  105. package/src/generation/foliage/config/PhyllotaxisMode.js +20 -0
  106. package/src/generation/foliage/config/TreeLODConfig.d.ts +87 -0
  107. package/src/generation/foliage/config/TreeLODConfig.d.ts.map +1 -0
  108. package/src/generation/foliage/config/TreeLODConfig.js +211 -0
  109. package/src/generation/foliage/config/TreePreset.d.ts +16 -0
  110. package/src/generation/foliage/config/TreePreset.d.ts.map +1 -0
  111. package/src/generation/foliage/config/TreePreset.js +17 -0
  112. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts +109 -0
  113. package/src/generation/foliage/config/TreeSpeciesConfig.d.ts.map +1 -0
  114. package/src/generation/foliage/config/TreeSpeciesConfig.js +400 -0
  115. package/src/generation/foliage/config/TreeWindConfig.d.ts +84 -0
  116. package/src/generation/foliage/config/TreeWindConfig.d.ts.map +1 -0
  117. package/src/generation/foliage/config/TreeWindConfig.js +157 -0
  118. package/src/generation/foliage/index.d.ts +38 -0
  119. package/src/generation/foliage/index.d.ts.map +1 -0
  120. package/src/generation/foliage/index.js +43 -0
  121. package/src/generation/foliage/material/make_bark_material.d.ts +37 -0
  122. package/src/generation/foliage/material/make_bark_material.d.ts.map +1 -0
  123. package/src/generation/foliage/material/make_bark_material.js +802 -0
  124. package/src/generation/foliage/material/make_foliage_material.d.ts +14 -0
  125. package/src/generation/foliage/material/make_foliage_material.d.ts.map +1 -0
  126. package/src/generation/foliage/material/make_foliage_material.js +359 -0
  127. package/src/generation/foliage/mesh/branch_collar_project.d.ts +42 -0
  128. package/src/generation/foliage/mesh/branch_collar_project.d.ts.map +1 -0
  129. package/src/generation/foliage/mesh/branch_collar_project.js +203 -0
  130. package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts +35 -0
  131. package/src/generation/foliage/mesh/branch_ring_triangulate.d.ts.map +1 -0
  132. package/src/generation/foliage/mesh/branch_ring_triangulate.js +72 -0
  133. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts +80 -0
  134. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts.map +1 -0
  135. package/src/generation/foliage/mesh/foliage_collect_attachments.js +502 -0
  136. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts +19 -0
  137. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.d.ts.map +1 -0
  138. package/src/generation/foliage/mesh/tree_mesh_apply_canopy_ao.js +150 -0
  139. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts +55 -0
  140. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -0
  141. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +1047 -0
  142. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts +21 -0
  143. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts.map +1 -0
  144. package/src/generation/foliage/mesh/tree_mesh_build_foliage.js +415 -0
  145. package/src/generation/foliage/presets/make_tree_species_preset.d.ts +13 -0
  146. package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -0
  147. package/src/generation/foliage/presets/make_tree_species_preset.js +837 -0
  148. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts +443 -0
  149. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts.map +1 -0
  150. package/src/generation/foliage/skeleton/TreeSkeleton.js +1100 -0
  151. package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts +27 -0
  152. package/src/generation/foliage/skeleton/crown_envelope_evaluate.d.ts.map +1 -0
  153. package/src/generation/foliage/skeleton/crown_envelope_evaluate.js +121 -0
  154. package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts +32 -0
  155. package/src/generation/foliage/skeleton/spine_frame_double_reflection.d.ts.map +1 -0
  156. package/src/generation/foliage/skeleton/spine_frame_double_reflection.js +87 -0
  157. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts +33 -0
  158. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.d.ts.map +1 -0
  159. package/src/generation/foliage/skeleton/tree_skeleton_assign_skin_joints.js +205 -0
  160. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts +14 -0
  161. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts.map +1 -0
  162. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.js +179 -0
  163. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts +18 -0
  164. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -0
  165. package/src/generation/foliage/skeleton/tree_skeleton_grow.js +1104 -0
  166. package/src/shade/playground/additive_blending/index.html +197 -0
  167. package/src/shade/playground/additive_blending/main.d.ts +2 -0
  168. package/src/shade/playground/additive_blending/main.d.ts.map +1 -0
  169. package/src/shade/playground/additive_blending/main.js +529 -0
  170. package/src/shade/playground/foliage_wind/README.md +18 -0
  171. package/src/shade/playground/foliage_wind/foliage_world.d.ts +127 -0
  172. package/src/shade/playground/foliage_wind/foliage_world.d.ts.map +1 -0
  173. package/src/shade/playground/foliage_wind/foliage_world.js +593 -0
  174. package/src/shade/playground/foliage_wind/index.html +254 -0
  175. package/src/shade/playground/foliage_wind/main.d.ts +2 -0
  176. package/src/shade/playground/foliage_wind/main.d.ts.map +1 -0
  177. package/src/shade/playground/foliage_wind/main.js +263 -0
  178. package/src/shade/playground/tonemap_sdr/README.md +5 -3
  179. package/src/shade/renderer/Renderer.d.ts +1 -1
  180. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  181. package/src/shade/renderer/Renderer.js +88 -31
  182. package/src/shade/renderer/ShadeToneMappingMode.d.ts +3 -2
  183. package/src/shade/renderer/ShadeToneMappingMode.js +15 -4
  184. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +145 -0
  185. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts +9 -1
  186. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.d.ts.map +1 -1
  187. package/src/shade/renderer/animation/ANIMATION_DATABASE_SPEC.js +53 -1
  188. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts +8 -0
  189. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.d.ts.map +1 -0
  190. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_JOINT_STRUCT.js +71 -0
  191. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts +11 -0
  192. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.d.ts.map +1 -0
  193. package/src/shade/renderer/animation/ANIMATION_FOLIAGE_RIG_STRUCT.js +32 -0
  194. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +30 -3
  195. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  196. package/src/shade/renderer/animation/GPUAnimationManager.js +532 -79
  197. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +19 -12
  198. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
  199. package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +20 -13
  200. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts +35 -8
  201. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts.map +1 -1
  202. package/src/shade/renderer/animation/ShadeAnimationClip.js +433 -2
  203. package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
  204. package/src/shade/renderer/animation/chunk_pose_accumulator.js +40 -32
  205. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts +97 -0
  206. package/src/shade/renderer/animation/foliage/FoliageWindJoint.d.ts.map +1 -0
  207. package/src/shade/renderer/animation/foliage/FoliageWindJoint.js +161 -0
  208. package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts +65 -0
  209. package/src/shade/renderer/animation/foliage/FoliageWindRig.d.ts.map +1 -0
  210. package/src/shade/renderer/animation/foliage/FoliageWindRig.js +89 -0
  211. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts +19 -0
  212. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.d.ts.map +1 -0
  213. package/src/shade/renderer/animation/foliage/chunk_foliage_wind_step.js +143 -0
  214. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts +14 -0
  215. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.d.ts.map +1 -0
  216. package/src/shade/renderer/animation/foliage/shader_foliage_wind_apply.js +116 -0
  217. package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
  218. package/src/shade/renderer/animation/pose/pose_evaluate_local.js +39 -29
  219. package/src/shade/renderer/animation/shader_animation_pose_resolve.js +37 -37
  220. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +2 -2
  221. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts +38 -0
  222. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.d.ts.map +1 -0
  223. package/src/shade/renderer/deferred/tonemap/TonemapAces2Tables.js +97 -0
  224. package/src/shade/renderer/deferred/{TonemapDisplaySettings.d.ts → tonemap/TonemapDisplaySettings.d.ts} +1 -1
  225. package/src/shade/renderer/deferred/tonemap/TonemapDisplaySettings.d.ts.map +1 -0
  226. package/src/shade/renderer/deferred/{TonemapDisplaySettings.js → tonemap/TonemapDisplaySettings.js} +5 -5
  227. package/src/shade/renderer/deferred/{shader_tonemap_HDR.d.ts → tonemap/shader_tonemap_HDR.d.ts} +1 -1
  228. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR.d.ts.map +1 -0
  229. package/src/shade/renderer/deferred/{shader_tonemap_HDR.js → tonemap/shader_tonemap_HDR.js} +9 -9
  230. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts +17 -0
  231. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.d.ts.map +1 -0
  232. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_aces.js +101 -0
  233. package/src/shade/renderer/deferred/{shader_tonemap_HDR_none.d.ts → tonemap/shader_tonemap_HDR_none.d.ts} +1 -1
  234. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_none.d.ts.map +1 -0
  235. package/src/shade/renderer/deferred/{shader_tonemap_HDR_none.js → tonemap/shader_tonemap_HDR_none.js} +6 -6
  236. package/src/shade/renderer/deferred/{shader_tonemap_HDR_pbr_neutral.d.ts → tonemap/shader_tonemap_HDR_pbr_neutral.d.ts} +1 -1
  237. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_pbr_neutral.d.ts.map +1 -0
  238. package/src/shade/renderer/deferred/{shader_tonemap_HDR_pbr_neutral.js → tonemap/shader_tonemap_HDR_pbr_neutral.js} +8 -8
  239. package/src/shade/renderer/deferred/{shader_tonemap_LDR.d.ts → tonemap/shader_tonemap_LDR.d.ts} +1 -1
  240. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR.d.ts.map +1 -0
  241. package/src/shade/renderer/deferred/{shader_tonemap_LDR.js → tonemap/shader_tonemap_LDR.js} +10 -10
  242. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts +10 -0
  243. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.d.ts.map +1 -0
  244. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_aces.js +77 -0
  245. package/src/shade/renderer/deferred/{shader_tonemap_LDR_none.d.ts → tonemap/shader_tonemap_LDR_none.d.ts} +1 -1
  246. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_none.d.ts.map +1 -0
  247. package/src/shade/renderer/deferred/{shader_tonemap_LDR_none.js → tonemap/shader_tonemap_LDR_none.js} +7 -7
  248. package/src/shade/renderer/deferred/{shader_tonemap_LDR_pbr_neutral.d.ts → tonemap/shader_tonemap_LDR_pbr_neutral.d.ts} +1 -1
  249. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_pbr_neutral.d.ts.map +1 -0
  250. package/src/shade/renderer/deferred/{shader_tonemap_LDR_pbr_neutral.js → tonemap/shader_tonemap_LDR_pbr_neutral.js} +8 -8
  251. package/src/shade/renderer/extension/RenderExtension.d.ts +7 -0
  252. package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
  253. package/src/shade/renderer/extension/RenderExtension.js +9 -0
  254. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts +6 -0
  255. package/src/shade/renderer/extension/RenderExtensionRegistry.d.ts.map +1 -1
  256. package/src/shade/renderer/extension/RenderExtensionRegistry.js +15 -0
  257. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +10 -3
  258. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts.map +1 -1
  259. package/src/shade/renderer/fluid/GPUFluidCascade.js +15 -0
  260. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +8 -1
  261. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  262. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +11 -0
  263. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.d.ts.map +1 -1
  264. package/src/shade/renderer/fluid/coupling/chunk_fluid_cascade_parent.js +51 -48
  265. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  266. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts +6 -0
  267. package/src/shade/renderer/fluid/mac/FluidMacPasses.d.ts.map +1 -1
  268. package/src/shade/renderer/fluid/mac/FluidMacPasses.js +16 -0
  269. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.d.ts.map +1 -1
  270. package/src/shade/renderer/fluid/mac/chunk_fluid_mac_seams.js +15 -3
  271. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.d.ts.map +1 -1
  272. package/src/shade/renderer/fluid/mac/chunk_v3_mac_lattice_corners.js +102 -96
  273. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +12 -12
  274. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_predict.js +12 -12
  275. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +8 -1
  276. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts.map +1 -1
  277. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.js +16 -0
  278. package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts +7 -0
  279. package/src/shade/renderer/fluid/publish/FluidWindPublish.d.ts.map +1 -1
  280. package/src/shade/renderer/fluid/publish/FluidWindPublish.js +10 -0
  281. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  282. package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.js +2 -2
  283. package/src/shade/renderer/loader/SceneBundle.d.ts +7 -0
  284. package/src/shade/renderer/loader/SceneBundle.d.ts.map +1 -1
  285. package/src/shade/renderer/loader/SceneBundle.js +119 -111
  286. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  287. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +4 -0
  288. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  289. package/src/shade/renderer/material/standard/fragment_gbuffer.js +6 -5
  290. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +8 -7
  291. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
  292. package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +9 -8
  293. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  294. package/src/shade/renderer/particles/GPUParticleSystem.js +3 -1
  295. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  296. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +9 -4
  297. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  298. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
  299. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +9 -7
  300. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.d.ts.map +1 -1
  301. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment.js +15 -7
  302. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.d.ts.map +1 -1
  303. package/src/shade/renderer/rasterize/native/avboit/avboit_draw_fragment_body.js +6 -4
  304. package/src/shade/renderer/rasterize/native/oit/oit_resolve_fragment_body.js +3 -3
  305. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.d.ts.map +1 -1
  306. package/src/shade/renderer/rasterize/native/oit/shader_oit_generate_moments.js +8 -5
  307. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  308. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +4 -3
  309. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +160 -0
  310. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +5 -1
  311. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +15 -5
  312. package/src/shade/renderer/shader/chunk/color/tonemap/aces/aces2_transform_block.d.ts +41 -0
  313. package/src/shade/renderer/shader/chunk/color/tonemap/aces/aces2_transform_block.d.ts.map +1 -0
  314. package/src/shade/renderer/shader/chunk/color/tonemap/aces/aces2_transform_block.js +692 -0
  315. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces2_output_transform.d.ts +25 -0
  316. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces2_output_transform.d.ts.map +1 -0
  317. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces2_output_transform.js +446 -0
  318. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts +22 -0
  319. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts.map +1 -0
  320. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.js +68 -0
  321. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.d.ts +32 -0
  322. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.d.ts.map +1 -0
  323. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.js +163 -0
  324. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts +10 -3
  325. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts.map +1 -1
  326. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js +12 -4
  327. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +1 -1
  328. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts +9 -0
  329. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.d.ts.map +1 -0
  330. package/src/shade/renderer/texture/SAMPLER_ANISOTROPIC_CLAMP.js +17 -0
  331. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts +8 -0
  332. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.d.ts.map +1 -1
  333. package/src/shade/renderer/texture/SAMPLER_LINEAR_UPSCALE.js +28 -20
  334. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts +8 -0
  335. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.d.ts.map +1 -0
  336. package/src/shade/renderer/texture/SAMPLER_TRILINEAR_CLAMP.js +15 -0
  337. package/src/shade/renderer/view/chunk_view_mip_bias.d.ts +21 -0
  338. package/src/shade/renderer/view/chunk_view_mip_bias.d.ts.map +1 -0
  339. package/src/shade/renderer/view/chunk_view_mip_bias.js +44 -0
  340. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  341. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  342. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +105 -26
  343. package/src/engine/graphics/composit/CompositingStages.d.ts +0 -6
  344. package/src/engine/graphics/composit/CompositingStages.d.ts.map +0 -1
  345. package/src/engine/graphics/composit/CompositingStages.js +0 -8
  346. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts +0 -7
  347. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.d.ts.map +0 -1
  348. package/src/engine/graphics/geometry/buffered/computeBufferAttributeHash.js +0 -24
  349. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts +0 -8
  350. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.d.ts.map +0 -1
  351. package/src/engine/graphics/geometry/buffered/computeGeometryBoundingSphereMiniball.js +0 -17
  352. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts +0 -8
  353. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.d.ts.map +0 -1
  354. package/src/engine/graphics/geometry/buffered/computeGeometryEquality.js +0 -60
  355. package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts +0 -7
  356. package/src/engine/graphics/geometry/buffered/computeGeometryHash.d.ts.map +0 -1
  357. package/src/engine/graphics/geometry/buffered/computeGeometryHash.js +0 -26
  358. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts +0 -7
  359. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.d.ts.map +0 -1
  360. package/src/engine/graphics/geometry/buffered/compute_buffer_geometry_byte_size.js +0 -23
  361. package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts +0 -7
  362. package/src/engine/graphics/geometry/instancing/geometry_copy.d.ts.map +0 -1
  363. package/src/engine/graphics/geometry/instancing/geometry_copy.js +0 -15
  364. package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts +0 -2
  365. package/src/engine/graphics/geometry/instancing/rewriteMaterial.d.ts.map +0 -1
  366. package/src/engine/graphics/geometry/instancing/rewriteMaterial.js +0 -57
  367. package/src/engine/graphics/geometry/ribbon/Quad.d.ts +0 -96
  368. package/src/engine/graphics/geometry/ribbon/Quad.d.ts.map +0 -1
  369. package/src/engine/graphics/geometry/ribbon/Quad.js +0 -213
  370. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts +0 -9
  371. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.d.ts.map +0 -1
  372. package/src/engine/graphics/geometry/ribbon/copyAttributeV3.js +0 -12
  373. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts +0 -10
  374. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.d.ts.map +0 -1
  375. package/src/engine/graphics/geometry/ribbon/copyAttributeValue.js +0 -17
  376. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts +0 -10
  377. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.d.ts.map +0 -1
  378. package/src/engine/graphics/geometry/ribbon/equalAttributeV3.js +0 -13
  379. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts +0 -11
  380. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.d.ts.map +0 -1
  381. package/src/engine/graphics/geometry/ribbon/equalAttributeValue.js +0 -24
  382. package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts +0 -6
  383. package/src/engine/graphics/geometry/ribbon/rotateRibbon.d.ts.map +0 -1
  384. package/src/engine/graphics/geometry/ribbon/rotateRibbon.js +0 -37
  385. package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts +0 -9
  386. package/src/engine/graphics/geometry/ribbon/updateTipPosition.d.ts.map +0 -1
  387. package/src/engine/graphics/geometry/ribbon/updateTipPosition.js +0 -52
  388. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts +0 -8
  389. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.d.ts.map +0 -1
  390. package/src/engine/graphics/geometry/skining/computeSkinnedMeshVertices.js +0 -54
  391. package/src/engine/graphics/render/RenderPassType.d.ts +0 -6
  392. package/src/engine/graphics/render/RenderPassType.d.ts.map +0 -1
  393. package/src/engine/graphics/render/RenderPassType.js +0 -8
  394. package/src/engine/graphics/render/layers/RenderLayer.d.ts +0 -78
  395. package/src/engine/graphics/render/layers/RenderLayer.d.ts.map +0 -1
  396. package/src/engine/graphics/render/layers/RenderLayer.js +0 -95
  397. package/src/engine/graphics/render/layers/RenderLayerManager.d.ts +0 -72
  398. package/src/engine/graphics/render/layers/RenderLayerManager.d.ts.map +0 -1
  399. package/src/engine/graphics/render/layers/RenderLayerManager.js +0 -160
  400. package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts +0 -18
  401. package/src/engine/graphics/render/layers/RenderLayerManagerState.d.ts.map +0 -1
  402. package/src/engine/graphics/render/layers/RenderLayerManagerState.js +0 -48
  403. package/src/engine/graphics/render/layers/RenderLayerState.d.ts +0 -18
  404. package/src/engine/graphics/render/layers/RenderLayerState.d.ts.map +0 -1
  405. package/src/engine/graphics/render/layers/RenderLayerState.js +0 -27
  406. package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts +0 -8
  407. package/src/engine/graphics/render/layers/RenderLayerUtils.d.ts.map +0 -1
  408. package/src/engine/graphics/render/layers/RenderLayerUtils.js +0 -103
  409. package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts +0 -10
  410. package/src/engine/graphics/render/make_bvh_visibility_builder.d.ts.map +0 -1
  411. package/src/engine/graphics/render/make_bvh_visibility_builder.js +0 -64
  412. package/src/engine/graphics/render/view/CameraViewFlags.d.ts +0 -7
  413. package/src/engine/graphics/render/view/CameraViewFlags.d.ts.map +0 -1
  414. package/src/engine/graphics/render/view/CameraViewFlags.js +0 -9
  415. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +0 -143
  416. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts.map +0 -1
  417. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.js +0 -328
  418. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts +0 -39
  419. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts.map +0 -1
  420. package/src/engine/graphics/render/visibility/VisibilityComputer.js +0 -80
  421. package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts +0 -29
  422. package/src/engine/graphics/render/visibility/VisibilityFilter.d.ts.map +0 -1
  423. package/src/engine/graphics/render/visibility/VisibilityFilter.js +0 -37
  424. package/src/engine/graphics3/animation/write_graph_playback.d.ts +0 -24
  425. package/src/engine/graphics3/animation/write_graph_playback.d.ts.map +0 -1
  426. package/src/engine/graphics3/animation/write_graph_playback.js +0 -48
  427. package/src/shade/renderer/deferred/TonemapDisplaySettings.d.ts.map +0 -1
  428. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +0 -1
  429. package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts.map +0 -1
  430. package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts.map +0 -1
  431. package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts.map +0 -1
  432. package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts.map +0 -1
  433. package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts.map +0 -1
@@ -14,9 +14,17 @@ import { graph_import_buffer } from "../shader/graph/graph_import_buffer.js";
14
14
  import { ANIMATION_CLIP_STATE_STRUCT } from "./ANIMATION_CLIP_STATE_STRUCT.js";
15
15
  import { ANIMATION_CURVE_KEYFRAME_STRUCT } from "./ANIMATION_CURVE_KEYFRAME_STRUCT.js";
16
16
  import { ANIMATION_DATABASE_SPEC } from "./ANIMATION_DATABASE_SPEC.js";
17
+ import { ANIMATION_FOLIAGE_JOINT_STRUCT } from "./ANIMATION_FOLIAGE_JOINT_STRUCT.js";
18
+ import { ANIMATION_FOLIAGE_RIG_STRUCT } from "./ANIMATION_FOLIAGE_RIG_STRUCT.js";
17
19
  import { ANIMATION_SKIN_JOINT_STRUCT } from "./ANIMATION_SKIN_JOINT_STRUCT.js";
18
20
  import { ANIMATION_SKIN_STRUCT } from "./ANIMATION_SKIN_STRUCT.js";
19
21
  import { ANIMATION_TRACK_BINDING_STRUCT } from "./ANIMATION_TRACK_BINDING_STRUCT.js";
22
+ import { ShaderSwitchSet } from "../shader/compiler/ShaderSwitchSet.js";
23
+ import { WIND_FIELD_UNIFORM } from "../wind/WIND_FIELD_UNIFORM.js";
24
+ import {
25
+ shader_foliage_wind_apply,
26
+ WORKGROUP_SIZE as FOLIAGE_WIND_APPLY_WORKGROUP_SIZE,
27
+ } from "./foliage/shader_foliage_wind_apply.js";
20
28
  import { AnimationClipFlags } from "./AnimationClipFlags.js";
21
29
  import { POSE_ACCUMULATOR_SLOT_BYTES } from "./POSE_ACCUMULATOR_LAYOUT.js";
22
30
  import { GPUStateAuthorityFlags } from "../../../engine/ecs/gpu/GPUStateAuthorityFlags.js";
@@ -29,6 +37,7 @@ import { gpu_authority_declare } from "../../../engine/ecs/gpu/gpu_authority_dec
29
37
  import { TransformAttachment } from "../../../engine/ecs/transform-attachment/TransformAttachment.js";
30
38
  import { TRANSFORM_ATTACHMENT_EVENT_CHANGE } from "../../../engine/ecs/transform-attachment/TRANSFORM_ATTACHMENT_EVENT_CHANGE.js";
31
39
  import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
40
+ import { Node3DProperty } from "../object_property/Node3DProperty.js";
32
41
  import { pose_evaluate_local } from "./pose/pose_evaluate_local.js";
33
42
  import { PosePlayback } from "./pose/PosePlayback.js";
34
43
  import {
@@ -107,6 +116,51 @@ function rest_rotation_of(dataset, entity) {
107
116
  return [rest.rotation_x, rest.rotation_y, rest.rotation_z, rest.rotation_w];
108
117
  }
109
118
 
119
+ /**
120
+ * Write the rest value for a specific {@link Node3DProperty} into `out` (`[x, y, z, w]`).
121
+ *
122
+ * @param {number[]} out
123
+ * @param {Transform64} rest
124
+ * @param {number} property
125
+ * @returns {number[]} `out`
126
+ */
127
+ function write_rest_for_property(out, rest, property) {
128
+ switch (property) {
129
+ case Node3DProperty.Translation:
130
+ out[0] = rest.translation_x;
131
+ out[1] = rest.translation_y;
132
+ out[2] = rest.translation_z;
133
+ out[3] = 0;
134
+ break;
135
+ case Node3DProperty.Scale:
136
+ out[0] = rest.scale_x;
137
+ out[1] = rest.scale_y;
138
+ out[2] = rest.scale_z;
139
+ out[3] = 0;
140
+ break;
141
+ case Node3DProperty.Rotation:
142
+ default:
143
+ out[0] = rest.rotation_x;
144
+ out[1] = rest.rotation_y;
145
+ out[2] = rest.rotation_z;
146
+ out[3] = rest.rotation_w;
147
+ break;
148
+ }
149
+ return out;
150
+ }
151
+
152
+ /**
153
+ * The rest value an entity rests at for a bound {@link Node3DProperty}, packed as `[x, y, z, w]`.
154
+ *
155
+ * @param {EntityComponentDataset} dataset
156
+ * @param {number} entity
157
+ * @param {number} property
158
+ * @returns {number[]}
159
+ */
160
+ function rest_for_property(dataset, entity, property) {
161
+ return write_rest_for_property([0, 0, 0, 1], rest_of(dataset, entity), property);
162
+ }
163
+
110
164
  /*
111
165
  Generated writers for the rows a registration adds as a run. Through `add_run` every row is a
112
166
  reflective walk of its type, and a run is one row per keyframe, binding or joint where a chain
@@ -117,6 +171,14 @@ function rest_rotation_of(dataset, entity) {
117
171
  const KEYFRAME_WRITER = generate_record_writer(ANIMATION_CURVE_KEYFRAME_STRUCT);
118
172
  const BINDING_WRITER = generate_record_writer(ANIMATION_TRACK_BINDING_STRUCT);
119
173
  const SKIN_JOINT_WRITER = generate_record_writer(ANIMATION_SKIN_JOINT_STRUCT);
174
+ const FOLIAGE_JOINT_WRITER = generate_record_writer(ANIMATION_FOLIAGE_JOINT_STRUCT);
175
+ const FOLIAGE_RIG_WEIGHT_WRITER = generate_record_writer(ANIMATION_FOLIAGE_RIG_STRUCT, ['weight']);
176
+ const FOLIAGE_RIG_COMPLETE_WRITER = generate_record_writer(ANIMATION_FOLIAGE_RIG_STRUCT, ['joints_first', 'joint_count', 'root_node']);
177
+ const FOLIAGE_JOINT_NODE_WRITER = generate_record_writer(ANIMATION_FOLIAGE_JOINT_STRUCT, ['node']);
178
+ const FOLIAGE_JOINT_UNMUTE_WRITER = generate_record_writer(ANIMATION_FOLIAGE_JOINT_STRUCT, ['node', 'rest_rotation']);
179
+ const FOLIAGE_RIG_JOINTS_FIRST_WORD = ANIMATION_FOLIAGE_RIG_STRUCT.get('joints_first').offset / 4;
180
+ const FOLIAGE_JOINT_NODE = { node: 0 };
181
+ const FOLIAGE_JOINT_UNMUTE = { node: 0, rest_rotation: [0, 0, 0, 1] };
120
182
 
121
183
  /*
122
184
  Writers for the fields of a clip that change after registration, each owning only its own words.
@@ -354,9 +416,10 @@ function skin_content_equals(skin, joints, inverse_bind_matrices) {
354
416
  export class GPUAnimationManager {
355
417
 
356
418
  /**
357
- * Offer the pipelines {@link tick} runs on every frame: the transform hierarchy, which composes
358
- * world matrices whether or not anything is animated — see {@link PipelineEnquiry}. The clip,
359
- * pose and skinning passes are left to the first frame that has a clip or a skin.
419
+ * Offer the pipelines {@link tick} runs on every frame: the
420
+ * transform hierarchy — see {@link PipelineEnquiry}. The clip,
421
+ * pose and skinning passes are left to the first frame that has a
422
+ * clip or a skin.
360
423
  *
361
424
  * @param {PipelineEnquiry} enquiry
362
425
  */
@@ -626,6 +689,35 @@ export class GPUAnimationManager {
626
689
  */
627
690
  #pending_clips = [];
628
691
 
692
+ /**
693
+ * Foliage wind rigs registered via {@link register_foliage_rig} whose target entities have not
694
+ * all taken their scene-database transform rows yet.
695
+ *
696
+ * @type {Array<{ rig_id: number, rig: import("./foliage/FoliageWindRig.js").FoliageWindRig }>}
697
+ */
698
+ #pending_foliage_rigs = [];
699
+
700
+ /**
701
+ * Bound foliage wind rigs driving each entity, by entity id.
702
+ *
703
+ * @type {Map<number, number[]>}
704
+ */
705
+ #foliage_rigs_driving = new Map();
706
+
707
+ /**
708
+ * Distinct target entities driven by each completed foliage wind rig, by rig id.
709
+ *
710
+ * @type {Map<number, number[]>}
711
+ */
712
+ #targets_by_foliage_rig = new Map();
713
+
714
+ /**
715
+ * CPU shadow record of each registered foliage wind rig, by rig id.
716
+ *
717
+ * @type {Map<number, { rig: import("./foliage/FoliageWindRig.js").FoliageWindRig, weight: number }>}
718
+ */
719
+ #foliage_rig_by_id = new Map();
720
+
629
721
  /**
630
722
  * @param {GPUDevice} device
631
723
  * @param {string} label
@@ -1521,7 +1613,7 @@ export class GPUAnimationManager {
1521
1613
  clip: clip_id,
1522
1614
  // a held target's rest is the holder's pose of the moment, taken again when the
1523
1615
  // hold ends: see #unmute
1524
- rest_rotation: rest_rotation_of(rows.dataset, target),
1616
+ rest_rotation: rest_for_property(rows.dataset, target, ch.property),
1525
1617
  };
1526
1618
  }
1527
1619
 
@@ -1568,31 +1660,33 @@ export class GPUAnimationManager {
1568
1660
 
1569
1661
  driving.set(target, clips);
1570
1662
 
1571
- /*
1572
- The first clip to drive a joint takes its offset, and with it the joint's world
1573
- and every world below: the hierarchy pass composes the subtree from the rows, and
1574
- the CPU stops composing it (D4). Stated on each entity of the subtree, so a
1575
- reader can be told rather than left to infer it from the joint above.
1576
- */
1577
- gpu_authority_grant(
1578
- dataset,
1579
- target,
1580
- GPUStateAuthorityFlags.TransformAttachment | GPUStateAuthorityFlags.Transform64
1581
- );
1582
-
1583
- // The offset as it stands is the clip's rest, and the row's on every axis it does
1584
- // not key: an announcement still waiting for the flush is skipped once the bit is set.
1585
- rows.mark_handover(target);
1586
-
1587
- rows.for_each_descendant(target, descendant => {
1588
- // a prefab declares its animated subtree; an entity attached under a joint
1589
- // from elsewhere is declared here, at the one moment it is taken
1590
- gpu_authority_declare(dataset, descendant);
1591
- gpu_authority_grant(dataset, descendant, GPUStateAuthorityFlags.Transform64);
1592
- });
1593
-
1594
- // A CPU writer may hold the offset now or later; it says so on the entity.
1595
- dataset.addEntityEventListener(target, GPU_AUTHORITY_EVENT_HOLD_CHANGE, this.#hold_changed, this);
1663
+ if (!this.#foliage_rigs_driving.has(target)) {
1664
+ /*
1665
+ The first clip to drive a joint takes its offset, and with it the joint's world
1666
+ and every world below: the hierarchy pass composes the subtree from the rows, and
1667
+ the CPU stops composing it (D4). Stated on each entity of the subtree, so a
1668
+ reader can be told rather than left to infer it from the joint above.
1669
+ */
1670
+ gpu_authority_grant(
1671
+ dataset,
1672
+ target,
1673
+ GPUStateAuthorityFlags.TransformAttachment | GPUStateAuthorityFlags.Transform64
1674
+ );
1675
+
1676
+ // The offset as it stands is the clip's rest, and the row's on every axis it does
1677
+ // not key: an announcement still waiting for the flush is skipped once the bit is set.
1678
+ rows.mark_handover(target);
1679
+
1680
+ rows.for_each_descendant(target, descendant => {
1681
+ // a prefab declares its animated subtree; an entity attached under a joint
1682
+ // from elsewhere is declared here, at the one moment it is taken
1683
+ gpu_authority_declare(dataset, descendant);
1684
+ gpu_authority_grant(dataset, descendant, GPUStateAuthorityFlags.Transform64);
1685
+ });
1686
+
1687
+ // A CPU writer may hold the offset now or later; it says so on the entity.
1688
+ dataset.addEntityEventListener(target, GPU_AUTHORITY_EVENT_HOLD_CHANGE, this.#hold_changed, this);
1689
+ }
1596
1690
  }
1597
1691
 
1598
1692
  clips.push(clip_id);
@@ -1611,11 +1705,12 @@ export class GPUAnimationManager {
1611
1705
  */
1612
1706
  #gpu_composed(entity, dataset) {
1613
1707
  const driving = this.#clips_driving;
1708
+ const foliage_driving = this.#foliage_rigs_driving;
1614
1709
 
1615
1710
  let cursor = entity;
1616
1711
 
1617
1712
  while (cursor !== -1) {
1618
- if (driving.has(cursor)) {
1713
+ if (driving.has(cursor) || foliage_driving.has(cursor)) {
1619
1714
  return true;
1620
1715
  }
1621
1716
 
@@ -1664,6 +1759,10 @@ export class GPUAnimationManager {
1664
1759
 
1665
1760
  driving.delete(target);
1666
1761
 
1762
+ if (this.#foliage_rigs_driving.has(target)) {
1763
+ continue;
1764
+ }
1765
+
1667
1766
  if (!dataset.entityExists(target)) {
1668
1767
  continue;
1669
1768
  }
@@ -1776,6 +1875,10 @@ export class GPUAnimationManager {
1776
1875
  BINDING_INSTANCE.instance = GPU_DATABASE_NULL;
1777
1876
 
1778
1877
  this.#write_bindings(entity, BINDING_INSTANCE, BINDING_INSTANCE_WRITER);
1878
+
1879
+ FOLIAGE_JOINT_NODE.node = GPU_DATABASE_NULL;
1880
+
1881
+ this.#write_foliage_joints(entity, FOLIAGE_JOINT_NODE, FOLIAGE_JOINT_NODE_WRITER);
1779
1882
  }
1780
1883
 
1781
1884
  /**
@@ -1795,15 +1898,36 @@ export class GPUAnimationManager {
1795
1898
  #unmute(entity, dataset) {
1796
1899
  const rest = rest_of(dataset, entity);
1797
1900
  const rest_rotation = BINDING_UNMUTE.rest_rotation;
1901
+ const row = row_of_entity(entity);
1798
1902
 
1799
- BINDING_UNMUTE.instance = row_of_entity(entity);
1903
+ BINDING_UNMUTE.instance = row;
1800
1904
 
1801
- rest_rotation[0] = rest.rotation_x;
1802
- rest_rotation[1] = rest.rotation_y;
1803
- rest_rotation[2] = rest.rotation_z;
1804
- rest_rotation[3] = rest.rotation_w;
1905
+ const clips = this.#clips_driving.get(entity);
1906
+ if (clips !== undefined) {
1907
+ const clips_table = this.#database.get('animation_clips');
1908
+ const bindings = this.#database.get('animation_bindings');
1909
+
1910
+ for (let c = 0; c < clips.length; c++) {
1911
+ const clip_id = clips[c];
1912
+ const first = clips_table.get_word(clip_id, CLIP_BINDINGS_FIRST_WORD);
1913
+ const channels = this.#playback_by_clip.get(clip_id).clip.channels;
1914
+
1915
+ for (let i = 0; i < channels.length; i++) {
1916
+ if (channels[i].target === entity) {
1917
+ write_rest_for_property(rest_rotation, rest, channels[i].property);
1918
+ bindings.set_fields(first + i, BINDING_UNMUTE, BINDING_UNMUTE_WRITER);
1919
+ }
1920
+ }
1921
+ }
1922
+ }
1923
+
1924
+ FOLIAGE_JOINT_UNMUTE.node = row;
1925
+ FOLIAGE_JOINT_UNMUTE.rest_rotation[0] = rest.rotation_x;
1926
+ FOLIAGE_JOINT_UNMUTE.rest_rotation[1] = rest.rotation_y;
1927
+ FOLIAGE_JOINT_UNMUTE.rest_rotation[2] = rest.rotation_z;
1928
+ FOLIAGE_JOINT_UNMUTE.rest_rotation[3] = rest.rotation_w;
1805
1929
 
1806
- this.#write_bindings(entity, BINDING_UNMUTE, BINDING_UNMUTE_WRITER);
1930
+ this.#write_foliage_joints(entity, FOLIAGE_JOINT_UNMUTE, FOLIAGE_JOINT_UNMUTE_WRITER);
1807
1931
  }
1808
1932
 
1809
1933
  /**
@@ -1882,6 +2006,285 @@ export class GPUAnimationManager {
1882
2006
  this.#playback_by_clip.delete(clip_id);
1883
2007
  }
1884
2008
 
2009
+ /**
2010
+ * Register a {@link FoliageWindRig} whose joints and root address ECS entities.
2011
+ *
2012
+ * Allocates a row in `animation_foliage_rigs` immediately. Once `rig.root` and every joint's
2013
+ * `target` entity hold rows in `GPUSceneRows`, adds the run of `animation_foliage_joints`
2014
+ * records and grants `GPUStateAuthority` on the driven joints.
2015
+ *
2016
+ * @param {import("./foliage/FoliageWindRig.js").FoliageWindRig} rig
2017
+ * @returns {number} foliage rig id (index into `animation_foliage_rigs`)
2018
+ */
2019
+ register_foliage_rig(rig) {
2020
+ assert.defined(rig, 'rig');
2021
+ assert.equal(rig.isFoliageWindRig, true, 'rig.isFoliageWindRig !== true');
2022
+ assert.isNonNegativeInteger(rig.root, 'rig.root');
2023
+ assert.greaterThanOrEqual(rig.joints.length, 1, 'foliage rig must have at least one joint');
2024
+
2025
+ const cloned = rig.clone();
2026
+ const weight = typeof cloned.weight === 'number' ? cloned.weight : 1.0;
2027
+
2028
+ const rigs_table = this.#database.get('animation_foliage_rigs');
2029
+ const rig_id = rigs_table.add({
2030
+ joints_first: GPU_DATABASE_NULL,
2031
+ joint_count: 0,
2032
+ root_node: GPU_DATABASE_NULL,
2033
+ weight,
2034
+ });
2035
+
2036
+ this.#foliage_rig_by_id.set(rig_id, { rig: cloned, weight });
2037
+
2038
+ const pending = { rig_id, rig: cloned };
2039
+ if (!this.#try_complete_foliage_rig(pending)) {
2040
+ this.#pending_foliage_rigs.push(pending);
2041
+ }
2042
+
2043
+ return rig_id;
2044
+ }
2045
+
2046
+ /**
2047
+ * Update a registered foliage wind rig's contribution weight.
2048
+ *
2049
+ * @param {number} rig_id
2050
+ * @param {number} weight
2051
+ */
2052
+ set_foliage_rig_weight(rig_id, weight) {
2053
+ assert.isNonNegativeInteger(rig_id, 'rig_id');
2054
+ assert.isNumber(weight, 'weight');
2055
+
2056
+ const rigs_table = this.#database.get('animation_foliage_rigs');
2057
+ assert.equal(rigs_table.occupancy.get(rig_id), true, `Invalid foliage rig_id: ${rig_id} (not allocated)`);
2058
+
2059
+ rigs_table.set_fields(rig_id, { weight }, FOLIAGE_RIG_WEIGHT_WRITER);
2060
+
2061
+ const shadow = this.#foliage_rig_by_id.get(rig_id);
2062
+ if (shadow !== undefined) {
2063
+ shadow.weight = weight;
2064
+ }
2065
+ }
2066
+
2067
+ /**
2068
+ * Drop a foliage wind rig from the manager: removes its row in `animation_foliage_rigs`
2069
+ * (and with it the owned run in `animation_foliage_joints`) and releases GPU authority on
2070
+ * its target entities. Safe to call repeatedly on the same id.
2071
+ *
2072
+ * @param {number} rig_id
2073
+ */
2074
+ unregister_foliage_rig(rig_id) {
2075
+ assert.isNonNegativeInteger(rig_id, 'rig_id');
2076
+
2077
+ for (let i = this.#pending_foliage_rigs.length - 1; i >= 0; i--) {
2078
+ if (this.#pending_foliage_rigs[i].rig_id === rig_id) {
2079
+ this.#pending_foliage_rigs.splice(i, 1);
2080
+ }
2081
+ }
2082
+
2083
+ const rigs_table = this.#database.get('animation_foliage_rigs');
2084
+ if (!rigs_table.occupancy.get(rig_id)) return;
2085
+
2086
+ rigs_table.remove(rig_id);
2087
+
2088
+ this.#release_foliage_targets(rig_id);
2089
+
2090
+ this.#foliage_rig_by_id.delete(rig_id);
2091
+ }
2092
+
2093
+ /**
2094
+ * @param {{ rig_id: number, rig: import("./foliage/FoliageWindRig.js").FoliageWindRig }} pending
2095
+ * @returns {boolean}
2096
+ */
2097
+ #try_complete_foliage_rig(pending) {
2098
+ const rows = this.#scene_context.rows;
2099
+ const dataset = rows.dataset;
2100
+ const rig = pending.rig;
2101
+ const rig_id = pending.rig_id;
2102
+
2103
+ if (!rows.has(rig.root)) {
2104
+ return false;
2105
+ }
2106
+
2107
+ const src_joints = rig.joints;
2108
+ const records = new Array(src_joints.length);
2109
+
2110
+ for (let i = 0; i < src_joints.length; i++) {
2111
+ const j = src_joints[i];
2112
+ const target = j.target;
2113
+ assert.isNonNegativeInteger(target, `foliage rig joint ${i} target`);
2114
+
2115
+ if (!rows.has(target)) {
2116
+ return false;
2117
+ }
2118
+
2119
+ records[i] = {
2120
+ rest_rotation: rest_rotation_of(dataset, target),
2121
+ branch_axis: j.branch_axis,
2122
+ compliance: j.compliance,
2123
+ angular_displacement: [0, 0, 0],
2124
+ natural_frequency: j.natural_frequency,
2125
+ angular_velocity: [0, 0, 0],
2126
+ damping_ratio: j.damping_ratio,
2127
+ node: gpu_authority_held(dataset, target, GPUStateAuthorityFlags.TransformAttachment)
2128
+ ? GPU_DATABASE_NULL
2129
+ : row_of_entity(target),
2130
+ rig: rig_id,
2131
+ max_angle: j.max_angle,
2132
+ turbulence: j.turbulence,
2133
+ flutter_phase: j.flutter_phase ?? 0,
2134
+ };
2135
+ }
2136
+
2137
+ const joints_first = this.#database.get('animation_foliage_joints').add_run_records(records, FOLIAGE_JOINT_WRITER);
2138
+
2139
+ this.#database.get('animation_foliage_rigs').set_fields(
2140
+ rig_id,
2141
+ {
2142
+ joints_first,
2143
+ joint_count: records.length,
2144
+ root_node: row_of_entity(rig.root),
2145
+ },
2146
+ FOLIAGE_RIG_COMPLETE_WRITER
2147
+ );
2148
+
2149
+ this.#take_foliage_targets(rig_id, src_joints);
2150
+
2151
+ return true;
2152
+ }
2153
+
2154
+ /**
2155
+ * @param {number} rig_id
2156
+ * @param {Array<{target: number}>} joints
2157
+ */
2158
+ #take_foliage_targets(rig_id, joints) {
2159
+ const rows = this.#scene_context.rows;
2160
+ const dataset = rows.dataset;
2161
+ const driving = this.#foliage_rigs_driving;
2162
+
2163
+ const targets = [];
2164
+
2165
+ for (let i = 0; i < joints.length; i++) {
2166
+ const target = joints[i].target;
2167
+ if (targets.indexOf(target) !== -1) {
2168
+ continue;
2169
+ }
2170
+ targets.push(target);
2171
+
2172
+ let rigs = driving.get(target);
2173
+ if (rigs === undefined) {
2174
+ rigs = [];
2175
+ driving.set(target, rigs);
2176
+
2177
+ if (!this.#clips_driving.has(target)) {
2178
+ gpu_authority_declare(dataset, target);
2179
+ gpu_authority_grant(
2180
+ dataset,
2181
+ target,
2182
+ GPUStateAuthorityFlags.TransformAttachment | GPUStateAuthorityFlags.Transform64
2183
+ );
2184
+
2185
+ rows.mark_handover(target);
2186
+
2187
+ rows.for_each_descendant(target, descendant => {
2188
+ gpu_authority_declare(dataset, descendant);
2189
+ gpu_authority_grant(dataset, descendant, GPUStateAuthorityFlags.Transform64);
2190
+ });
2191
+
2192
+ dataset.addEntityEventListener(target, GPU_AUTHORITY_EVENT_HOLD_CHANGE, this.#hold_changed, this);
2193
+ }
2194
+ }
2195
+
2196
+ rigs.push(rig_id);
2197
+ }
2198
+
2199
+ this.#targets_by_foliage_rig.set(rig_id, targets);
2200
+ }
2201
+
2202
+ /**
2203
+ * @param {number} rig_id
2204
+ */
2205
+ #release_foliage_targets(rig_id) {
2206
+ const targets = this.#targets_by_foliage_rig.get(rig_id);
2207
+ if (targets === undefined) {
2208
+ return;
2209
+ }
2210
+
2211
+ this.#targets_by_foliage_rig.delete(rig_id);
2212
+
2213
+ const rows = this.#scene_context.rows;
2214
+ const dataset = rows.dataset;
2215
+ const driving = this.#foliage_rigs_driving;
2216
+
2217
+ for (let i = 0; i < targets.length; i++) {
2218
+ const target = targets[i];
2219
+ const rigs = driving.get(target);
2220
+
2221
+ rigs.splice(rigs.indexOf(rig_id), 1);
2222
+
2223
+ if (rigs.length > 0) {
2224
+ continue;
2225
+ }
2226
+
2227
+ driving.delete(target);
2228
+
2229
+ if (this.#clips_driving.has(target)) {
2230
+ continue;
2231
+ }
2232
+
2233
+ if (!dataset.entityExists(target)) {
2234
+ continue;
2235
+ }
2236
+
2237
+ dataset.removeEntityEventListener(target, GPU_AUTHORITY_EVENT_HOLD_CHANGE, this.#hold_changed, this);
2238
+
2239
+ const attachment = dataset.getComponent(target, TransformAttachment);
2240
+
2241
+ gpu_authority_revoke(dataset, target, GPUStateAuthorityFlags.TransformAttachment);
2242
+
2243
+ if (!this.#gpu_composed(target, dataset)) {
2244
+ gpu_authority_revoke(dataset, target, GPUStateAuthorityFlags.Transform64);
2245
+ }
2246
+
2247
+ rows.for_each_descendant(target, descendant => {
2248
+ if (!this.#gpu_composed(descendant, dataset)) {
2249
+ gpu_authority_revoke(dataset, descendant, GPUStateAuthorityFlags.Transform64);
2250
+ }
2251
+ });
2252
+
2253
+ rows.mark_local(target);
2254
+
2255
+ if (attachment !== undefined && attachment !== null) {
2256
+ dataset.sendEvent(target, TRANSFORM_ATTACHMENT_EVENT_CHANGE);
2257
+ }
2258
+ }
2259
+ }
2260
+
2261
+ /**
2262
+ * @param {number} entity
2263
+ * @param {object} fields
2264
+ * @param {GPURecordWriter} writer
2265
+ */
2266
+ #write_foliage_joints(entity, fields, writer) {
2267
+ const rigs = this.#foliage_rigs_driving.get(entity);
2268
+ if (rigs === undefined) {
2269
+ return;
2270
+ }
2271
+
2272
+ const rigs_table = this.#database.get('animation_foliage_rigs');
2273
+ const joints_table = this.#database.get('animation_foliage_joints');
2274
+
2275
+ for (let r = 0; r < rigs.length; r++) {
2276
+ const rig_id = rigs[r];
2277
+ const first = rigs_table.get_word(rig_id, FOLIAGE_RIG_JOINTS_FIRST_WORD);
2278
+ const joints = this.#foliage_rig_by_id.get(rig_id).rig.joints;
2279
+
2280
+ for (let i = 0; i < joints.length; i++) {
2281
+ if (joints[i].target === entity) {
2282
+ joints_table.set_fields(first + i, fields, writer);
2283
+ }
2284
+ }
2285
+ }
2286
+ }
2287
+
1885
2288
  /**
1886
2289
  * Drop a skin from the manager: its row, and with it the run of its joints — the skin's range
1887
2290
  * owns the run, so the table removes it — and every skinning binding pointing at this skin (so
@@ -2174,6 +2577,7 @@ export class GPUAnimationManager {
2174
2577
  update(cmd_ctx) {
2175
2578
  this.#drain_pending_skins();
2176
2579
  this.#drain_pending_clips();
2580
+ this.#drain_pending_foliage_rigs();
2177
2581
  this.#database.update(cmd_ctx);
2178
2582
  }
2179
2583
 
@@ -2195,6 +2599,14 @@ export class GPUAnimationManager {
2195
2599
  }
2196
2600
  }
2197
2601
 
2602
+ #drain_pending_foliage_rigs() {
2603
+ for (let i = this.#pending_foliage_rigs.length - 1; i >= 0; i--) {
2604
+ if (this.#try_complete_foliage_rig(this.#pending_foliage_rigs[i])) {
2605
+ this.#pending_foliage_rigs.splice(i, 1);
2606
+ }
2607
+ }
2608
+ }
2609
+
2198
2610
  /**
2199
2611
  * Run the per-frame skin-matrix-prep dispatch and advance the
2200
2612
  * ping-pong. Replaces the manual `shader_skin_matrix_prep.dispatch`
@@ -2359,13 +2771,16 @@ export class GPUAnimationManager {
2359
2771
  // Flush database + drain pending registrations.
2360
2772
  this.update(cmd_ctx);
2361
2773
 
2362
- // Only clip evaluation is conditional. Every scene needs current globals.
2774
+ // Only clip / foliage wind evaluation is conditional. Every scene needs current globals.
2363
2775
  const apply_groups = this.#database
2364
2776
  .get('animation_bindings')
2365
2777
  .dispatch_group_count(ANIMATION_APPLY_WORKGROUP_SIZE);
2778
+ const foliage_groups = this.#database
2779
+ .get('animation_foliage_joints')
2780
+ .dispatch_group_count(FOLIAGE_WIND_APPLY_WORKGROUP_SIZE);
2366
2781
 
2367
- if (apply_groups > 0) {
2368
- this.#encode_clip_passes(cmd_ctx, dt, apply_groups);
2782
+ if (apply_groups > 0 || foliage_groups > 0) {
2783
+ this.#encode_clip_passes(cmd_ctx, dt, apply_groups, foliage_groups);
2369
2784
  } else {
2370
2785
  // CPU uploads seed global with the previous pose. Even without clips,
2371
2786
  // compose current globals and advance prev_global before skinning/rendering.
@@ -2384,37 +2799,40 @@ export class GPUAnimationManager {
2384
2799
  const deformed = this.#scene_context.skinning.update(cmd_ctx);
2385
2800
 
2386
2801
  // Whether anything on the GPU moved a row this frame without the CPU knowing: a clip wrote
2387
- // a TRS, a skinning pass moved a clone. What follows the tick — bounds, the TLAS — is
2388
- // derived from rows, and this is what says the derivation is stale.
2389
- return apply_groups > 0 || deformed;
2802
+ // a TRS, a foliage wind bone deflected, or a skinning pass moved a clone.
2803
+ return apply_groups > 0 || foliage_groups > 0 || deformed;
2390
2804
  }
2391
2805
 
2392
2806
  /**
2393
- * Encode the clip-driven passes: GPU tick (advances
2394
- * `clip.time`), track apply into the pose accumulator, pose
2395
- * resolve into node TRS, and transform-hierarchy propagation.
2396
- * Split out of {@link tick} so the skin passes there run
2397
- * independently of the bound-track early-out.
2807
+ * Encode the clip-driven and foliage-fluid-wind passes: GPU tick (advances
2808
+ * `clip.time`), track apply and/or foliage fluid wind apply into the pose
2809
+ * accumulator, pose resolve into node TRS, and transform-hierarchy propagation.
2398
2810
  *
2399
2811
  * @param {ShadeGPUCommandContext} cmd_ctx
2400
2812
  * @param {number} dt clamped delta time, seconds
2401
- * @param {number} apply_groups dispatch group count for the
2402
- * apply pass — caller guarantees `> 0`
2813
+ * @param {number} apply_groups dispatch group count for the clip apply pass
2814
+ * @param {number} [foliage_groups=0] dispatch group count for the foliage wind apply pass
2403
2815
  */
2404
- #encode_clip_passes(cmd_ctx, dt, apply_groups) {
2816
+ #encode_clip_passes(cmd_ctx, dt, apply_groups, foliage_groups = 0) {
2405
2817
  // Tick: advance clip.time on the GPU.
2406
- const tick_groups = this.#database
2407
- .get('animation_clips')
2408
- .dispatch_group_count(ANIMATION_TICK_WORKGROUP_SIZE);
2409
- if (tick_groups > 0) {
2410
- shader_animation_tick.dispatch({
2411
- encoder: cmd_ctx,
2412
- group_count_x: tick_groups,
2413
- bindings: {
2414
- dt,
2415
- animation_database: this.#database.buffer,
2416
- },
2417
- });
2818
+ if (apply_groups > 0) {
2819
+ const tick_groups = this.#database
2820
+ .get('animation_clips')
2821
+ .dispatch_group_count(ANIMATION_TICK_WORKGROUP_SIZE);
2822
+ if (tick_groups > 0) {
2823
+ shader_animation_tick.dispatch({
2824
+ encoder: cmd_ctx,
2825
+ group_count_x: tick_groups,
2826
+ bindings: {
2827
+ dt,
2828
+ animation_database: this.#database.buffer,
2829
+ },
2830
+ });
2831
+ }
2832
+ }
2833
+
2834
+ if (foliage_groups > 0 && this.#scene_context.wind) {
2835
+ this.#scene_context.wind.update();
2418
2836
  }
2419
2837
 
2420
2838
  // Size the pose accumulator to cover every allocated row of
@@ -2426,7 +2844,7 @@ export class GPUAnimationManager {
2426
2844
  );
2427
2845
  this.ensure_pose_accumulator_capacity(transforms_table.element_capacity);
2428
2846
 
2429
- // ── Frame graph: apply → pose resolve → hierarchy propagate
2847
+ // ── Frame graph: apply → foliage_wind_apply → pose resolve → hierarchy propagate
2430
2848
  const graph = new FrameGraph("GPUAnimationManager/Tick");
2431
2849
  const gr_animation_database = graph_import_buffer(
2432
2850
  graph, this.#database.buffer, "animation_database"
@@ -2434,28 +2852,59 @@ export class GPUAnimationManager {
2434
2852
  const gr_scene_database = graph_import_buffer(
2435
2853
  graph, this.#scene_context.scene_database_buffer, "scene_database"
2436
2854
  );
2437
- const gr_materials = graph_import_buffer(
2438
- graph, this.#scene_context.materials.metadata_table.buffer, "materials"
2439
- );
2440
2855
  const gr_pose_accumulator = graph_import_buffer(
2441
2856
  graph, this.#pose_accumulator_buffer, "pose_accumulator"
2442
2857
  );
2443
2858
 
2444
- const apply_data = {};
2445
- const apply_pass = graph.add("animation/apply", apply_data, (data, resources, ctx) => {
2446
- shader_animation_apply.dispatch({
2447
- encoder: ctx.encoder,
2448
- group_count_x: apply_groups,
2449
- bindings: {
2859
+ let last_pose_accumulator = gr_pose_accumulator;
2860
+
2861
+ if (apply_groups > 0) {
2862
+ const gr_materials = graph_import_buffer(
2863
+ graph, this.#scene_context.materials.metadata_table.buffer, "materials"
2864
+ );
2865
+ const apply_data = {};
2866
+ const apply_pass = graph.add("animation/apply", apply_data, (data, resources, ctx) => {
2867
+ shader_animation_apply.dispatch({
2868
+ encoder: ctx.encoder,
2869
+ group_count_x: apply_groups,
2870
+ bindings: {
2871
+ animation_database: resources.get(data.animation_database),
2872
+ pose_accumulator: resources.get(data.pose_accumulator),
2873
+ materials: resources.get(data.materials),
2874
+ },
2875
+ });
2876
+ });
2877
+ apply_data.animation_database = apply_pass.read(gr_animation_database);
2878
+ apply_data.materials = apply_pass.write(apply_pass.read(gr_materials));
2879
+ apply_data.pose_accumulator = apply_pass.write(apply_pass.read(last_pose_accumulator));
2880
+ last_pose_accumulator = apply_data.pose_accumulator;
2881
+ }
2882
+
2883
+ if (foliage_groups > 0) {
2884
+ const foliage_data = {};
2885
+ const foliage_pass = graph.add("animation/foliage_wind_apply", foliage_data, (data, resources, ctx) => {
2886
+ const bindings = {
2887
+ dt,
2888
+ scene_database: resources.get(data.scene_database),
2450
2889
  animation_database: resources.get(data.animation_database),
2451
2890
  pose_accumulator: resources.get(data.pose_accumulator),
2452
- materials: resources.get(data.materials),
2453
- },
2891
+ };
2892
+ this.#scene_context.wind.bind(bindings);
2893
+ const switches = ShaderSwitchSet.EMPTY.with(
2894
+ WIND_FIELD_UNIFORM,
2895
+ this.#scene_context.wind.cascade_count === 0
2896
+ );
2897
+ shader_foliage_wind_apply.variant(switches).dispatch({
2898
+ encoder: ctx.encoder,
2899
+ group_count_x: foliage_groups,
2900
+ bindings,
2901
+ });
2454
2902
  });
2455
- });
2456
- apply_data.animation_database = apply_pass.read(gr_animation_database);
2457
- apply_data.materials = apply_pass.write(apply_pass.read(gr_materials));
2458
- apply_data.pose_accumulator = apply_pass.write(apply_pass.read(gr_pose_accumulator));
2903
+ foliage_data.scene_database = foliage_pass.read(gr_scene_database);
2904
+ foliage_data.animation_database = foliage_pass.write(foliage_pass.read(gr_animation_database));
2905
+ foliage_data.pose_accumulator = foliage_pass.write(foliage_pass.read(last_pose_accumulator));
2906
+ last_pose_accumulator = foliage_data.pose_accumulator;
2907
+ }
2459
2908
 
2460
2909
  const resolve_data = {};
2461
2910
  const resolve_pass = graph.add("animation/pose_resolve", resolve_data, (data, resources, ctx) => {
@@ -2470,7 +2919,7 @@ export class GPUAnimationManager {
2470
2919
  });
2471
2920
  });
2472
2921
  resolve_data.scene_database = resolve_pass.write(resolve_pass.read(gr_scene_database));
2473
- resolve_data.pose_accumulator = resolve_pass.write(resolve_pass.read(apply_data.pose_accumulator));
2922
+ resolve_data.pose_accumulator = resolve_pass.write(resolve_pass.read(last_pose_accumulator));
2474
2923
 
2475
2924
  graph_scene_update_transform_hierarchy({
2476
2925
  graph,
@@ -2487,8 +2936,12 @@ export class GPUAnimationManager {
2487
2936
  for (const clip_id of Array.from(this.#targets_by_clip.keys())) {
2488
2937
  this.#release_targets(clip_id);
2489
2938
  }
2939
+ for (const rig_id of Array.from(this.#targets_by_foliage_rig.keys())) {
2940
+ this.#release_foliage_targets(rig_id);
2941
+ }
2490
2942
 
2491
2943
  this.#playback_by_clip.clear();
2944
+ this.#foliage_rig_by_id.clear();
2492
2945
 
2493
2946
  this.#database.destroy();
2494
2947
  for (let i = 0; i < 2; i++) {