@woosh/meep-engine 3.58.0 → 3.59.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 (609) hide show
  1. package/editor/particles/effect/ParticleEffectDocument.d.ts +162 -43
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +450 -43
  4. package/editor/particles/effect/ParticleReferenceSimulation.d.ts +12 -3
  5. package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
  6. package/editor/particles/effect/ParticleReferenceSimulation.js +78 -23
  7. package/editor/particles/effect/make_starter_particle_effect.js +17 -17
  8. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts +3 -3
  9. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  10. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +224 -67
  11. package/editor/view/particles/effect/ParticleGraphEditorView.d.ts.map +1 -1
  12. package/editor/view/particles/effect/ParticleGraphEditorView.js +44 -11
  13. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts +2 -1
  14. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  15. package/editor/view/particles/effect/ParticleNodeParametersView.js +46 -16
  16. package/editor/view/particles/effect/ParticlePreviewView.js +2 -2
  17. package/editor/view/particles/effect/particle-editor.css +77 -68
  18. package/package.json +1 -1
  19. package/src/engine/Engine.d.ts.map +1 -1
  20. package/src/engine/Engine.js +2 -2
  21. package/src/engine/ecs/EntityManager.d.ts +29 -5
  22. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  23. package/src/engine/ecs/EntityManager.js +37 -1
  24. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  25. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +4 -0
  26. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +74 -17
  27. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -1
  28. package/src/engine/graphics/ecs/particles/ParticleEffect.js +156 -25
  29. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +13 -3
  30. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -1
  31. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +59 -13
  32. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts +3 -3
  33. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.js +9 -9
  34. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_2_3.d.ts +15 -0
  35. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_2_3.d.ts.map +1 -0
  36. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_2_3.js +78 -0
  37. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +2 -0
  38. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  39. package/src/engine/graphics/ecs/trail3d/Trail3D.js +2 -0
  40. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +1 -1
  41. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +1 -1
  42. package/src/engine/graphics/trail/tube/TubeX.d.ts +5 -3
  43. package/src/engine/graphics/trail/tube/TubeX.d.ts.map +1 -1
  44. package/src/engine/graphics/trail/tube/TubeX.js +5 -3
  45. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts +3 -2
  46. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts.map +1 -1
  47. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +9 -8
  48. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +65 -4
  49. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  50. package/src/engine/graphics3/GPUParticleEmitterSystem.js +1351 -904
  51. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts +1 -1
  52. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +13 -13
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/generation/foliage/FOLIAGE_DESIGN.md +26 -5
  55. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +35 -0
  56. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +2 -1
  57. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +552 -0
  58. package/src/generation/foliage/analysis/tree_crown_opacity.d.ts.map +1 -1
  59. package/src/generation/foliage/analysis/tree_crown_opacity.js +2 -1
  60. package/src/generation/foliage/analysis/tree_render_cost.d.ts +5 -3
  61. package/src/generation/foliage/analysis/tree_render_cost.d.ts.map +1 -1
  62. package/src/generation/foliage/analysis/tree_render_cost.js +8 -7
  63. package/src/generation/foliage/asset/TreeAsset.d.ts +17 -0
  64. package/src/generation/foliage/asset/TreeAsset.d.ts.map +1 -1
  65. package/src/generation/foliage/asset/TreeAsset.js +20 -0
  66. package/src/generation/foliage/asset/TreeSpeciesCache.d.ts +69 -0
  67. package/src/generation/foliage/asset/TreeSpeciesCache.d.ts.map +1 -0
  68. package/src/generation/foliage/asset/TreeSpeciesCache.js +147 -0
  69. package/src/generation/foliage/asset/generate_tree.d.ts +10 -0
  70. package/src/generation/foliage/asset/generate_tree.d.ts.map +1 -1
  71. package/src/generation/foliage/asset/generate_tree.js +57 -29
  72. package/src/generation/foliage/asset/place_tree.d.ts +2 -1
  73. package/src/generation/foliage/asset/place_tree.d.ts.map +1 -1
  74. package/src/generation/foliage/asset/place_tree.js +2 -1
  75. package/src/generation/foliage/asset/tree_lod_plan.d.ts +4 -2
  76. package/src/generation/foliage/asset/tree_lod_plan.d.ts.map +1 -1
  77. package/src/generation/foliage/asset/tree_lod_plan.js +12 -14
  78. package/src/generation/foliage/asset/tree_shoot_instances.d.ts +119 -0
  79. package/src/generation/foliage/asset/tree_shoot_instances.d.ts.map +1 -0
  80. package/src/generation/foliage/asset/tree_shoot_instances.js +410 -0
  81. package/src/generation/foliage/asset/tree_shoot_prototypes.d.ts +155 -0
  82. package/src/generation/foliage/asset/tree_shoot_prototypes.d.ts.map +1 -0
  83. package/src/generation/foliage/asset/tree_shoot_prototypes.js +251 -0
  84. package/src/generation/foliage/config/TreeGrowth.d.ts +10 -0
  85. package/src/generation/foliage/config/TreeGrowth.d.ts.map +1 -0
  86. package/src/generation/foliage/config/TreeGrowth.js +18 -0
  87. package/src/generation/foliage/config/TreeLODConfig.d.ts +6 -0
  88. package/src/generation/foliage/config/TreeLODConfig.d.ts.map +1 -1
  89. package/src/generation/foliage/config/TreeLODConfig.js +7 -0
  90. package/src/generation/foliage/index.d.ts +3 -0
  91. package/src/generation/foliage/index.js +3 -0
  92. package/src/generation/foliage/material/foliage_tile.d.ts +6 -6
  93. package/src/generation/foliage/material/foliage_tile.js +3 -3
  94. package/src/generation/foliage/material/tree_cluster_atlas.d.ts +44 -0
  95. package/src/generation/foliage/material/tree_cluster_atlas.d.ts.map +1 -0
  96. package/src/generation/foliage/material/tree_cluster_atlas.js +37 -0
  97. package/src/generation/foliage/mesh/foliage_collect_attachments.js +2 -2
  98. package/src/generation/foliage/mesh/foliage_scale_spread.d.ts +14 -0
  99. package/src/generation/foliage/mesh/foliage_scale_spread.d.ts.map +1 -0
  100. package/src/generation/foliage/mesh/foliage_scale_spread.js +15 -0
  101. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts +8 -7
  102. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts.map +1 -1
  103. package/src/generation/foliage/mesh/tree_cluster_representatives.js +85 -40
  104. package/src/generation/foliage/mesh/tree_clusters.d.ts +26 -5
  105. package/src/generation/foliage/mesh/tree_clusters.d.ts.map +1 -1
  106. package/src/generation/foliage/mesh/tree_clusters.js +52 -39
  107. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
  108. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +32 -54
  109. package/src/generation/foliage/presets/make_tree_species_preset.d.ts +6 -1
  110. package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -1
  111. package/src/generation/foliage/presets/make_tree_species_preset.js +157 -3
  112. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts +19 -0
  113. package/src/generation/foliage/skeleton/TreeSkeleton.d.ts.map +1 -1
  114. package/src/generation/foliage/skeleton/TreeSkeleton.js +41 -0
  115. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.d.ts +5 -0
  116. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.d.ts.map +1 -1
  117. package/src/generation/foliage/skeleton/tree_skeleton_compute_joint_mechanics.js +8 -1
  118. package/src/generation/foliage/skeleton/tree_skeleton_copy_branches.d.ts +70 -0
  119. package/src/generation/foliage/skeleton/tree_skeleton_copy_branches.d.ts.map +1 -0
  120. package/src/generation/foliage/skeleton/tree_skeleton_copy_branches.js +171 -0
  121. package/src/generation/foliage/skeleton/tree_skeleton_extend_branch.d.ts +17 -0
  122. package/src/generation/foliage/skeleton/tree_skeleton_extend_branch.d.ts.map +1 -0
  123. package/src/generation/foliage/skeleton/tree_skeleton_extend_branch.js +79 -0
  124. package/src/generation/foliage/skeleton/tree_skeleton_fit_crown_frame.d.ts +12 -0
  125. package/src/generation/foliage/skeleton/tree_skeleton_fit_crown_frame.d.ts.map +1 -0
  126. package/src/generation/foliage/skeleton/tree_skeleton_fit_crown_frame.js +56 -0
  127. package/src/generation/foliage/skeleton/tree_skeleton_floor_girth.d.ts +11 -0
  128. package/src/generation/foliage/skeleton/tree_skeleton_floor_girth.d.ts.map +1 -0
  129. package/src/generation/foliage/skeleton/tree_skeleton_floor_girth.js +38 -0
  130. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts +4 -11
  131. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -1
  132. package/src/generation/foliage/skeleton/tree_skeleton_grow.js +8 -2034
  133. package/src/generation/foliage/skeleton/tree_skeleton_grow_framework.d.ts +22 -0
  134. package/src/generation/foliage/skeleton/tree_skeleton_grow_framework.d.ts.map +1 -0
  135. package/src/generation/foliage/skeleton/tree_skeleton_grow_framework.js +2050 -0
  136. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.d.ts +10 -0
  137. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.d.ts.map +1 -1
  138. package/src/generation/foliage/skeleton/tree_skeleton_grow_shoots.js +27 -56
  139. package/src/shade/descriptor/pipeline/render/DepthStencilState.d.ts +4 -0
  140. package/src/shade/descriptor/pipeline/render/DepthStencilState.d.ts.map +1 -1
  141. package/src/shade/descriptor/pipeline/render/DepthStencilState.js +170 -144
  142. package/src/shade/descriptor/pipeline/render/MultisampleState.d.ts +4 -0
  143. package/src/shade/descriptor/pipeline/render/MultisampleState.d.ts.map +1 -1
  144. package/src/shade/descriptor/pipeline/render/MultisampleState.js +78 -65
  145. package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.d.ts.map +1 -1
  146. package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.js +176 -172
  147. package/src/shade/descriptor/pipeline/render/StencilFaceState.d.ts +4 -0
  148. package/src/shade/descriptor/pipeline/render/StencilFaceState.d.ts.map +1 -1
  149. package/src/shade/descriptor/pipeline/render/StencilFaceState.js +107 -88
  150. package/src/shade/playground/particle_ecs/README.md +9 -8
  151. package/src/shade/playground/particle_ecs/bonfire_editor.js +3 -3
  152. package/src/shade/playground/particle_ecs/bonfire_effects.d.ts +6 -6
  153. package/src/shade/playground/particle_ecs/bonfire_effects.js +6 -6
  154. package/src/shade/playground/particle_editor/README.md +14 -11
  155. package/src/shade/playground/particle_system/particle_prototype.js +18 -18
  156. package/src/shade/playground/particle_system/particle_scene.js +13 -13
  157. package/src/shade/playground/probe_clipmap/README.md +42 -0
  158. package/src/shade/playground/probe_clipmap/index.html +178 -0
  159. package/src/shade/playground/probe_clipmap/main.d.ts +8 -0
  160. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -0
  161. package/src/shade/playground/probe_clipmap/main.js +360 -0
  162. package/src/shade/renderer/Renderer.d.ts +3 -1
  163. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  164. package/src/shade/renderer/Renderer.js +94 -38
  165. package/src/shade/renderer/extension/ViewTextures.d.ts +2 -1
  166. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  167. package/src/shade/renderer/extension/ViewTextures.js +2 -1
  168. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  169. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  170. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  171. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  172. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  173. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +34 -12
  174. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  175. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +56 -15
  176. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +2 -2
  177. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
  178. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +13 -26
  179. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts +25 -2
  180. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.d.ts.map +1 -1
  181. package/src/shade/renderer/geometry/virtual/runtime/VGeoViewCut.js +54 -32
  182. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_VERDICT.d.ts +14 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_VERDICT.d.ts.map +1 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_VERDICT.js +37 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -1
  186. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +16 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts.map +1 -1
  188. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.js +2 -6
  189. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_descent.d.ts +131 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_descent.d.ts.map +1 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_descent.js +467 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.d.ts +24 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.d.ts.map +1 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.js +111 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_rule.d.ts +42 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_rule.d.ts.map +1 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_rule.js +404 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_stat.d.ts +16 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_stat.d.ts.map +1 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_stat.js +23 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_want.d.ts +17 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_want.d.ts.map +1 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_want.js +65 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -1
  205. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +14 -70
  206. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  207. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +13 -773
  208. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_cut_descent.d.ts +55 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_cut_descent.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_cut_descent.js +248 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
  212. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +15 -174
  213. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_probe_meta_pick2.d.ts.map +1 -1
  214. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_probe_meta_pick2.js +8 -24
  215. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_forward_indirect.d.ts.map +1 -1
  216. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_forward_indirect.js +1 -25
  217. package/src/shade/renderer/global_illumination/lpv/deprecated/chunk_lpv_get_visibility_mask.d.ts.map +1 -1
  218. package/src/shade/renderer/global_illumination/lpv/deprecated/chunk_lpv_get_visibility_mask.js +5 -23
  219. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +25 -4
  220. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  221. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +126 -8
  222. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +832 -4
  223. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts +7 -0
  224. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.d.ts.map +1 -1
  225. package/src/shade/renderer/global_illumination/probe_clipmap/brick/BRICK_CLIPMAP.js +8 -0
  226. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +16 -0
  227. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  228. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +9 -0
  229. package/src/shade/renderer/global_illumination/probe_clipmap/brick/{mesh/chunk_mesh_brick_object.d.ts → chunk_brick_object.d.ts} +8 -8
  230. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_object.d.ts.map +1 -0
  231. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_object.js +42 -0
  232. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_provider.d.ts +45 -0
  233. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_provider.d.ts.map +1 -0
  234. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_provider.js +93 -0
  235. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts +0 -7
  236. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.d.ts.map +1 -1
  237. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/MESH_BRICK_INSTANCE_STRUCT.js +0 -8
  238. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -4
  239. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts.map +1 -1
  240. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +5 -8
  241. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.d.ts.map +1 -1
  242. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/shader_mesh_brick_provider.js +13 -22
  243. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts +99 -0
  244. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.d.ts.map +1 -0
  245. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGEO_BRICK.js +139 -0
  246. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts +65 -0
  247. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.d.ts.map +1 -0
  248. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/VGeoBrickProvider.js +393 -0
  249. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts +17 -0
  250. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.d.ts.map +1 -0
  251. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_box.js +36 -0
  252. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts +29 -0
  253. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.d.ts.map +1 -0
  254. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_pair.js +108 -0
  255. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts +31 -0
  256. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.d.ts.map +1 -0
  257. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_texel.js +113 -0
  258. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts +36 -0
  259. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.d.ts.map +1 -0
  260. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/chunk_vgeo_brick_triangle.js +85 -0
  261. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts +23 -0
  262. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.d.ts.map +1 -0
  263. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_distance.js +273 -0
  264. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts +13 -0
  265. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.d.ts.map +1 -0
  266. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_gather.js +151 -0
  267. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts +13 -0
  268. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.d.ts.map +1 -0
  269. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_traverse.js +133 -0
  270. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts +22 -0
  271. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.d.ts.map +1 -0
  272. package/src/shade/renderer/global_illumination/probe_clipmap/brick/vgeo/shader_vgeo_brick_wait.js +135 -0
  273. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +20 -6
  274. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  275. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +152 -10
  276. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +7 -0
  277. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  278. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +8 -0
  279. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +14 -2
  280. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  281. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +50 -5
  282. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.d.ts +19 -0
  283. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.d.ts.map +1 -0
  284. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_cage.js +40 -0
  285. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +72 -0
  286. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -0
  287. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +343 -0
  288. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +29 -0
  289. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -0
  290. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +188 -0
  291. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +26 -0
  292. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -0
  293. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +132 -0
  294. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +4 -0
  295. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  296. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +26 -3
  297. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts +3 -0
  298. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.d.ts.map +1 -1
  299. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +8 -1
  300. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts +12 -0
  301. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts.map +1 -0
  302. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +101 -0
  303. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +1 -1
  304. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +1 -1
  305. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts +15 -0
  306. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -0
  307. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +175 -0
  308. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts +26 -0
  309. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.d.ts.map +1 -0
  310. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +210 -0
  311. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts +3 -3
  312. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +3 -3
  313. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts +2 -1
  314. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  315. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +5 -1
  316. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  317. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +3 -10
  318. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +5 -9
  319. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  320. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +9 -110
  321. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts +27 -0
  322. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.d.ts.map +1 -0
  323. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_hits.js +110 -0
  324. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts +13 -0
  325. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts.map +1 -1
  326. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.js +40 -0
  327. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts +11 -6
  328. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts.map +1 -1
  329. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.js +15 -8
  330. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts +9 -2
  331. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts.map +1 -1
  332. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.js +25 -11
  333. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  334. package/src/shade/renderer/particles/DESIGN.md +151 -42
  335. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +283 -0
  336. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +10 -2
  337. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  338. package/src/shade/renderer/particles/GPUParticleSystem.js +46 -8
  339. package/src/shade/renderer/particles/ParticleConstants.d.ts +23 -6
  340. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  341. package/src/shade/renderer/particles/ParticleConstants.js +25 -6
  342. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.js +5 -5
  343. package/src/shade/renderer/particles/bounds/shader_particle_bounds.js +187 -187
  344. package/src/shade/renderer/particles/data/PARTICLE_DATABASE_SPEC.d.ts +20 -9
  345. package/src/shade/renderer/particles/data/PARTICLE_DATABASE_SPEC.d.ts.map +1 -1
  346. package/src/shade/renderer/particles/data/PARTICLE_DATABASE_SPEC.js +36 -10
  347. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +8 -7
  348. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  349. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +25 -16
  350. package/src/shade/renderer/particles/data/PARTICLE_FIELD_BINDING.d.ts +51 -0
  351. package/src/shade/renderer/particles/data/PARTICLE_FIELD_BINDING.d.ts.map +1 -0
  352. package/src/shade/renderer/particles/data/PARTICLE_FIELD_BINDING.js +56 -0
  353. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -1
  354. package/src/shade/renderer/particles/data/particle_emitter_record.js +2 -0
  355. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +1 -1
  356. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +1 -1
  357. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts +22 -11
  358. package/src/shade/renderer/particles/graph/ParticleNodeDescription.d.ts.map +1 -1
  359. package/src/shade/renderer/particles/graph/ParticleNodeDescription.js +14 -11
  360. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts +4 -4
  361. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  362. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +59 -24
  363. package/src/shade/renderer/particles/graph/ParticleValueType.d.ts +3 -3
  364. package/src/shade/renderer/particles/graph/ParticleValueType.js +287 -287
  365. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts +13 -6
  366. package/src/shade/renderer/particles/graph/compile_particle_graph.d.ts.map +1 -1
  367. package/src/shade/renderer/particles/graph/compile_particle_graph.js +46 -27
  368. package/src/shade/renderer/particles/graph/infer_particle_graph_types.d.ts +8 -2
  369. package/src/shade/renderer/particles/graph/infer_particle_graph_types.d.ts.map +1 -1
  370. package/src/shade/renderer/particles/graph/infer_particle_graph_types.js +240 -234
  371. package/src/shade/renderer/particles/graph/make_particle_group.d.ts +1 -1
  372. package/src/shade/renderer/particles/graph/make_particle_group.js +1 -1
  373. package/src/shade/renderer/particles/graph/particle_graph_authoring.d.ts +3 -2
  374. package/src/shade/renderer/particles/graph/particle_graph_authoring.d.ts.map +1 -1
  375. package/src/shade/renderer/particles/graph/particle_graph_authoring.js +3 -2
  376. package/src/shade/renderer/particles/graph/particle_graph_distributions.js +170 -170
  377. package/src/shade/renderer/particles/graph/particle_graph_json.d.ts +25 -16
  378. package/src/shade/renderer/particles/graph/particle_graph_json.d.ts.map +1 -1
  379. package/src/shade/renderer/particles/graph/particle_graph_json.js +16 -2
  380. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +29 -15
  381. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  382. package/src/shade/renderer/particles/graph/particle_node_parameters.js +54 -22
  383. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  384. package/src/shade/renderer/particles/graph/particle_node_presentation.js +18 -8
  385. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts +9 -2
  386. package/src/shade/renderer/particles/graph/validate_particle_graph.d.ts.map +1 -1
  387. package/src/shade/renderer/particles/graph/validate_particle_graph.js +70 -32
  388. package/src/shade/renderer/particles/graph_particles.d.ts +9 -4
  389. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  390. package/src/shade/renderer/particles/graph_particles.js +27 -4
  391. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +7 -6
  392. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  393. package/src/shade/renderer/particles/isa/InstructionStream.js +17 -16
  394. package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts +17 -0
  395. package/src/shade/renderer/particles/isa/ParticleAssembler.d.ts.map +1 -1
  396. package/src/shade/renderer/particles/isa/ParticleAssembler.js +35 -0
  397. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts +26 -6
  398. package/src/shade/renderer/particles/isa/ParticleProgram.d.ts.map +1 -1
  399. package/src/shade/renderer/particles/isa/ParticleProgram.js +61 -9
  400. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +55 -4
  401. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  402. package/src/shade/renderer/particles/isa/ParticleVMISA.js +79 -10
  403. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +20 -6
  404. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  405. package/src/shade/renderer/particles/isa/particle_assembly.js +136 -25
  406. package/src/shade/renderer/particles/isa/particle_link_global_fields.d.ts +20 -0
  407. package/src/shade/renderer/particles/isa/particle_link_global_fields.d.ts.map +1 -0
  408. package/src/shade/renderer/particles/isa/particle_link_global_fields.js +46 -0
  409. package/src/shade/renderer/particles/isa/validate_particle_program.js +8 -8
  410. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts +62 -28
  411. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  412. package/src/shade/renderer/particles/layout/ParticleLayout.js +102 -62
  413. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.d.ts.map +1 -1
  414. package/src/shade/renderer/particles/optimizer/dag/optimize_particle_program_vector.js +2 -0
  415. package/src/shade/renderer/particles/optimizer/dag/particle_vector_groups.js +1 -1
  416. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +4 -3
  417. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lower.js +2 -2
  418. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts +3 -3
  419. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +11 -11
  420. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +4 -4
  421. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  422. package/src/shade/renderer/particles/optimizer/optimize_particle_program.js +5 -4
  423. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.d.ts +1 -1
  424. package/src/shade/renderer/particles/optimizer/particle_integer_bounds.js +1 -1
  425. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts +4 -4
  426. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  427. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +13 -11
  428. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +7 -7
  429. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +3 -2
  430. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  431. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +5 -4
  432. package/src/shade/renderer/particles/optimizer/pass_allocate_registers.d.ts.map +1 -1
  433. package/src/shade/renderer/particles/optimizer/pass_dedup_constants.d.ts.map +1 -1
  434. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.d.ts.map +1 -1
  435. package/src/shade/renderer/particles/optimizer/pass_eliminate_dead_code.js +51 -51
  436. package/src/shade/renderer/particles/optimizer/pass_fold_constants.d.ts.map +1 -1
  437. package/src/shade/renderer/particles/optimizer/pass_fold_constants.js +5 -5
  438. package/src/shade/renderer/particles/optimizer/pass_inline_constants.d.ts.map +1 -1
  439. package/src/shade/renderer/particles/optimizer/pass_narrow_widths.d.ts.map +1 -1
  440. package/src/shade/renderer/particles/optimizer/pass_pack_registers.d.ts.map +1 -1
  441. package/src/shade/renderer/particles/optimizer/pass_peephole.d.ts.map +1 -1
  442. package/src/shade/renderer/particles/optimizer/pass_propagate_copies.d.ts.map +1 -1
  443. package/src/shade/renderer/particles/optimizer/pass_schedule.d.ts.map +1 -1
  444. package/src/shade/renderer/particles/optimizer/pass_schedule.js +2 -2
  445. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.d.ts.map +1 -1
  446. package/src/shade/renderer/particles/optimizer/pass_share_subexpressions.js +5 -4
  447. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +93 -22
  448. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  449. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +336 -29
  450. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +43 -3
  451. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -1
  452. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +43 -3
  453. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +56 -26
  454. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  455. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +89 -33
  456. package/src/shade/renderer/particles/runtime/ParticleGlobalFields.d.ts +85 -0
  457. package/src/shade/renderer/particles/runtime/ParticleGlobalFields.d.ts.map +1 -0
  458. package/src/shade/renderer/particles/runtime/ParticleGlobalFields.js +221 -0
  459. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts +143 -18
  460. package/src/shade/renderer/particles/runtime/ProgramHeap.d.ts.map +1 -1
  461. package/src/shade/renderer/particles/runtime/ProgramHeap.js +378 -28
  462. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts +19 -7
  463. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  464. package/src/shade/renderer/particles/runtime/create_particle_effect.js +22 -9
  465. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +8 -8
  466. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +1 -1
  467. package/src/shade/renderer/particles/shaders/chunk_particle_setup_context.d.ts +3 -0
  468. package/src/shade/renderer/particles/shaders/chunk_particle_setup_context.d.ts.map +1 -1
  469. package/src/shade/renderer/particles/shaders/chunk_particle_setup_context.js +4 -0
  470. package/src/shade/renderer/particles/shaders/shader_particle_field_bind.d.ts +30 -0
  471. package/src/shade/renderer/particles/shaders/shader_particle_field_bind.d.ts.map +1 -0
  472. package/src/shade/renderer/particles/shaders/shader_particle_field_bind.js +121 -0
  473. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.d.ts.map +1 -1
  474. package/src/shade/renderer/particles/vm/PARTICLE_VM_CONTEXT_STRUCT.js +3 -1
  475. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +12 -4
  476. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  477. package/src/shade/renderer/particles/vm/ParticleVMReference.js +48 -11
  478. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  479. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +36 -14
  480. package/src/shade/renderer/postprocess/PostProcess.d.ts.map +1 -1
  481. package/src/shade/renderer/postprocess/PostProcess.js +2 -1
  482. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +31 -19
  483. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
  484. package/src/shade/renderer/postprocess/gtao/GTAO.js +44 -30
  485. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
  486. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +16 -2
  487. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  488. package/src/shade/renderer/postprocess/nss/NSS.d.ts.map +1 -1
  489. package/src/shade/renderer/postprocess/nss/NSS.js +4 -3
  490. package/src/shade/renderer/postprocess/ssr/SSR.d.ts +7 -1
  491. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  492. package/src/shade/renderer/postprocess/ssr/SSR.js +16 -0
  493. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_add_hit_irradiance.d.ts +20 -2
  494. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_add_hit_irradiance.d.ts.map +1 -1
  495. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_add_hit_irradiance.js +53 -3
  496. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_sample_radiance.d.ts +10 -2
  497. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_sample_radiance.d.ts.map +1 -1
  498. package/src/shade/renderer/postprocess/ssr/resolve/chunk_ssr_sample_radiance.js +31 -3
  499. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.d.ts.map +1 -1
  500. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader.js +17 -11
  501. package/src/shade/renderer/postprocess/taa/TAA.d.ts +4 -2
  502. package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
  503. package/src/shade/renderer/postprocess/taa/TAA.js +6 -1
  504. package/src/shade/renderer/postprocess/taa/chunk_fsr2_compute_depth_clip.d.ts.map +1 -1
  505. package/src/shade/renderer/postprocess/taa/chunk_fsr2_compute_depth_clip.js +10 -5
  506. package/src/shade/renderer/postprocess/taa/shader_taa.d.ts.map +1 -1
  507. package/src/shade/renderer/postprocess/taa/shader_taa.js +15 -12
  508. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  509. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +26 -17
  510. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect.d.ts +4 -3
  511. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect.d.ts.map +1 -1
  512. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect.js +6 -4
  513. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts +12 -0
  514. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts.map +1 -0
  515. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.js +57 -0
  516. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +4 -2
  517. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  518. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +4 -2
  519. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +8 -2
  520. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  521. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +28 -15
  522. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw.d.ts +2 -1
  523. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw.d.ts.map +1 -1
  524. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw.js +19 -3
  525. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.d.ts.map +1 -1
  526. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +4 -2
  527. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts +3 -1
  528. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  529. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +27 -14
  530. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.d.ts +2 -1
  531. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.d.ts.map +1 -1
  532. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +19 -3
  533. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.d.ts +2 -8
  534. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.d.ts.map +1 -1
  535. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_bounds.js +25 -52
  536. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_positions.d.ts +15 -0
  537. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_positions.d.ts.map +1 -0
  538. package/src/shade/renderer/shader/chunk/geometry/meshlet/chunk_read_meshlet_triangle_positions.js +52 -0
  539. package/src/shade/renderer/shader/chunk/geometry/triangle/TRIANGLE_POSITIONS_STRUCT.d.ts +7 -0
  540. package/src/shade/renderer/shader/chunk/geometry/triangle/TRIANGLE_POSITIONS_STRUCT.d.ts.map +1 -0
  541. package/src/shade/renderer/shader/chunk/geometry/triangle/TRIANGLE_POSITIONS_STRUCT.js +12 -0
  542. package/src/shade/renderer/shader/chunk/grid/chunk_index_to_grid2d_reciprocal.d.ts +22 -0
  543. package/src/shade/renderer/shader/chunk/grid/chunk_index_to_grid2d_reciprocal.d.ts.map +1 -0
  544. package/src/shade/renderer/shader/chunk/grid/chunk_index_to_grid2d_reciprocal.js +37 -0
  545. package/src/shade/renderer/shader/chunk/light/lpv/depth/chunk_lpv_mask_weights_by_visibility.d.ts.map +1 -1
  546. package/src/shade/renderer/shader/chunk/light/lpv/depth/chunk_lpv_mask_weights_by_visibility.js +26 -60
  547. package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.d.ts +23 -0
  548. package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.d.ts.map +1 -0
  549. package/src/shade/renderer/shader/chunk/light/probe/chunk_probe_visibility_weight.js +54 -0
  550. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts +25 -0
  551. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts.map +1 -0
  552. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.js +43 -0
  553. package/src/shade/renderer/shader/chunk/random/chunk_jitter_from_vectors.d.ts +14 -0
  554. package/src/shade/renderer/shader/chunk/random/chunk_jitter_from_vectors.d.ts.map +1 -0
  555. package/src/shade/renderer/shader/chunk/random/chunk_jitter_from_vectors.js +37 -0
  556. package/src/shade/renderer/shader/chunk/random/reservoir/chunk_pick2_wrs_mat2x4.d.ts +27 -0
  557. package/src/shade/renderer/shader/chunk/random/reservoir/chunk_pick2_wrs_mat2x4.d.ts.map +1 -0
  558. package/src/shade/renderer/shader/chunk/random/reservoir/chunk_pick2_wrs_mat2x4.js +61 -0
  559. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/chunk_resolve_irradiance_sh_to_specular.d.ts +21 -0
  560. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/chunk_resolve_irradiance_sh_to_specular.d.ts.map +1 -0
  561. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/chunk_resolve_irradiance_sh_to_specular.js +41 -0
  562. package/src/shade/renderer/texture/util/texture_fill_rectangle.d.ts.map +1 -1
  563. package/src/shade/renderer/texture/util/texture_fill_rectangle.js +282 -267
  564. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +8 -4
  565. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  566. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +36 -36
  567. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +6 -1
  568. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
  569. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +498 -484
  570. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +15 -2
  571. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -1
  572. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +57 -3
  573. package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.d.ts.map +1 -1
  574. package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.js +197 -191
  575. package/src/shade/renderer/volumetrics/taa/shader_volumetrics_taa.js +4 -4
  576. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +2 -1
  577. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  578. package/src/shade/renderer/water/GPUWaterRenderer.js +5 -1
  579. package/src/shade/renderer/water/chunk_water_gi.d.ts +13 -3
  580. package/src/shade/renderer/water/chunk_water_gi.d.ts.map +1 -1
  581. package/src/shade/renderer/water/chunk_water_gi.js +47 -5
  582. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  583. package/src/shade/renderer/water/shader_water.d.ts +3 -2
  584. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  585. package/src/shade/renderer/water/shader_water.js +9 -3
  586. package/src/shade/renderer/geometry/sdf/SDF_BUILD_SETTINGS_STRUCT.d.ts +0 -3
  587. package/src/shade/renderer/geometry/sdf/SDF_BUILD_SETTINGS_STRUCT.d.ts.map +0 -1
  588. package/src/shade/renderer/geometry/sdf/SFD_BUILD_WORKGROUP_SIZE.d.ts +0 -2
  589. package/src/shade/renderer/geometry/sdf/SFD_BUILD_WORKGROUP_SIZE.d.ts.map +0 -1
  590. package/src/shade/renderer/geometry/sdf/chunk_blas_query_sdf.d.ts +0 -8
  591. package/src/shade/renderer/geometry/sdf/chunk_blas_query_sdf.d.ts.map +0 -1
  592. package/src/shade/renderer/geometry/sdf/chunk_blas_query_volume_sign.d.ts +0 -3
  593. package/src/shade/renderer/geometry/sdf/chunk_blas_query_volume_sign.d.ts.map +0 -1
  594. package/src/shade/renderer/geometry/sdf/shader_build_sdf.d.ts +0 -3
  595. package/src/shade/renderer/geometry/sdf/shader_build_sdf.d.ts.map +0 -1
  596. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_object.d.ts.map +0 -1
  597. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_object.js +0 -42
  598. package/src/shade/renderer/particles/shaders/shader_particle_init_free_list.d.ts +0 -31
  599. package/src/shade/renderer/particles/shaders/shader_particle_init_free_list.d.ts.map +0 -1
  600. package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts +0 -42
  601. package/src/shade/renderer/shadow/vsm/VSMMoverTracker.d.ts.map +0 -1
  602. package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts +0 -54
  603. package/src/shade/renderer/shadow/vsm/VSM_MOVER_LAYOUT.d.ts.map +0 -1
  604. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts +0 -14
  605. package/src/shade/renderer/shadow/vsm/shader/chunk_vsm_append_mover.d.ts.map +0 -1
  606. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts +0 -30
  607. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_movers.d.ts.map +0 -1
  608. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts +0 -23
  609. package/src/shade/renderer/shadow/vsm/shader/shader_vsm_skinned_movers.d.ts.map +0 -1
@@ -0,0 +1,467 @@
1
+ import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
2
+ import { VGEO_CUT_STAT } from "../layout/VGEO_CUT_STAT.js";
3
+ import { VGEO_GROUP_ROW_OFFSET } from "../layout/VGEO_GROUP_ROW_OFFSET.js";
4
+ import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
5
+ import { VGEO_PAGE_ROW_OFFSET } from "../layout/VGEO_PAGE_ROW_OFFSET.js";
6
+ import { VGEO_PARENT_ROW_OFFSET } from "../layout/VGEO_PARENT_ROW_OFFSET.js";
7
+ import { chunk_vgeo_cut_claim } from "./chunk_vgeo_cut_claim.js";
8
+ import { chunk_vgeo_cut_rule } from "./chunk_vgeo_cut_rule.js";
9
+ import { chunk_vgeo_cut_want } from "./chunk_vgeo_cut_want.js";
10
+ import { VGEO_CUT_FLAG_COARSEN } from "./VGEO_CUT_FLAG_COARSEN.js";
11
+ import { VGEO_CUT_WORKGROUP_SIZE } from "./VGEO_CUT_WORKGROUP_SIZE.js";
12
+
13
+ /**
14
+ * The virtual-geometry cut's descent — design §7's pass, as a descent that lives inside one dispatch — for every
15
+ * cut: the camera's (`shader_vgeo_cut_traverse`) and a box cut's. A kernel is this chunk with the rule's two culls
16
+ * and what taking a cluster means to it:
17
+ *
18
+ * ```wgsl
19
+ * fn vg_cut_sphere_outside(instance_base: u32, sphere: vec4<f32>) -> bool
20
+ * fn vg_cut_box_outside(instance_base: u32, lower: vec3<f32>, upper: vec3<f32>) -> bool
21
+ * fn vg_cut_take(instance_base: u32, page_row: u32, verdict: VGVerdict)
22
+ * ```
23
+ *
24
+ * `vg_cut_take` is called for a cluster in the cut, a stand-in's too (`VGEO_CUT_VERDICT` TAKE, CLAMP, HELD); the
25
+ * descent itself counts the stand-ins and wants what a clamp could not reach.
26
+ *
27
+ * ## The rule
28
+ *
29
+ * A cluster is in the cut iff
30
+ *
31
+ * > `own group selectable AND project(parent) > tau AND (project(self) <= tau OR child group not
32
+ * > selectable)`
33
+ *
34
+ * which is {@link chunk_vgeo_cut_rule}'s.
35
+ *
36
+ * ## The shape
37
+ *
38
+ * The loop over depth is *inside* this kernel: a dispatch is a spill generation rather than a level
39
+ * of the descent. Depth is what a cut costs. Measured on a 28M-face container at tau = 1 on a 4090:
40
+ * the descent converges at **39 levels**, carrying 15,027 items — an average frontier of 385 items,
41
+ * or **six workgroups of 64 on a 128-SM part** — and an empty prepare/traverse pair costs 3.9 us
42
+ * whatever it contains. Page depth grows like log2(triangles), so a dispatch per level gets *worse*
43
+ * with better assets and no better with a faster GPU.
44
+ *
45
+ * What a lane cannot do is wait for another workgroup: WebGPU guarantees no forward progress across
46
+ * workgroups, so persistent threads over an MPMC queue — Nanite's answer — is unbounded waiting.
47
+ * What a lane *can* do is cooperate with the other lanes of its own subgroup, and that is enough:
48
+ *
49
+ * - Every lane executes its item and says how many children it produced. No lane walks its own
50
+ * subtree while its neighbours idle; production is a **count**, at constant cost.
51
+ * - `subgroupExclusiveAdd` over those counts numbers the wave's whole production densely. The first
52
+ * `subgroup_size` of them are taken back into the wave's own lanes — perfectly packed, one child
53
+ * per lane, whoever produced them — and the descent takes another step without touching memory.
54
+ * - Everything past a full wave **spills** to the global queue under one `atomicAdd`. Breadth the
55
+ * wave cannot hold becomes work for other waves rather than a serial loop inside this one.
56
+ *
57
+ * So the number of dispatches is the number of spill generations, and the narrow top of the DAG —
58
+ * twenty levels that move between 1 and 120 items and draw nothing — is one wave taking twenty
59
+ * steps in registers.
60
+ *
61
+ * This is Karis' "Variable sized work" (graphicrants, 2026-03) with its groupshared scatter
62
+ * removed. That scatter needs HLSL's `GroupMemoryBarrier()` — memory ordering with no execution
63
+ * sync, sound because a wave is in lockstep — and WGSL has no memory-only workgroup barrier.
64
+ * `workgroupBarrier` synchronizes execution as well, which pins every subgroup of the workgroup to
65
+ * the same number of steps and is a deadlock the moment they disagree; `workgroupUniformLoad` is
66
+ * that same control barrier plus a load, and what it returns is one value uniform across the
67
+ * workgroup, which is the opposite of the per-lane read a scatter is made of.
68
+ * `vg_child_owner` finds each item's producer by binary search over the same prefix sums
69
+ * instead: `log2(subgroup_size)` shuffles, no workgroup memory and no barrier anywhere in this
70
+ * file, so nothing here needs the workgroup to agree on anything.
71
+ *
72
+ * ## What WGSL will not let this do
73
+ *
74
+ * Every loop around a subgroup operation needs a **uniform trip count**, and nothing launders one —
75
+ * not `subgroupAdd`, not `subgroupMax`, not even `subgroupBroadcastFirst`, which launders a value
76
+ * for a use but not for control flow. Nor may such a loop carry a non-uniform `break`, `continue`
77
+ * or `return`. So the descent runs `params.descent_steps` times and masks; a wave that drains its
78
+ * subtree early pays the remaining steps at about ten instructions each rather than leaving. That
79
+ * makes `descent_steps` a tuning knob rather than a safety bound, and
80
+ * `VGEO_CUT_STAT.QUEUE_REMAINING` is what says when it is set too low.
81
+ *
82
+ * Divergence *inside* the loop is free: Tint models reconvergence, so a non-uniform `if` that opens
83
+ * and closes taints nothing after it, and the spill's per-lane loop is fine because it contains no
84
+ * subgroup operation of its own.
85
+ *
86
+ * ## One lane per cluster
87
+ *
88
+ * A leaf produces one item per cluster of its groups and the wave packs them, so what bounds a
89
+ * lane's work is the packing rather than a chunk size, and consecutive lanes read consecutive
90
+ * cluster rows instead of striding over runs of them.
91
+ *
92
+ * ## Why page-granular dedup is enough, and why it is necessary
93
+ *
94
+ * The page DAG is many-parented — 82 of 91 pages of a measured 98k sphere have more than one parent
95
+ * — so an undeduped descent would visit a page once per parent and draw its whole cut that many
96
+ * times. The claim is one bit per (instance, resident page), which is affordable. Cluster-granular
97
+ * dedup is what this avoids: the resident cluster count is exactly the number design §4 is trying
98
+ * not to pay per frame.
99
+ *
100
+ * Visiting a cluster the descent "should not" have reached costs only the test, because the
101
+ * predicate is a pure function of the row and gives the same answer from every direction. Missing
102
+ * one costs a hole. That asymmetry is the whole design:
103
+ *
104
+ * - **No cluster is drawn twice.** It is evaluated once per page visit, and the claim makes that at
105
+ * most once per instance.
106
+ * - **No cluster the flat rule would draw is missed.** If `project(C.parent) > tau`, then any
107
+ * parent cluster `P` of `C`'s group has `project(P.self) = project(C.parent) > tau` — every
108
+ * cluster of a group shares the consuming step's sphere and error — and monotonicity gives
109
+ * `project(P.parent) >= project(P.self)`, so `P` satisfies the predicate's first half and by
110
+ * induction its page is visited. `P` fails `project(self) <= tau`, so it either enqueues `C`'s
111
+ * page or clamps, and it clamps only when `C`'s group is not selectable, in which case `C` must
112
+ * not be drawn. Neither cull intervenes: a node's sphere contains `P.parent_sphere` and its
113
+ * `max_parent_error` is at least `P.parent_error`, so the LOD cull cannot fire, and both culls
114
+ * are on bounds of `P`'s whole subtree, which contains `C` — so they fire only where `C` is
115
+ * outside the cut's volume anyway.
116
+ *
117
+ * Note that the per-cluster culls do **not** have to agree across a group's several parents, and
118
+ * nothing here asks them to. A group is claimed and descended once, by whichever parent reaches it
119
+ * first; a parent that culls itself out simply is not that one. What each test promises is about
120
+ * its own subtree and nothing else.
121
+ *
122
+ * Descent crosses a page boundary by producing the child page's **node 0**: uniform items, one
123
+ * kernel, no special case for "entering a page". `SAME_PAGE` needs no special case either, because
124
+ * the CPU resolved it to this page's own index at install, so it looks up a page that is trivially
125
+ * resident and falls through to the only question it was really asking — is that group selectable.
126
+ *
127
+ * ## Bounds
128
+ *
129
+ * Every append is checked and every overflow is counted, and they all degrade in one direction —
130
+ * coarser or missing, never doubled. The exception worth knowing is `QUEUE_DROPPED`: a dropped item
131
+ * is a subtree never descended, and the parent that would have stood in over it was not drawn
132
+ * either, so that one is a hole.
133
+ *
134
+ * Requires the importing shader to declare `params`, `vg_lookup`, `vg_arena`, `vg_want_stamps`,
135
+ * `instances`, `queue_in`, `queue_out`, `claim` and `feedback`, and the three hooks.
136
+ *
137
+ * @author Alex Goldring
138
+ * @copyright Company Named Limited (c) 2026
139
+ * @type {CodeChunk}
140
+ */
141
+ export const chunk_vgeo_cut_descent = CodeChunk.from(
142
+ //language=WGSL
143
+ `
144
+ /*
145
+ vg_stat, vg_claim_page and vg_touch_page are chunk_vgeo_cut_claim's — the seed and reseed
146
+ passes take the same three, which is why they are no longer written here.
147
+ */
148
+
149
+ /**
150
+ * One cluster: the rule's verdict taken, wanted, claimed, or the walk up it elects.
151
+ */
152
+ fn vg_visit_cluster(
153
+ instance_base: u32,
154
+ page_row: u32,
155
+ group: u32,
156
+ member: u32
157
+ ) -> VGExpand {
158
+ let verdict = vg_cut_cluster(instance_base, page_row, group, member);
159
+
160
+ if (verdict.kind == VG_VERDICT_BELOW) {
161
+ /*
162
+ The decision is group-uniform, so the group's first member can carry the election alone.
163
+ That is an election with nothing to communicate: the other members reach the same answer
164
+ and defer to the same lane.
165
+ */
166
+ let group_row_here = vg_group_row(page_row, group);
167
+
168
+ let parent_count = vg_arena[group_row_here + ${VGEO_GROUP_ROW_OFFSET.PARENT_COUNT}u];
169
+
170
+ if ((params.flags & ${VGEO_CUT_FLAG_COARSEN}u) == 0u || member != 0u
171
+ || parent_count == 0u) {
172
+ return vg_expand_none();
173
+ }
174
+
175
+ return VGExpand(
176
+ VG_EXPAND_PARENTS,
177
+ parent_count,
178
+ page_row,
179
+ vg_arena[group_row_here + ${VGEO_GROUP_ROW_OFFSET.PARENT_FIRST}u],
180
+ 0u
181
+ );
182
+ }
183
+
184
+ if (verdict.kind == VG_VERDICT_TAKE) {
185
+ vg_cut_take(instance_base, page_row, verdict);
186
+ return vg_expand_none();
187
+ }
188
+
189
+ if (verdict.kind == VG_VERDICT_CLAMP) {
190
+ vg_cut_take(instance_base, page_row, verdict);
191
+
192
+ vg_stat(${VGEO_CUT_STAT.CLAMPED}u, 1u);
193
+
194
+ vg_want(
195
+ page_row,
196
+ verdict.child_ref,
197
+ verdict.child_page_index,
198
+ instances[instance_base + ${VGEO_INSTANCE_OFFSET.LOOKUP_WORD_OFFSET}u],
199
+ verdict.projected
200
+ );
201
+
202
+ return vg_expand_none();
203
+ }
204
+
205
+ if (verdict.kind == VG_VERDICT_HELD) {
206
+ vg_cut_take(instance_base, page_row, verdict);
207
+
208
+ vg_stat(${VGEO_CUT_STAT.CLAMPED}u, 1u);
209
+ vg_stat(${VGEO_CUT_STAT.CLAMPED_ON_ACTIVATION}u, 1u);
210
+
211
+ return vg_expand_none();
212
+ }
213
+
214
+ if (verdict.kind != VG_VERDICT_REFINE || !vg_claim_page(instance_base, verdict.child_page_row)) {
215
+ // nothing, or another lane, or another parent of this page, got there first
216
+ return vg_expand_none();
217
+ }
218
+
219
+ return VGExpand(VG_EXPAND_PAGE, 1u, verdict.child_page_row, 0u, 0u);
220
+ }
221
+
222
+ /**
223
+ * One entry of a page's parent rows: the page holding that parent, claimed and queued.
224
+ *
225
+ * The mirror of the descent's page crossing, and deliberately page-granular like it. The
226
+ * entry names a cluster as well, and this ignores it: a page reached from any direction is
227
+ * evaluated whole, the rule is a pure function of each row, and visiting a cluster the walk
228
+ * did not need costs only the test. What the cluster half of the entry is for is the
229
+ * refine-side election of CUT_PLAN_2026_09_14 section 3, which is section 7.6's work.
230
+ *
231
+ * A parent that is not resident stops the walk rather than clamping. There is nothing to
232
+ * clamp *to* -- the surface this lane is standing on is below the cut and is not drawn -- so
233
+ * the honest answer is that this instance cannot be served incrementally this frame, which
234
+ * is the fallback section 4 already defines and section 7.6 wires up.
235
+ */
236
+ fn vg_visit_parent(instance_base: u32, page_row: u32, entry: u32) -> VGExpand {
237
+ if (entry >= vg_page_field(page_row, ${VGEO_PAGE_ROW_OFFSET.PARENT_ENTRY_COUNT}u)) {
238
+ return vg_expand_none();
239
+ }
240
+
241
+ let row = vg_parent_base(page_row) + entry * VG_PARENT_ROW_WORDS;
242
+
243
+ let parent_page_index = vg_arena[row + ${VGEO_PARENT_ROW_OFFSET.PAGE_INDEX}u];
244
+
245
+ if (parent_page_index == VG_NO_CHILD_PAGE) {
246
+ return vg_expand_none();
247
+ }
248
+
249
+ let lookup_base = instances[instance_base + ${VGEO_INSTANCE_OFFSET.LOOKUP_WORD_OFFSET}u];
250
+
251
+ let parent_page_row = vg_lookup[lookup_base + parent_page_index];
252
+
253
+ if (parent_page_row == VG_PAGE_ROW_NONE) {
254
+ return vg_expand_none();
255
+ }
256
+
257
+ if (!vg_claim_page(instance_base, parent_page_row)) {
258
+ // this page is already in this instance's cut, from above or from another parent
259
+ return vg_expand_none();
260
+ }
261
+
262
+ return VGExpand(VG_EXPAND_PAGE, 1u, parent_page_row, 0u, 0u);
263
+ }
264
+
265
+ /**
266
+ * Execute whatever this lane is holding.
267
+ */
268
+ fn vg_execute(item: VGItem, holding: bool) -> VGExpand {
269
+ if (!holding) {
270
+ return vg_expand_none();
271
+ }
272
+
273
+ vg_stat(${VGEO_CUT_STAT.ITEMS}u, 1u);
274
+
275
+ let instance_base = item.instance_slot * VG_INSTANCE_WORDS;
276
+
277
+ if ((item.visit & VG_QUEUE_GROUP_BIT) != 0u) {
278
+ return vg_visit_cluster(
279
+ instance_base, item.page_row, item.visit & ~VG_QUEUE_GROUP_BIT, item.aux
280
+ );
281
+ }
282
+
283
+ if ((item.visit & VG_QUEUE_PARENT_BIT) != 0u) {
284
+ return vg_visit_parent(
285
+ instance_base, item.page_row, item.visit & ~VG_QUEUE_PARENT_BIT
286
+ );
287
+ }
288
+
289
+ return vg_cut_node(instance_base, item.page_row, item.visit);
290
+ }
291
+
292
+ /**
293
+ * Which lane of the wave produced the item at \`index\` of its densely numbered production.
294
+ *
295
+ * The owner is the **largest** lane whose base is at or below the index — largest, because a lane
296
+ * that produced nothing repeats its neighbour's base, and a repeat sits at the start of the next
297
+ * producer's run rather than the end of the previous one. The bases are non-decreasing, so this is
298
+ * a binary search, and \`span\` starts at a builtin so the loop's trip count is uniform.
299
+ */
300
+ fn vg_child_owner(first: u32, index: u32, lane_count: u32) -> u32 {
301
+ var owner = 0u;
302
+ var span = lane_count;
303
+
304
+ while (span > 1u) {
305
+ let step_half = span >> 1u;
306
+ let mid = owner + step_half;
307
+
308
+ // branchless: a non-uniform if around the next iteration's shuffle would not compile
309
+ owner = select(owner, mid, subgroupShuffle(first, mid) <= index);
310
+
311
+ span = span - step_half;
312
+ }
313
+
314
+ return owner;
315
+ }
316
+
317
+ fn vg_queue_write(slot: u32, item: VGItem) {
318
+ if (slot >= params.queue_capacity) {
319
+ vg_stat(${VGEO_CUT_STAT.QUEUE_DROPPED}u, 1u);
320
+ return;
321
+ }
322
+
323
+ let base = slot * 4u;
324
+
325
+ queue_out.elements[base] = item.instance_slot;
326
+ queue_out.elements[base + 1u] = item.page_row;
327
+ queue_out.elements[base + 2u] = item.visit;
328
+ queue_out.elements[base + 3u] = item.aux;
329
+ }
330
+
331
+ @compute @workgroup_size(${VGEO_CUT_WORKGROUP_SIZE})
332
+ fn main(
333
+ @builtin(global_invocation_id) global_id: vec3<u32>,
334
+ @builtin(subgroup_size) lane_count: u32,
335
+ @builtin(subgroup_invocation_id) lane_index: u32,
336
+ ) {
337
+ let slot = global_id.x;
338
+
339
+ /*
340
+ The queue's count against what the queue holds. \`shader_vgeo_cut_queue_prepare\` runs
341
+ immediately before every dispatch of this kernel and stores exactly this clamp back, so the
342
+ bound is already there — but it was the *read* below that carried it here and not the predicate
343
+ that decides whether a lane executes, and those two have to agree. A lane held past capacity
344
+ reads the clamped index, which is the last item of the queue: it would execute a duplicate of
345
+ an item another lane is already holding, and a cluster visited twice from two lanes is two draw
346
+ records for one surface. That is the one failure the claim bitmask and the own-group term are
347
+ both arranged to prevent, so the predicate does not get to be the looser of the two.
348
+ */
349
+ let queue_count = min(queue_in.count, params.queue_capacity);
350
+
351
+ /*
352
+ One per dispatch that had work, which is one per spill generation rather than one per level of
353
+ the descent: the depth is inside this kernel. Reaching params.descent_steps with items still
354
+ held is what QUEUE_REMAINING reports, and nothing else can.
355
+ */
356
+ if (slot == 0u && queue_count > 0u) {
357
+ vg_stat(${VGEO_CUT_STAT.WAVEFRONTS}u, 1u);
358
+ }
359
+
360
+ var holding = slot < queue_count;
361
+
362
+ let base = slot * 4u;
363
+
364
+ /*
365
+ Read unconditionally and mask the result. A branch here would be a non-uniform if, which is
366
+ harmless on its own — but every lane must reach every subgroup operation below, and a lane that
367
+ returned early is a lane the shuffles are not allowed to read.
368
+ */
369
+ let in_bounds = min(base, params.queue_capacity * 4u - 4u);
370
+
371
+ var item = VGItem(
372
+ queue_in.elements[in_bounds],
373
+ queue_in.elements[in_bounds + 1u],
374
+ queue_in.elements[in_bounds + 2u],
375
+ queue_in.elements[in_bounds + 3u]
376
+ );
377
+
378
+ for (var step = 0u; step < params.descent_steps; step = step + 1u) {
379
+ let expand = vg_execute(item, holding);
380
+
381
+ let first = subgroupExclusiveAdd(expand.count);
382
+ let total = subgroupAdd(expand.count);
383
+
384
+ // ----- what this wave keeps: one child per lane, densely packed, whoever produced it -----
385
+
386
+ let owner = vg_child_owner(first, lane_index, lane_count);
387
+
388
+ let kept = vg_child(
389
+ subgroupShuffle(item.instance_slot, owner),
390
+ VGExpand(
391
+ subgroupShuffle(expand.kind, owner),
392
+ 0u,
393
+ subgroupShuffle(expand.page_row, owner),
394
+ subgroupShuffle(expand.first, owner),
395
+ subgroupShuffle(expand.span, owner)
396
+ ),
397
+ lane_index - subgroupShuffle(first, owner)
398
+ );
399
+
400
+ // ----- what it cannot hold: spilled, packed, under one reservation for the whole wave -----
401
+
402
+ let mine_first = max(first, lane_count);
403
+ let mine_last = max(first + expand.count, lane_count);
404
+
405
+ let spill_count = mine_last - mine_first;
406
+
407
+ let spill_offset = subgroupExclusiveAdd(spill_count);
408
+ let spill_total = subgroupAdd(spill_count);
409
+
410
+ /*
411
+ Elected *before* the branch, so the branch carries no subgroup operation of its own and is
412
+ free to be non-uniform — which lets a wave with nothing to spill skip the reservation
413
+ outright. An atomic on the queue head is a global round trip; a descent step that keeps
414
+ everything it produced is otherwise register work, and would spend more reserving zero
415
+ slots than on the step.
416
+ */
417
+ let spill_elected = subgroupElect();
418
+
419
+ var reserved = 0u;
420
+
421
+ if (spill_elected && spill_total > 0u) {
422
+ reserved = atomicAdd(&queue_out.count, spill_total);
423
+ }
424
+
425
+ // after the branch closes, which Tint permits: it models reconvergence
426
+ let spill_base = subgroupBroadcastFirst(reserved) + spill_offset;
427
+
428
+ for (var i = 0u; i < spill_count; i = i + 1u) {
429
+ vg_queue_write(spill_base + i, vg_child(
430
+ item.instance_slot, expand, mine_first - first + i
431
+ ));
432
+ }
433
+
434
+ item = kept;
435
+ holding = lane_index < total;
436
+ }
437
+
438
+ /*
439
+ Whatever is still held has not been executed, so it goes back to the queue rather than being
440
+ dropped. This is the descent handing its unfinished frontier to the next dispatch, and at
441
+ lane_count items per wave it is the common case rather than an overflow path.
442
+ */
443
+ let tail_count = select(0u, 1u, holding);
444
+
445
+ let tail_offset = subgroupExclusiveAdd(tail_count);
446
+ let tail_total = subgroupAdd(tail_count);
447
+
448
+ let tail_elected = subgroupElect();
449
+
450
+ var tail_reserved = 0u;
451
+
452
+ // as above: a wave holding nothing does not reserve
453
+ if (tail_elected && tail_total > 0u) {
454
+ tail_reserved = atomicAdd(&queue_out.count, tail_total);
455
+ }
456
+
457
+ let tail_base = subgroupBroadcastFirst(tail_reserved) + tail_offset;
458
+
459
+ if (holding) {
460
+ vg_queue_write(tail_base, item);
461
+ }
462
+ }
463
+ `, [
464
+ chunk_vgeo_cut_rule,
465
+ chunk_vgeo_cut_want,
466
+ chunk_vgeo_cut_claim,
467
+ ]);
@@ -0,0 +1,24 @@
1
+ /**
2
+ * What every cut's collect writes of an instance record (`VGEO_INSTANCE_OFFSET`), whatever its view:
3
+ *
4
+ * ```wgsl
5
+ * fn vg_instance_stretch(global: mat4x4<f32>) -> vec2<f32>
6
+ * fn vg_instance_record(mesh_index: u32, geometry_row: u32, capacity: u32) -> u32
7
+ * fn vg_store(base: u32, field: u32, value: f32)
8
+ * ```
9
+ *
10
+ * `vg_instance_stretch` is the largest and smallest stretch the transform applies to any direction,
11
+ * or zero for a transform that flattens the instance. `vg_instance_record` reserves a record under
12
+ * `capacity`, writes the instance's mesh row and its geometry's root page, lookup and claim width,
13
+ * and returns the record's first word, or {@link VG_INSTANCE_RECORD_NONE} when the records are full.
14
+ * What the instance is cut against (its eye, projection and volume) is the collect's own.
15
+ *
16
+ * Requires the importing shader to declare `instances`, `claim_widths` and `vg_geometries`.
17
+ *
18
+ * @author Alex Goldring
19
+ * @copyright Company Named Limited (c) 2026
20
+ * @type {CodeChunk}
21
+ */
22
+ export const chunk_vgeo_cut_instance: CodeChunk;
23
+ import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
24
+ //# sourceMappingURL=chunk_vgeo_cut_instance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_vgeo_cut_instance.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_instance.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,sCAFU,SAAS,CAoFc;0BA7GP,0CAA0C"}
@@ -0,0 +1,111 @@
1
+ import { chunk_mat3_singular_values } from "../../../../shader/chunk/geometry/mat3/chunk_mat3_singular_values.js";
2
+ import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
3
+ import { VGEO_GEOMETRY_ROW_OFFSET } from "../layout/VGEO_GEOMETRY_ROW_OFFSET.js";
4
+ import { VGEO_GEOMETRY_ROW_WORDS } from "../layout/VGEO_GEOMETRY_ROW_WORDS.js";
5
+ import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
6
+ import { VGEO_INSTANCE_WORDS } from "../layout/VGEO_INSTANCE_WORDS.js";
7
+
8
+ /**
9
+ * What every cut's collect writes of an instance record (`VGEO_INSTANCE_OFFSET`), whatever its view:
10
+ *
11
+ * ```wgsl
12
+ * fn vg_instance_stretch(global: mat4x4<f32>) -> vec2<f32>
13
+ * fn vg_instance_record(mesh_index: u32, geometry_row: u32, capacity: u32) -> u32
14
+ * fn vg_store(base: u32, field: u32, value: f32)
15
+ * ```
16
+ *
17
+ * `vg_instance_stretch` is the largest and smallest stretch the transform applies to any direction,
18
+ * or zero for a transform that flattens the instance. `vg_instance_record` reserves a record under
19
+ * `capacity`, writes the instance's mesh row and its geometry's root page, lookup and claim width,
20
+ * and returns the record's first word, or {@link VG_INSTANCE_RECORD_NONE} when the records are full.
21
+ * What the instance is cut against (its eye, projection and volume) is the collect's own.
22
+ *
23
+ * Requires the importing shader to declare `instances`, `claim_widths` and `vg_geometries`.
24
+ *
25
+ * @author Alex Goldring
26
+ * @copyright Company Named Limited (c) 2026
27
+ * @type {CodeChunk}
28
+ */
29
+ export const chunk_vgeo_cut_instance = CodeChunk.from(
30
+ //language=WGSL
31
+ `
32
+ const VG_INSTANCE_RECORD_NONE = 0xffffffffu;
33
+
34
+ fn vg_store(base: u32, field: u32, value: f32) {
35
+ instances[base + field] = bitcast<u32>(value);
36
+ }
37
+
38
+ fn vg_instance_stretch(global: mat4x4<f32>) -> vec2<f32> {
39
+ let linear = mat3x3<f32>(global[0].xyz, global[1].xyz, global[2].xyz);
40
+
41
+ let stretch = mat3_singular_values(linear);
42
+
43
+ /*
44
+ A singular transform — an instance scaled to zero in some direction. mat4_inverse says so
45
+ by dividing by a zero determinant, and the NaN that comes back makes **every** comparison
46
+ in vg_project and the culls fail open, so one zero-scaled instance draws its whole
47
+ resident set. It covers nothing, so dropping it is also the right picture.
48
+
49
+ **The determinant is the test, and sigma_min alone was not.** This guard used to be
50
+ !(sigma_min > 0) on its own, and the closed form's own doc offered sigma_min as a
51
+ degeneracy test — true in exact arithmetic, false in f32. An axis-aligned flatten makes
52
+ MtM exactly diagonal and takes the exact branch, which does return zero. A ROTATED one
53
+ takes the trigonometric branch, where sigma_min is a difference of nearly equal numbers
54
+ with an absolute error of about sqrt(eps_f32) * sigma_max — so it came back near 1e-4
55
+ rather than 0, and thirty-six of forty rotated zero-scale instances passed this line with
56
+ a NaN eye and a projection scale of 6.2e10 behind it (REVIEW_LEDGER M3, re-review
57
+ 2026-09-12). The determinant does not have that problem: a flattened instance has one
58
+ exactly-zero column at every rotation, and every term of the expansion carries a factor
59
+ from it. It is also, exactly, the number mat4_inverse divides by.
60
+
61
+ sigma_min is kept beside it because it is not redundant: a matrix that is merely very
62
+ close to singular has a non-zero determinant and can still report sigma_min as zero, and
63
+ a ratio of the two would then be an infinity rather than a correction.
64
+
65
+ Both written as !(x > 0) rather than x <= 0 so that a NaN — which compares false against
66
+ everything — is caught rather than passed through.
67
+ */
68
+ if (!(abs(determinant(linear)) > 0.0) || !(stretch.y > 0.0)) {
69
+ return vec2<f32>(0.0);
70
+ }
71
+
72
+ return stretch;
73
+ }
74
+
75
+ fn vg_instance_record(mesh_index: u32, geometry_row: u32, capacity: u32) -> u32 {
76
+ let slot = atomicAdd(&claim_widths.count, 1u);
77
+
78
+ if (slot >= capacity) {
79
+ /*
80
+ Dropping the instance is the safe direction: a cut run without a claim slice draws every
81
+ page once per parent that reaches it.
82
+ */
83
+ return VG_INSTANCE_RECORD_NONE;
84
+ }
85
+
86
+ let base = slot * ${VGEO_INSTANCE_WORDS}u;
87
+
88
+ let geometry_base = geometry_row * ${VGEO_GEOMETRY_ROW_WORDS}u;
89
+
90
+ /*
91
+ The geometry's ordinal capacity rather than its resident page count is the claim width,
92
+ because ordinals come from a free list and can be sparse; a bitmask indexed by a sparse
93
+ ordinal has to be as wide as the highest one handed out.
94
+ */
95
+ let ordinal_capacity = vg_geometries[
96
+ geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.ORDINAL_CAPACITY}u
97
+ ];
98
+
99
+ instances[base + ${VGEO_INSTANCE_OFFSET.MESH_INDEX}u] = mesh_index;
100
+ instances[base + ${VGEO_INSTANCE_OFFSET.ROOT_PAGE_ROW}u] =
101
+ vg_geometries[geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.ROOT_PAGE_ROW}u];
102
+ instances[base + ${VGEO_INSTANCE_OFFSET.LOOKUP_WORD_OFFSET}u] =
103
+ vg_geometries[geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.LOOKUP_WORD_OFFSET}u];
104
+ instances[base + ${VGEO_INSTANCE_OFFSET.ORDINAL_CAPACITY}u] = ordinal_capacity;
105
+ instances[base + ${VGEO_INSTANCE_OFFSET.CLAIM_BASE}u] = 0u;
106
+
107
+ claim_widths.elements[slot] = ordinal_capacity;
108
+
109
+ return base;
110
+ }
111
+ `, [chunk_mat3_singular_values]);
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The cut's rule, once, for every traversal that selects clusters: the camera's wavefront
3
+ * (`shader_vgeo_cut_traverse`) and a box cut. A cluster is in the cut iff
4
+ *
5
+ * > `own group selectable AND project(parent) > tau AND (project(self) <= tau OR child group not
6
+ * > selectable)`
7
+ *
8
+ * which is design §4's per-cluster form together with its first term. That term is load-bearing
9
+ * and §4 states the rule without it: a group that is resident but not yet selectable has clusters
10
+ * satisfying the rest of the rule while their coarse stand-in is drawn over the same surface, a few
11
+ * microns apart, with the depth buffer choosing between them. That reads as corrupt geometry rather
12
+ * than as a missing page, which is what makes it hard to attribute and worth stating first.
13
+ *
14
+ * ```wgsl
15
+ * fn vg_cut_node(instance_base: u32, page_row: u32, node: u32) -> VGExpand
16
+ * fn vg_cut_cluster(instance_base: u32, page_row: u32, group: u32, member: u32) -> VGVerdict
17
+ * fn vg_child(instance_slot: u32, expand: VGExpand, k: u32) -> VGItem
18
+ * ```
19
+ *
20
+ * The rule is evaluated in an instance's own space, against the instance record
21
+ * (`VGEO_INSTANCE_OFFSET`): its eye, projection constant and distance weight for `vg_project`,
22
+ * its lookup base for the child pages. What it is culled against is the traversal's, so the
23
+ * importing shader defines both culls, each a test of a bound of the whole subtree under it:
24
+ *
25
+ * ```wgsl
26
+ * fn vg_cut_sphere_outside(instance_base: u32, sphere: vec4<f32>) -> bool
27
+ * fn vg_cut_box_outside(instance_base: u32, lower: vec3<f32>, upper: vec3<f32>) -> bool
28
+ * ```
29
+ *
30
+ * What a traversal does with a verdict is its own: the camera draws, wants and claims; a box cut
31
+ * takes the cluster's triangles.
32
+ *
33
+ * Requires the importing shader to declare `params`, `vg_lookup`, `vg_arena`, `instances` and
34
+ * `feedback`. Claiming a page is the traversal's: the camera's takes `chunk_vgeo_cut_claim`.
35
+ *
36
+ * @author Alex Goldring
37
+ * @copyright Company Named Limited (c) 2026
38
+ * @type {CodeChunk}
39
+ */
40
+ export const chunk_vgeo_cut_rule: CodeChunk;
41
+ import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
42
+ //# sourceMappingURL=chunk_vgeo_cut_rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_vgeo_cut_rule.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_rule.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,kCAFU,SAAS,CA8V8B;0BAnZvB,0CAA0C"}