@woosh/meep-engine 3.60.4 → 3.60.5

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 (379) hide show
  1. package/CHANGELOG.md +2602 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  63. package/src/shade/renderer/Renderer.js +7 -5
  64. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  67. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  68. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  69. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  70. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  71. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  72. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
  74. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  75. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  77. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  78. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  80. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  81. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  82. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  83. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  85. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  86. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  87. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  88. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  89. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  90. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  91. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  93. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  94. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  96. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  98. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  99. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  100. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  101. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  102. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  103. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  104. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  105. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  106. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  107. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  108. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  109. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  110. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  111. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  112. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  113. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  114. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  115. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  116. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  117. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  118. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  119. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  120. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  121. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  122. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  123. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  124. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  126. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  127. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  128. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  129. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  130. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  131. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  132. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  133. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  134. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  135. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  136. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  137. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  138. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  139. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  140. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  141. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  142. package/src/shade/renderer/water/shader_water.js +22 -13
  143. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  144. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  145. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  146. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  147. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  148. package/editor/REWORK_PLAN_2026_08.md +0 -692
  149. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  150. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  151. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  152. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  153. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  154. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  155. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  156. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  157. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  158. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  159. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  160. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  161. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  162. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  163. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  164. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  165. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  166. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  167. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  168. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  169. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  170. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  171. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  172. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  173. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  174. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  175. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  176. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  177. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  178. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  179. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  180. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  181. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  182. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  183. package/src/REVIEW_2026_08_06/generation.md +0 -176
  184. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  185. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  186. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  187. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  188. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  189. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  190. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  191. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  192. package/src/REVIEW_2026_08_06/view.md +0 -667
  193. package/src/REVIEW_2026_08_06.md +0 -610
  194. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  195. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  196. package/src/core/bvh8/NOTES.md +0 -63
  197. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  198. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  199. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  200. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  201. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  202. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  203. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  204. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  205. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  206. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  207. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  208. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  209. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  210. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  211. package/src/engine/REVIEW_2026_07_03.md +0 -211
  212. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  213. package/src/engine/control/first-person/DESIGN.md +0 -658
  214. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  215. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  216. package/src/engine/control/first-person/TODO.md +0 -160
  217. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  218. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  219. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  220. package/src/engine/ecs/ik/PLAN.md +0 -179
  221. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  222. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  223. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  224. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  225. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  226. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  227. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  228. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  229. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  230. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  231. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  232. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  233. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  234. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  235. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  236. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  237. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  238. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  239. package/src/engine/physics/cloth/PLAN.md +0 -3056
  240. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  241. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  242. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  243. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  244. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  245. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  246. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  247. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  248. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  249. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  250. package/src/format/image/avif/DECISIONS.md +0 -545
  251. package/src/format/image/jpeg/NOTES.md +0 -3
  252. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  253. package/src/generation/COORDINATES.md +0 -54
  254. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  255. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  256. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  257. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  258. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  259. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  260. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  261. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  262. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  263. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  264. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  265. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  266. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  267. package/src/shade/RENDERER_CONTRACT.md +0 -697
  268. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  269. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  270. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  271. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  272. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  273. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  274. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  275. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  276. package/src/shade/renderer/NOTES.md +0 -78
  277. package/src/shade/renderer/PLAN.md +0 -8
  278. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  279. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  280. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  281. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  282. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  283. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  284. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  285. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  286. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  287. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  288. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  289. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  290. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  291. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  292. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  293. package/src/shade/renderer/camera/orbital/README.md +0 -81
  294. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  295. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  296. package/src/shade/renderer/camera/orbital/index.js +0 -9
  297. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  298. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  299. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  300. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  301. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  302. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  303. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  304. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  305. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  306. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  307. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  308. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  309. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  310. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  311. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  312. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  313. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  314. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  315. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  316. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  317. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  318. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  319. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  320. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  321. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  322. package/src/shade/renderer/hiz/NOTES.md +0 -3
  323. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  324. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  325. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  326. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  327. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  328. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  329. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  330. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  331. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  332. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  333. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  334. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  335. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  336. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  337. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  338. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  339. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  340. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  341. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  342. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  343. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  344. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  345. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  346. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  347. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  348. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  349. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  350. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  351. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  352. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  353. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  354. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  355. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  356. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  357. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  358. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  359. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  360. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  361. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  362. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  363. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  364. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  365. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  366. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  367. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  368. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  369. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  370. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  371. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  372. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  373. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  374. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  375. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  376. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  377. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  378. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  379. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,280 +0,0 @@
1
- # Particle, emitter and global fields — scope (2026-10-29, revision 4)
2
-
3
- **Status: landed.** `DESIGN.md` (*Vocabulary: fields*, *Emitter fields*, *Global fields*, *Transform
4
- bindings*) describes what was built. This is the scope as proposed. The **Outcome** section at the
5
- end lists where the build departs from it, and the measurements.
6
-
7
- **The model.** The program is the class and the emitter is an instance.
8
- - The class declares the fields every instance carries, and the global fields it reads.
9
- - The instance holds the values.
10
- - The class's own data — code, the constant pool, its bucket — is never touched by an instance.
11
-
12
- **Rejected alternatives:**
13
- - fixed 32-word emitter rows, in favour of general allocation;
14
- - GPU-integrated emitter state: values are static or set by gameplay, which the GPU cannot see;
15
- - a copy of the class for every set of instance values.
16
-
17
- ## Vocabulary
18
-
19
- | scope | term | engine's own members | read by |
20
- |---|---|---|---|
21
- | particle | `particle_field` (was "attribute") | none (by design) | `LOAD_PARTICLE_FIELD` / `STORE_PARTICLE_FIELD` |
22
- | emitter | `emitter_field` | `EMITTER_POSITION`, `_DIRECTION`, `_UP`, `EMITTER_AGE` | `LOAD_BUILTIN` |
23
- | system | `global_field` | `TIME`, `DELTA_TIME` | `LOAD_BUILTIN` |
24
-
25
- **What the rename covers.**
26
- - **Renamed:** `ParticleLayout`'s entries, the `ParticleEffect` / `ParticleEmitter` API, the editor,
27
- the graph node types (`particleField` / `setParticleField`), and the documentation.
28
- - **What keeps loading:** the graph JSON keys node types by name, and those names are wire format,
29
- so `attribute` and `setAttribute` still load as aliases.
30
- - **Unchanged:** the binary effect format writes a layout's field names, widths and tags, and no
31
- vocabulary words, so it does not change.
32
- - **The mnemonics** become `LOAD_PARTICLE_FIELD` / `STORE_PARTICLE_FIELD`, on the opcode numbers they
33
- already have. `LOAD_ATTR` / `STORE_ATTR` text still parses, the precedent being legacy `SWIZZLE`
34
- text.
35
-
36
- ## Format
37
-
38
- - **The class declares its `emitter_field`s as a `ParticleLayout`**: name, width, an optional `type`
39
- tag, and a default each. It sits on `ParticleProgram` beside the particle layout.
40
- - Declaration order is wire format, the same rule as for particle fields.
41
- - **The class declares the `global_field`s it imports**: a name and a width each.
42
- - **The system's global layout is the union of what it holds.**
43
- - It is append-only, and capacity only rises.
44
- - Game code may declare names up front.
45
- - A global field nobody has set reads 0.
46
-
47
- ## Storage: a third region of `ProgramHeap`'s buffer
48
-
49
- **`ProgramHeap` already is this.**
50
- - Its sections are `ProgramRegion`s over flat word arrays, each managed by an `OffsetAllocator`.
51
- - It packs them into one buffer, `[header][constants][code]`, which every pass running the VM already
52
- binds.
53
- - It repacks when a section has no run long enough, and capacities only rise.
54
- - A repack moves `placement_version`, and that restages every emitter row.
55
-
56
- The fields are a third region:
57
-
58
- ```
59
- [header][fields: global (reserved) | emitter blocks][constants][code]
60
- ```
61
-
62
- - **Global fields are always addressed from 0.** They take the region's top, reserved at 16 KiB
63
- (4,096 words), so they never move.
64
- - **Each instance's `emitter_field` block is one allocation**, sized to its class's layout.
65
- - The emitter record carries `field_offset`, the block's start within the region. The record writer
66
- fills it from the instance's context, beside the program placement.
67
- - An instance whose class declares no emitter fields allocates nothing.
68
- - **The header gains a word for the field base**, beside the code base it already holds.
69
- - **No storage binding is added.**
70
- - Emit and simulate stay at eight, and their wide twins at nine, inside the device floor of ten.
71
- - A buffer of its own would put the wide twins at ten, the floor itself.
72
- - This was the deciding cost.
73
- - **Upload goes by span.**
74
- - Today a placement re-uploads the whole buffer, which is right for code, because code changes
75
- rarely.
76
- - Field values change with gameplay, so the fields region uploads its changed spans through the
77
- engine's existing small-write upload path (small writes batched in blocks, mapped from 32 KiB up).
78
- - A repack or growth still rebuilds the whole buffer, as today.
79
- - **Authority.** The VM reads the buffer and never writes it. The CPU writes values. The binding pass
80
- (below) writes the words that are bound.
81
-
82
- ## Reading
83
-
84
- - **`LOAD_BUILTIN` gets two convention ranges above the engine's ids:**
85
- - `VM_BUILTIN_EMITTER_FIELD_BASE + word offset`;
86
- - `VM_BUILTIN_GLOBAL_FIELD_BASE + import index`.
87
- The component count rides in `s1`, as `LOAD_PARTICLE_FIELD` carries it, and lanes past it read 0.
88
- - **`vm_load_builtin`'s default case calls two host functions.** They follow the external-symbol
89
- pattern `particle_vm_sample_wind` already uses: `particle_vm_load_emitter_field` and
90
- `particle_vm_load_global_field`. Every host defines them: emit, simulate, their wide twins, and the
91
- warm-up advance.
92
- - **An `emitter_field` is read per lane.**
93
- - The emitter row comes from the record header, then `field_offset` from the row, then the words.
94
- - Nothing new is held across the interpreter loop, so `vm_ctx` does not grow.
95
- - A field read is two dependent reads. Whether to hold `field_offset` in `vm_ctx` instead is decided
96
- by the measurement below, not by argument.
97
- - **A `global_field`'s address is the same in every lane**, so it is a scalar read.
98
- - **Buckets, the constant pool and wave-uniform decode are untouched.**
99
-
100
- ### Linking global fields
101
-
102
- - Programs are durable content, compiled with no scene present, so a global field's offset cannot be
103
- baked in.
104
- - The operand is an index into the program's import table.
105
- - `ProgramHeap` rewrites it to the global field's offset when it copies the code into place, which
106
- it already does.
107
- - The heap stays keyed on the unpatched bytecode.
108
- - Appending a global field moves nothing.
109
-
110
- ## Transform bindings
111
-
112
- - **What they are.** A binding names a `transforms` row, a field and a channel. The GPU writes that
113
- row's composed `global` into the field every frame.
114
- - **What that gives.** A beam's far end, a homing target, a second bone: any transform can drive a
115
- field with nothing copied through the CPU. That is what the emitter's own `node` already does for
116
- `EMITTER_POSITION`, and it works for a row only the GPU composes, such as an animated joint.
117
-
118
- **Storage: a `field_bindings` table** in the particle database. It is CPU-staged and low-churn, which
119
- is what `GPUDatabase` is for.
120
- - `source` is a link to the scene's `transforms` table, non-owning, exactly like the emitter record's
121
- `node` (`PARTICLE_DATABASE_SPEC.add_link`).
122
- - `target` is a word address in the fields region. It may be a global field or a word of an emitter
123
- block, which is one rule for both scopes.
124
- - `channel` says what is written:
125
-
126
- | channel | width | from `global` |
127
- |---|---|---|
128
- | `POSITION` | 3 | the origin, as `EMITTER_POSITION` |
129
- | `DIRECTION` | 3 | normalised −Z, as `EMITTER_DIRECTION` |
130
- | `UP` | 3 | normalised +Y, as `EMITTER_UP` |
131
- | `ORIENTATION` | 4 | a quaternion, as the `orientation` channel takes it |
132
-
133
- The channel width must equal the field's width, and the system refuses the binding otherwise.
134
- - Targets are restaged when `placement_version` moves, the rule every row already follows.
135
-
136
- **The pass: `shader_particle_field_bind`.**
137
- - One thread per binding row, walked with the table's page iterator, as the tick walks emitters.
138
- - It reads `scene_read_node(source).global`, the same read `chunk_particle_setup_context` makes, and
139
- writes the channel's words into the fields region. The program buffer is bound read-write here and
140
- only here.
141
- - It runs once a frame, after the hierarchy pass has composed the rows and before the tick.
142
- - The host skips the dispatch while the table is empty.
143
-
144
- **Authority.** A bound word is recomputed from scratch every frame.
145
- - That is the argument that lets the scene's `transforms` table mix CPU fields with a GPU-written
146
- `global` (DESIGN.md, *The emitter state*), and it holds here.
147
- - The CPU's value for a bound field is its default until the first bind.
148
- - A span upload or a buffer rebuild that lands on a bound word is overwritten before any VM pass
149
- reads it.
150
-
151
- **ECS.**
152
- - `ParticleEffect.bindings`: `[{ field, entity, channel }]`, an entity reference, never a row. The
153
- system resolves it with `row_of_entity` and holds the row through the scene context's rows, as it
154
- does for the emitter's own placement.
155
- - `GPUParticleSystem.global_fields.bind(name, entity, channel)` does the same for global fields.
156
-
157
- ## Everything else it touches
158
-
159
- - **Optimizers.** `LOAD_BUILTIN` is already a pure read. Width inference has to take a field's width
160
- from `s1` rather than from `VM_BUILTIN_COMPONENTS`, and the fuzzer must generate both ranges.
161
- - **Reference VM.** The host passes `emitter_field` and `global_field` words as it passes the builtins
162
- today.
163
- - **Graph.** New node types, appended at the end of `ParticleNodeRegistry.js`:
164
- - `emitterField` (name, type, default);
165
- - `globalField` (name, type).
166
- Widths are validated per name.
167
- - **ECS values.**
168
- - `ParticleEffect.emitter_fields`: values by name, as `Uint32` bit patterns. Compare-to-last covers
169
- them, and a change marks the span dirty. It is not a restage, since a block does not move.
170
- - `GPUParticleSystem.global_fields.set(name, value)` does the same for global fields.
171
- - **Serialization.** The emitter-field layout and the imports ride in the program; values and bindings
172
- ride on the effect. `ParticleEffect` goes to v3, with an upgrader that gives old saves none.
173
-
174
- ## Cost
175
-
176
- - **A static value:** written once, when the block is allocated. Nothing per frame.
177
- - **A changed value:** one span upload. No restage, no rebucket, no program change.
178
- - **A binding:** one thread a frame, plus one dispatch (a tiny pass measures 5–8 µs here)
179
- while any binding exists.
180
- - **On the GPU:**
181
- - an `emitter_field` read is a header reload, a row read and up to four loads;
182
- - a `global_field` read is one scalar read;
183
- - an effect that reads neither pays nothing that executes.
184
-
185
- ## What gets measured
186
-
187
- - **The interpreter's register footprint.** Simulate and emit compiled through Dawn, before and after,
188
- on RDNA2 offline. The default case grows the static code. The gate is no VGPR change.
189
- - **The cost of an `emitter_field` read.** At 200k alive, on the 4090 and the iGPU, paired in one
190
- page:
191
- - the effect reading one field per particle, against the same effect reading a constant;
192
- - the same pair with `field_offset` held in `vm_ctx`.
193
- The cheaper of the two read paths is kept.
194
- - **The bind pass**, at 1 and 1,000 bindings.
195
-
196
- ## Stages
197
-
198
- Each stage lands red-then-green.
199
-
200
- | stage | what lands | pinned by |
201
- |---|---|---|
202
- | V0 | the vocabulary rename; old graph node names and mnemonics load as aliases | every existing graph and assembly spec green, plus a saved graph using `attribute` loading |
203
- | E1 | fields region, `field_offset`, emitter-field layout, `LOAD_BUILTIN` emitter range in both executors, graph node, `ParticleEffect.emitter_fields`, span upload, v3 | two bonfires differing only in flame tint: one program, one bucket, two blocks; a value change uploads one span and moves no program id |
204
- | G1 | global reservation, imports, link at placement, global range, `global_fields.set` | a global field changes a running effect without restaging an emitter row |
205
- | B1 | `field_bindings`, the bind pass, the ECS and global bind API | a beam whose far end follows an animated joint the CPU never sees |
206
-
207
- ## Outcome (2026-10-29)
208
-
209
- Landed as revision 4 describes, in four commits — V0 `b8d14148e`, E1 `66031919d`, G1 `f93d1d2e0` and
210
- B1 `3dd4b7ce7` — and the adversarial review's fixes, `a14459252`, with these departures:
211
-
212
- - **Emitter fields are declared by the effect's document, as particle fields are**, and the
213
- `emitterField` node reads one by name; the node does not declare. The same for global imports.
214
- The emitter layout sits on the effect and the emitter (`emitter_layout`), not on `ParticleProgram`.
215
- Values are `Uint32` words in layout order (`emitter_fields`), not a map by name.
216
- - **The fields are the buffer's fourth section**, `[header][constants][code][fields]`, not a region
217
- between the header and the constants.
218
- - **The VM reads fields inline** in `LOAD_BUILTIN`'s field branch. There are no host functions
219
- `particle_vm_load_emitter_field` / `particle_vm_load_global_field`.
220
- - **Global bindings go through the registry and the ECS system**: `EmitterRegistry.bind_global_field`
221
- and `GPUParticleEmitterSystem.bind_global_field`. There is no `GPUParticleSystem.global_fields.bind`.
222
- - **The bind pass runs after the counter reset**, before the spawn commands and the tick.
223
- - **A field read takes the instruction's width in words**, as `LOAD_CONST` does, rather than a
224
- component count in `s1`: the compiler emits a field at its own width, and `LOAD_BUILTIN`'s operand
225
- list — and so every saved assembly text — stays as it was.
226
- - **`field_offset` is held in `vm_ctx`**, beside `emitter_position`, rather than re-read from the
227
- emitter row inside the opcode. The re-read form was not built: the measured cost below is the
228
- address being per-lane, and a row found through the particle's own header is per-lane too.
229
- - **A value change restages the emitter's row** as well as writing its span — the registry's existing
230
- path — rather than the span alone.
231
- - **v3 of `ParticleEffect` carries the program's global imports**, written in E1 so the format bumped
232
- once.
233
- - **Transform bindings on the component are runtime data and not saved**: nothing in the engine's
234
- saves carries an entity reference across a load.
235
-
236
- **Measured (2026-10-29, at `a14459252`'s code).** Headless Chrome, one device per run. The two arms are two
237
- particle systems in one page, frames interleaved and the order alternating. Times are GPU timestamps,
238
- p10, over 1,200 frames on the 4090 and 300 on the iGPU. The emitter tick is the control and reads the
239
- same in both arms throughout.
240
-
241
- - **An `emitter_field` read at 200k alive.** The effect is `position += drift * dt`: six
242
- instructions, where `drift` is a 3-wide emitter field in one arm and a 3-wide constant in the
243
- other. Simulate:
244
-
245
- | | constant | field | field / constant |
246
- |---|---|---|---|
247
- | RTX 4090, 2 runs | 132–134 µs | 135–137 µs | 1.008, 1.039 |
248
- | Radeon iGPU (RDNA2), 7 runs | 1,893–1,952 µs | 2,111–2,204 µs | 1.111–1.131 |
249
-
250
- On the iGPU that is about 1.1 ns per particle per read: an eighth of a program this short. **The
251
- cause is that the address is per-lane.** Simulate's waves are one program, not one emitter, so
252
- `vm_ctx.emitter_field_offset` reaches the read per-lane while the constant pool's base arrives
253
- wave-uniform. Two experiments show it:
254
- - broadcasting the offset from the first lane, valid only in this one-emitter page, brings the ratio
255
- to 0.996 and 0.997;
256
- - hoisting the header word out of the loop changes nothing (1.117, 1.096).
257
- - **A guarded broadcast was measured and not kept.** It reads at the first lane's offset when
258
- `subgroupAll` says every lane agrees, and per-lane otherwise. Field-reading programs ran 0.985–0.996
259
- of the constant arm. But every program without a field read slowed by 2.6–3.6%: 2,001–2,021 µs
260
- against 1,949–1,952 µs, in three HEAD/fix pairs run back to back. The cost is there even though such
261
- a program never takes the branch. Most effects read no field, so the common case would pay.
262
- - **The bind pass**, POSITION bindings:
263
-
264
- | | 1 binding | 1,000 bindings |
265
- |---|---|---|
266
- | RTX 4090, 2 runs | 2.05 µs | 2.05 µs |
267
- | Radeon iGPU, 2 runs | 2.20–2.24 µs | 5.44 µs |
268
-
269
- On the 4090 both arms read the same as the emitter-tick control. On the iGPU, 999 more bindings add
270
- 3.2 µs.
271
-
272
- **Not measured:** the interpreter's register footprint. amdspv and spirv-as are not installed on this
273
- machine. Every VM pass and the bind pass compile and build pipelines under Tint on both GPUs.
274
-
275
- ## Sources
276
-
277
- - Niagara Emitter and System parameter namespaces (with User values beside them) and Parameter Collections (globals bound by name).
278
- - [Niagara key concepts (namespace read/write table)](https://dev.epicgames.com/documentation/unreal-engine/key-concepts-in-niagara-effects-for-unreal-engine)
279
- - [VFX Graph instancing](https://docs.unity3d.com/Packages/com.unity.visualeffectgraph@17.2/manual/Instancing.html)
280
- — instances share code and load their properties per instance.