@woosh/meep-engine 3.64.1 → 3.65.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 (324) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/build/bundle-worker-terrain.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/binary/BinaryBuffer.d.ts +5 -0
  6. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  7. package/src/core/binary/BinaryBuffer.js +39 -5
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
  10. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
  11. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
  12. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
  13. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
  14. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
  15. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
  16. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
  17. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
  19. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
  20. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
  21. package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
  22. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
  23. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
  25. package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
  26. package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
  28. package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
  29. package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
  30. package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
  31. package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
  32. package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
  33. package/src/engine/graphics3/GroundCoverSystem.js +58 -0
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +372 -110
  36. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  37. package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
  40. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  41. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
  42. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
  43. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  44. package/src/engine/network/sim/SimActionExecutor.js +65 -9
  45. package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
  46. package/src/engine/network/state/PredictionHistory.js +6 -1
  47. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
  48. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
  49. package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
  50. package/src/engine/network/time/RenderPlayout.d.ts +23 -3
  51. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  52. package/src/engine/network/time/RenderPlayout.js +40 -4
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
  55. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
  56. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
  57. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  58. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  59. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  60. package/src/shade/playground/grass_surfaces/index.html +75 -0
  61. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  62. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  63. package/src/shade/playground/grass_surfaces/main.js +593 -0
  64. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  65. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  66. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  67. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  68. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  69. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  70. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  71. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  72. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  73. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  74. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  75. package/src/shade/renderer/Renderer.js +47 -43
  76. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  77. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  78. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  79. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  80. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  81. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  82. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  83. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  84. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  88. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  89. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  91. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  92. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  103. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  104. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  106. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  108. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  110. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  113. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  115. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  168. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  169. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  170. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  171. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  172. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  173. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  174. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  175. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  176. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  177. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  178. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  179. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  180. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  181. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  182. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  183. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  184. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  185. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  186. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  187. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  188. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  189. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  190. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  191. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  192. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  193. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  194. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  195. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  196. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  197. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  198. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  199. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  200. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  201. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  202. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  203. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  204. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  205. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  206. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  207. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  208. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  209. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  210. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  211. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  212. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  213. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  214. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  215. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  216. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  217. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  218. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  219. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  220. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  221. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  222. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  223. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  224. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  225. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  226. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  227. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  228. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  229. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  230. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  231. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  232. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  233. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  234. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  235. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  236. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  237. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  238. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  239. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  240. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  241. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  242. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  243. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  244. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  245. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  246. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  247. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  248. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  249. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  250. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  251. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  252. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  253. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  254. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  255. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  256. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  257. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  258. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  259. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  260. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  261. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  262. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  263. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  264. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  265. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  266. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  267. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  268. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  269. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  270. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  271. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  272. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  273. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  274. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  275. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  276. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  277. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  278. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  280. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  281. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  282. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  283. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  284. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  285. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  286. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  287. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  288. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  289. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  290. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  291. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  292. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  293. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  294. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  295. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  296. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  297. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  298. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  299. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  300. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  301. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  302. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  303. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  304. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  305. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  306. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  307. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  308. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  309. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  310. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  311. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  312. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  313. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  314. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  315. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  316. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  317. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  319. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  320. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  321. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  322. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
@@ -352,7 +352,9 @@ export class GPUFluidCascadeStack {
352
352
  * wind.set_far_velocity(v_far(t))
353
353
  *
354
354
  * A tile holds `v − v_far(t_s,c)` and `k` is taken for `t`, so a cascade that did not step reads
355
- * from its old tile through its new decay. The field's own update uploads the table.
355
+ * from its old tile through its new decay. A cascade that is published takes the field's
356
+ * `publish_slot`, so the tile the frame before read stays as it was. The field's own update uploads
357
+ * the table.
356
358
  *
357
359
  * @param {object} options
358
360
  * @param {FrameGraph} options.graph
@@ -394,6 +396,9 @@ export class GPUFluidCascadeStack {
394
396
  record.far_velocity.set(cascade.read_far_velocity);
395
397
  cascade.describe_parent(record.parent, record.parent_faces, c + 1 < count ? cascades[c + 1] : null);
396
398
 
399
+ // its tile is written beside the one the frame before read
400
+ wind.publish_slot(c);
401
+
397
402
  pass.order[pending++] = c;
398
403
  this.#unpublished[c] = 0;
399
404
  }
@@ -125,6 +125,13 @@ export class GPUFluidForcing {
125
125
  * @returns {number}
126
126
  */
127
127
  get obstacle_count(): number;
128
+ /**
129
+ * A number that changes whenever an effector or obstacle row is added or removed: while it stands, a
130
+ * list of either table's rows is the list it was.
131
+ *
132
+ * @returns {number}
133
+ */
134
+ get sets_version(): number;
128
135
  /**
129
136
  * Every obstacle and effector row: the leaves of the finest tree, before its resolution cull.
130
137
  * @returns {number}
@@ -1 +1 @@
1
- {"version":3,"file":"GPUFluidForcing.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/fluid/forcing/GPUFluidForcing.js"],"names":[],"mappings":"AAuIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH;IAEI;;;;OAIG;IACH,iCAFW,eAAe,QAUzB;IA2ID;;;;;;;;;;;OAWG;IACH,kCAPW,wBAAwB,EAAE,QAC1B,MAAM,QACN,MAAM,SACN,MAAM,cACN,MAAM,GACJ,wBAAwB,CAcpC;IAylBD;;;;OAIG;IACH,yCAJW,MAAM,0CAEN;QAAC,OAAO,yBAAwB;KAAC,QAc3C;IA+MD,iFAcC;IAWD,gFAiCC;IAWD,kFAsBC;IA+GD,gFA0CC;IAjnCD;;;OAGG;IACH;QAF8B,MAAM;OAwCnC;IA4BD;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,yBAEC;IAED;;;;;;;OAOG;IACH,mBAHW,MAAM,GACJ,MAAM,CAiBlB;IAED;;;;;OAKG;IACH,4BAEC;IAED;;;;;OAKG;IACH,2BAEC;IAED;;;;;OAKG;IACH,qBAHW,mBAAmB,GACjB,MAAM,CAQlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,UACN,mBAAmB,QAQ7B;IAED;;OAEG;IACH,qBAFW,MAAM,QAUhB;IAED;;;;;OAKG;IACH,uBAHW,mBAAmB,EAAE,GACnB,MAAM,CAsBlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,UACN,mBAAmB,QAgB7B;IAED;;;OAGG;IACH,wBAHW,MAAM,SACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,MAAM,CAuBlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,SACN,MAAM,QAmBhB;IAED;;;OAGG;IACH,qBAHW,MAAM,SACN,MAAM,QAUhB;IAyID;;;;;;;;;;;;;;;;;;;OAmBG;IACH;QAf+B,KAAK,EAAzB,UAAU;QACW,cAAc,EAAnC,WAAW;QAEgB,MAAM,EAAjC,UAAU,MAAM,CAAC;QAID,UAAU,EAA1B,MAAM;QAEU,gBAAgB,EAAhC,MAAM;QAEU,SAAS,EAAzB,MAAM;aA4ChB;IAyND;;;;;;;;;;;;OAYG;IACH;QAJ+B,KAAK,EAAzB,UAAU;QACe,KAAK,EAA9B,eAAe;QACe,MAAM,EAApC,eAAe,GAAC,IAAI;aA8H9B;IAmHD;;;;;;;;;;;OAWG;IACH;QAN+B,KAAK,EAAzB,UAAU;QACe,OAAO,EAAhC,eAAe;QACC,EAAE,EAAlB,MAAM;QACJ,MAAM,GAAC,IAAI,CAuFvB;IAyDD;;;OAGG;IACH,gBAwBC;;CACJ;yBA16CY,OAAO,8DAA8D,EAAE,UAAU;8BACjF,OAAO,6CAA6C,EAAE,eAAe;8BACrE,OAAO,uBAAuB,EAAE,eAAe;kCAC/C,OAAO,kFAAkF,EAAE,mBAAmB;kCAC9G,OAAO,2EAA2E,EAAE,mBAAmB;4BAtCxF,mCAAmC;yCADtB,mDAAmD"}
1
+ {"version":3,"file":"GPUFluidForcing.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/fluid/forcing/GPUFluidForcing.js"],"names":[],"mappings":"AAuIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH;IAEI;;;;OAIG;IACH,iCAFW,eAAe,QAUzB;IA2ID;;;;;;;;;;;OAWG;IACH,kCAPW,wBAAwB,EAAE,QAC1B,MAAM,QACN,MAAM,SACN,MAAM,cACN,MAAM,GACJ,wBAAwB,CAcpC;IAmmBD;;;;OAIG;IACH,yCAJW,MAAM,0CAEN;QAAC,OAAO,yBAAwB;KAAC,QAc3C;IA+MD,iFAcC;IAWD,gFAiCC;IAWD,kFAsBC;IA+GD,gFA0CC;IA3nCD;;;OAGG;IACH;QAF8B,MAAM;OAwCnC;IA4BD;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;;;OAKG;IACH,2BAEC;IAED;;;OAGG;IACH,yBAEC;IAED;;;;;;;OAOG;IACH,mBAHW,MAAM,GACJ,MAAM,CAiBlB;IAED;;;;;OAKG;IACH,4BAEC;IAED;;;;;OAKG;IACH,2BAEC;IAED;;;;;OAKG;IACH,qBAHW,mBAAmB,GACjB,MAAM,CAQlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,UACN,mBAAmB,QAQ7B;IAED;;OAEG;IACH,qBAFW,MAAM,QAUhB;IAED;;;;;OAKG;IACH,uBAHW,mBAAmB,EAAE,GACnB,MAAM,CAsBlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,UACN,mBAAmB,QAgB7B;IAED;;;OAGG;IACH,wBAHW,MAAM,SACN,MAAM,QAYhB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,MAAM,CAuBlB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,SACN,MAAM,QAmBhB;IAED;;;OAGG;IACH,qBAHW,MAAM,SACN,MAAM,QAUhB;IAyID;;;;;;;;;;;;;;;;;;;OAmBG;IACH;QAf+B,KAAK,EAAzB,UAAU;QACW,cAAc,EAAnC,WAAW;QAEgB,MAAM,EAAjC,UAAU,MAAM,CAAC;QAID,UAAU,EAA1B,MAAM;QAEU,gBAAgB,EAAhC,MAAM;QAEU,SAAS,EAAzB,MAAM;aA4ChB;IAyND;;;;;;;;;;;;OAYG;IACH;QAJ+B,KAAK,EAAzB,UAAU;QACe,KAAK,EAA9B,eAAe;QACe,MAAM,EAApC,eAAe,GAAC,IAAI;aA8H9B;IAmHD;;;;;;;;;;;OAWG;IACH;QAN+B,KAAK,EAAzB,UAAU;QACe,OAAO,EAAhC,eAAe;QACC,EAAE,EAAlB,MAAM;QACJ,MAAM,GAAC,IAAI,CAuFvB;IAyDD;;;OAGG;IACH,gBAwBC;;CACJ;yBAp7CY,OAAO,8DAA8D,EAAE,UAAU;8BACjF,OAAO,6CAA6C,EAAE,eAAe;8BACrE,OAAO,uBAAuB,EAAE,eAAe;kCAC/C,OAAO,kFAAkF,EAAE,mBAAmB;kCAC9G,OAAO,2EAA2E,EAAE,mBAAmB;4BAtCxF,mCAAmC;yCADtB,mDAAmD"}
@@ -410,6 +410,16 @@ export class GPUFluidForcing {
410
410
  return this.#database.get(FLUID_OBSTACLE_TABLE).count;
411
411
  }
412
412
 
413
+ /**
414
+ * A number that changes whenever an effector or obstacle row is added or removed: while it stands, a
415
+ * list of either table's rows is the list it was.
416
+ *
417
+ * @returns {number}
418
+ */
419
+ get sets_version() {
420
+ return this.#sets_version;
421
+ }
422
+
413
423
  /**
414
424
  * Every obstacle and effector row: the leaves of the finest tree, before its resolution cull.
415
425
  * @returns {number}
@@ -274,11 +274,17 @@ export class GPUGeometrySDFManager {
274
274
  * `caches`, as the device holds them when the readbacks land: each brick once, however many fields
275
275
  * hold it, and each cache naming its field. Read while nothing bakes, it is what was baked.
276
276
  *
277
+ * With `morton`, the bundle is laid out for locality (`model_cache_bundle_sort_morton`): each field's
278
+ * bricks numbered in Morton order, its surface blocks with them, and the bricks in that order, which
279
+ * {@link upload_bundle} places them in. Off by default: worth it for assets prepared offline, where it
280
+ * costs nothing at load, and worth about 0.5% to the probe clipmap's material gather there.
281
+ *
277
282
  * @param {GPUGeometryMetadata[]} records
278
283
  * @param {number[]} caches surface cache ids, each of a geometry of `records`
284
+ * @param {boolean} [morton] lay the bundle out in Morton order
279
285
  * @returns {Promise<ModelCacheBundle>}
280
286
  */
281
- export_bundle(records: GPUGeometryMetadata[], caches: number[]): Promise<ModelCacheBundle>;
287
+ export_bundle(records: GPUGeometryMetadata[], caches: number[], morton?: boolean): Promise<ModelCacheBundle>;
282
288
  /**
283
289
  * Record the frame's bake: queue again what is held for the other side than it was baked for, free
284
290
  * what was given back, classify what is admitted, and take, evaluate and store up to `budget`
@@ -1 +1 @@
1
- {"version":3,"file":"GPUGeometrySDFManager.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js"],"names":[],"mappings":"AAmLA;;;;GAIG;AACH,uCAFU,MAAM,CAEuH;AAoEvI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH;IA8QI;;;OAGG;IACH,2CAFW,kBAAkB,EAS5B;IA7QD;;;;OAIG;IACH,aAAuB;IAEvB;;;;OAIG;IACH,iBAA2B;IAE3B;;;;OAIG;IACH,iBAA2B;IA4P3B;;;;;OAKG;IACH,qCAEC;IAED;;;;;;OAMG;IACH,sBAHW,MAAM,cACN,MAAM,QAkChB;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,yBAEC;IAED;;;;;OAKG;IACH,gBAHW,mBAAmB,aACnB,OAAO,QAajB;IAiCD;;;;;OAKG;IACH,gBAHW,mBAAmB,aACnB,OAAO,QAqBjB;IAED;;OAEG;IACH,aAYC;IAED;;;;;OAKG;IACH,eAFW,mBAAmB,QAiB7B;IAED;;;;;;;;;;;;OAYG;IACH,aAHW,mBAAmB,UACnB,mBAAmB,QAwD7B;IAcD;;;;;OAKG;IACH,iBAHW,mBAAmB,GACjB,YAAY,CAcxB;IAED;;;;;;OAMG;IACH,qBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;;;OAKG;IACH,wBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;OAGG;IACH,8BAEC;IAED;;OAEG;IACH,6BAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;;OAGG;IACH,2BAUC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;;OAIG;IACH,8BAEC;IAED;;;OAGG;IACH,yBAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,yBAIC;IAED;;;OAGG;IACH,6BAIC;IAED;;;OAGG;IACH,8EAIC;IAED;;;;;;OAMG;IACH,mCAOC;IAED;;OAEG;IACH,+BAcC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,sBANW,gBAAgB,WAChB,CAAC,mBAAmB,GAAC,IAAI,CAAC,EAAE,aAC5B,CAAC,aAAa,GAAC,IAAI,CAAC,EAAE,eACtB,OAAO,GACL,MAAM,CA2JlB;IA2CD;;;;;;;;OAQG;IACH,uBAJW,mBAAmB,EAAE,UACrB,MAAM,EAAE,GACN,QAAQ,gBAAgB,CAAC,CAqIrC;IAED;;;;;;;;;;;;;OAaG;IACH;QAP+B,KAAK,EAAzB,UAAU;QACM,MAAM,EAAtB,MAAM;QACW,cAAc,GAA/B,MAAM;QAEoC,SAAS,GAAnD,0BAA0B,GAAC,IAAI;aA+EzC;IAy+BD,gBAsCC;;CACJ;yBAj6EY,OAAO,8DAA8D,EAAE,UAAU;iCACjF,OAAO,0BAA0B,EAAE,kBAAkB;kCACrD,OAAO,2BAA2B,EAAE,mBAAmB;yCACvD,OAAO,uDAAuD,EAAE,0BAA0B;4BAC1F,OAAO,iCAAiC,EAAE,aAAa;qCAnB/B,mCAAmC;6BAOjE,eAAe;iCATyD,8BAA8B"}
1
+ {"version":3,"file":"GPUGeometrySDFManager.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js"],"names":[],"mappings":"AAoLA;;;;GAIG;AACH,uCAFU,MAAM,CAEuH;AAoEvI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH;IA8QI;;;OAGG;IACH,2CAFW,kBAAkB,EAS5B;IA7QD;;;;OAIG;IACH,aAAuB;IAEvB;;;;OAIG;IACH,iBAA2B;IAE3B;;;;OAIG;IACH,iBAA2B;IA4P3B;;;;;OAKG;IACH,qCAEC;IAED;;;;;;OAMG;IACH,sBAHW,MAAM,cACN,MAAM,QAkChB;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,yBAEC;IAED;;;;;OAKG;IACH,gBAHW,mBAAmB,aACnB,OAAO,QAajB;IAiCD;;;;;OAKG;IACH,gBAHW,mBAAmB,aACnB,OAAO,QAqBjB;IAED;;OAEG;IACH,aAYC;IAED;;;;;OAKG;IACH,eAFW,mBAAmB,QAiB7B;IAED;;;;;;;;;;;;OAYG;IACH,aAHW,mBAAmB,UACnB,mBAAmB,QAwD7B;IAcD;;;;;OAKG;IACH,iBAHW,mBAAmB,GACjB,YAAY,CAcxB;IAED;;;;;;OAMG;IACH,qBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;;;OAKG;IACH,wBAHW,mBAAmB,GACjB,OAAO,CAInB;IAED;;;OAGG;IACH,8BAEC;IAED;;OAEG;IACH,6BAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;;OAGG;IACH,2BAUC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;;OAIG;IACH,8BAEC;IAED;;;OAGG;IACH,yBAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,yBAIC;IAED;;;OAGG;IACH,6BAIC;IAED;;;OAGG;IACH,8EAIC;IAED;;;;;;OAMG;IACH,mCAOC;IAED;;OAEG;IACH,+BAcC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,sBANW,gBAAgB,WAChB,CAAC,mBAAmB,GAAC,IAAI,CAAC,EAAE,aAC5B,CAAC,aAAa,GAAC,IAAI,CAAC,EAAE,eACtB,OAAO,GACL,MAAM,CAiLlB;IA2CD;;;;;;;;;;;;;;OAcG;IACH,uBALW,mBAAmB,EAAE,UACrB,MAAM,EAAE,WACR,OAAO,GACL,QAAQ,gBAAgB,CAAC,CAuIrC;IAED;;;;;;;;;;;;;OAaG;IACH;QAP+B,KAAK,EAAzB,UAAU;QACM,MAAM,EAAtB,MAAM;QACW,cAAc,GAA/B,MAAM;QAEoC,SAAS,GAAnD,0BAA0B,GAAC,IAAI;aA+EzC;IAy+BD,gBAsCC;;CACJ;yBA/7EY,OAAO,8DAA8D,EAAE,UAAU;iCACjF,OAAO,0BAA0B,EAAE,kBAAkB;kCACrD,OAAO,2BAA2B,EAAE,mBAAmB;yCACvD,OAAO,uDAAuD,EAAE,0BAA0B;4BAC1F,OAAO,iCAAiC,EAAE,aAAa;qCAnB/B,mCAAmC;6BAOjE,eAAe;iCAVyD,8BAA8B"}
@@ -59,6 +59,7 @@ import {
59
59
  shader_mesh_sdf_upload_store
60
60
  } from "./bake/shader_mesh_sdf_upload.js";
61
61
  import { ModelCacheBundle, ModelCacheBundleCache, ModelCacheBundleField } from "./bundle/ModelCacheBundle.js";
62
+ import { model_cache_bundle_sort_morton } from "./bundle/model_cache_bundle_sort_morton.js";
62
63
  import { download_texture_data } from "../../texture/download_texture_data.js";
63
64
  import { GPUMeshSurfaceCaches } from "./surface/GPUMeshSurfaceCaches.js";
64
65
  import {
@@ -1083,8 +1084,10 @@ export class GPUGeometrySDFManager {
1083
1084
  this.#ensure_headers(this.#geometries.__last_geometry_index);
1084
1085
 
1085
1086
  const layout = this.#layout;
1086
- /** the bundle's bricks the upload carries, by their place in it */
1087
+ /** the bundle's bricks the upload carries, by their place in it: placed below in the bundle's order */
1087
1088
  const place_of = new Map();
1089
+ /** each field taken's offset, entry count and indirection words, its entries naming bundle bricks until placed */
1090
+ const writes = [];
1088
1091
  const runs = [];
1089
1092
  const fields = [];
1090
1093
 
@@ -1133,19 +1136,12 @@ export class GPUGeometrySDFManager {
1133
1136
  const entry = field.entries[e];
1134
1137
 
1135
1138
  if (entry < MESH_SDF_EMPTY) {
1136
- let place = place_of.get(entry);
1137
-
1138
- if (place === undefined) {
1139
- place = place_of.size;
1140
- place_of.set(entry, place);
1141
- }
1142
-
1143
- // its place in the upload, which link turns into its slot
1144
- scratch[2 + e] = place;
1145
- } else {
1146
- scratch[2 + e] = entry;
1139
+ // the bundle's brick for now: its place in the upload, which link turns into its slot, below
1140
+ place_of.set(entry, 0);
1147
1141
  }
1148
1142
 
1143
+ scratch[2 + e] = entry;
1144
+
1149
1145
  scratch[2 + count + e] = MESH_SDF_UNNUMBERED;
1150
1146
  }
1151
1147
 
@@ -1154,7 +1150,7 @@ export class GPUGeometrySDFManager {
1154
1150
  scratch[2 + 2 * count + n] = field.numbered[n];
1155
1151
  }
1156
1152
 
1157
- this.#device.queue.writeBuffer(this.#indirection, 4 * range.offset, scratch);
1153
+ writes.push(range.offset, count, scratch);
1158
1154
 
1159
1155
  this.#records[id] = record;
1160
1156
  this.#ranges[id] = range;
@@ -1184,6 +1180,33 @@ export class GPUGeometrySDFManager {
1184
1180
  return 0;
1185
1181
  }
1186
1182
 
1183
+ // the bricks placed in the bundle's order, about the order the fresh pass pops their slots in (an atomic a
1184
+ // thread). A sorted bundle's (`model_cache_bundle_sort_morton`) is its own. A whole exported bundle's,
1185
+ // every field taken, is the order its fields first name them; with fields left out, the bricks of
1186
+ // those taken still keep the bundle's order
1187
+ const placed = Array.from(place_of.keys()).sort((a, b) => a - b);
1188
+
1189
+ for (let place = 0; place < placed.length; place++) {
1190
+ place_of.set(placed[place], place);
1191
+ }
1192
+
1193
+ // after every growth's copy is submitted, so none of these is copied over
1194
+ for (let w = 0; w < writes.length; w += 3) {
1195
+ const offset = writes[w];
1196
+ const count = writes[w + 1];
1197
+ const scratch = writes[w + 2];
1198
+
1199
+ for (let e = 0; e < count; e++) {
1200
+ const entry = scratch[2 + e];
1201
+
1202
+ if (entry < MESH_SDF_EMPTY) {
1203
+ scratch[2 + e] = place_of.get(entry);
1204
+ }
1205
+ }
1206
+
1207
+ this.#device.queue.writeBuffer(this.#indirection, 4 * offset, scratch);
1208
+ }
1209
+
1187
1210
  const brick_count = place_of.size;
1188
1211
  const bytes = new Uint8Array(Math.max(4, brick_count * MESH_SDF_BRICK_TEXEL_COUNT));
1189
1212
 
@@ -1273,11 +1296,19 @@ export class GPUGeometrySDFManager {
1273
1296
  * `caches`, as the device holds them when the readbacks land: each brick once, however many fields
1274
1297
  * hold it, and each cache naming its field. Read while nothing bakes, it is what was baked.
1275
1298
  *
1299
+ * With `morton`, the bundle is laid out for locality (`model_cache_bundle_sort_morton`): each field's
1300
+ * bricks numbered in Morton order, its surface blocks with them, and the bricks in that order, which
1301
+ * {@link upload_bundle} places them in. Off by default: worth it for assets prepared offline, where it
1302
+ * costs nothing at load, and worth about 0.5% to the probe clipmap's material gather there.
1303
+ *
1276
1304
  * @param {GPUGeometryMetadata[]} records
1277
1305
  * @param {number[]} caches surface cache ids, each of a geometry of `records`
1306
+ * @param {boolean} [morton] lay the bundle out in Morton order
1278
1307
  * @returns {Promise<ModelCacheBundle>}
1279
1308
  */
1280
- async export_bundle(records, caches) {
1309
+ async export_bundle(records, caches, morton = false) {
1310
+ assert.isBoolean(morton, 'morton');
1311
+
1281
1312
  this.#ensure_device();
1282
1313
 
1283
1314
  for (let i = 0; i < records.length; i++) {
@@ -1407,7 +1438,7 @@ export class GPUGeometrySDFManager {
1407
1438
  bundle.caches.push(this.#surfaces.export_cache(caches[i], field, data, new ModelCacheBundleCache()));
1408
1439
  }
1409
1440
 
1410
- return bundle;
1441
+ return morton ? model_cache_bundle_sort_morton(bundle) : bundle;
1411
1442
  }
1412
1443
 
1413
1444
  /**
@@ -91,8 +91,9 @@ export class ModelCacheBundleCache {
91
91
  * takes it only at the same.
92
92
  *
93
93
  * `GPUGeometrySDFManager.export_bundle` makes one of what is resident; `upload_bundle` takes one back,
94
- * with or without sharing its bricks with those resident; `model_cache_bundle_write` and
95
- * `model_cache_bundle_read` keep it as bytes.
94
+ * with or without sharing its bricks with those resident, placing them in the order the bundle holds
95
+ * them; `model_cache_bundle_write` and `model_cache_bundle_read` keep it as bytes; and
96
+ * `model_cache_bundle_sort_morton` lays one out in Morton order for offline preparation.
96
97
  */
97
98
  export class ModelCacheBundle {
98
99
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ModelCacheBundle.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH;IACI;;;OAGG;IACH,QAFU,YAAY,CAEO;IAE7B;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;OAGG;IACH,QAFU,WAAW,CAEO;IAE5B;;OAEG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,WAFU,MAAM,CAEF;IAEd;;;;OAIG;IACH,SAFU,WAAW,CAEQ;IAE7B;;;;OAIG;IACH,UAFU,WAAW,CAES;IAE9B;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,OAFU,WAAW,CAEM;CAC9B;AAED;;;GAGG;AACH;IACI;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,OAFU,WAAW,CAEM;IAE3B;;;;OAIG;IACH,UAFU,WAAW,CAES;IAE9B;;;;OAIG;IACH,QAFU,WAAW,EAAE,CAE+C;CACzE;AAED;;;;;;;;;GASG;AACH;IACI;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;OAGG;IACH,QAFU,UAAU,CAEO;IAE3B;;OAEG;IACH,QAFU,qBAAqB,EAAE,CAErB;IAEZ;;OAEG;IACH,QAFU,qBAAqB,EAAE,CAErB;IAEZ;;OAEG;IACH,0BAEC;CACJ"}
1
+ {"version":3,"file":"ModelCacheBundle.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH;IACI;;;OAGG;IACH,QAFU,YAAY,CAEO;IAE7B;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;OAGG;IACH,QAFU,WAAW,CAEO;IAE5B;;OAEG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,WAFU,MAAM,CAEF;IAEd;;;;OAIG;IACH,SAFU,WAAW,CAEQ;IAE7B;;;;OAIG;IACH,UAFU,WAAW,CAES;IAE9B;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,OAFU,WAAW,CAEM;CAC9B;AAED;;;GAGG;AACH;IACI;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,OAFU,WAAW,CAEM;IAE3B;;;;OAIG;IACH,UAFU,WAAW,CAES;IAE9B;;;;OAIG;IACH,QAFU,WAAW,EAAE,CAE+C;CACzE;AAED;;;;;;;;;;GAUG;AACH;IACI;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;OAGG;IACH,QAFU,UAAU,CAEO;IAE3B;;OAEG;IACH,QAFU,qBAAqB,EAAE,CAErB;IAEZ;;OAEG;IACH,QAFU,qBAAqB,EAAE,CAErB;IAEZ;;OAEG;IACH,0BAEC;CACJ"}
@@ -107,8 +107,9 @@ export class ModelCacheBundleCache {
107
107
  * takes it only at the same.
108
108
  *
109
109
  * `GPUGeometrySDFManager.export_bundle` makes one of what is resident; `upload_bundle` takes one back,
110
- * with or without sharing its bricks with those resident; `model_cache_bundle_write` and
111
- * `model_cache_bundle_read` keep it as bytes.
110
+ * with or without sharing its bricks with those resident, placing them in the order the bundle holds
111
+ * them; `model_cache_bundle_write` and `model_cache_bundle_read` keep it as bytes; and
112
+ * `model_cache_bundle_sort_morton` lays one out in Morton order for offline preparation.
112
113
  */
113
114
  export class ModelCacheBundle {
114
115
  /**
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A copy of a {@link ModelCacheBundle} laid out for locality, holding the same fields and caches: what
3
+ * every entry reads, the bytes of its brick and its surface blocks, is unchanged.
4
+ *
5
+ * - each field's stored bricks are numbered in (level, Morton code of the brick) order, and its block
6
+ * table and its caches' blocks follow: a brick's blocks keep its mask and come in number order;
7
+ * - the bundle's bricks are ordered as the fields first name them, field by field in that numbering,
8
+ * with bricks no field names after them. `upload_bundle` places a bundle's bricks in that order, and its
9
+ * fresh pass pops their slots in about that order (an atomic a thread), so a field's neighbouring bricks
10
+ * mostly sit in neighbouring slots.
11
+ *
12
+ * Measured (2026-11-11, a 69k-brick library loaded into the probe clipmap on an RTX 4090 and a Radeon
13
+ * RDNA2 iGPU): the SDF batch pass does not change, and the brick material gather is about 0.5% faster.
14
+ * Bake order is already near this one, so the sort is for offline asset preparation, where it costs
15
+ * nothing at load, and is off unless asked for (`GPUGeometrySDFManager.export_bundle`).
16
+ *
17
+ * @param {ModelCacheBundle} bundle
18
+ * @returns {ModelCacheBundle} a new bundle; `bundle` is left as it was
19
+ */
20
+ export function model_cache_bundle_sort_morton(bundle: ModelCacheBundle): ModelCacheBundle;
21
+ import { ModelCacheBundle } from "./ModelCacheBundle.js";
22
+ //# sourceMappingURL=model_cache_bundle_sort_morton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model_cache_bundle_sort_morton.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js"],"names":[],"mappings":"AA0FA;;;;;;;;;;;;;;;;;;GAkBG;AACH,uDAHW,gBAAgB,GACd,gBAAgB,CA2I5B;iCA9O8E,uBAAuB"}
@@ -0,0 +1,247 @@
1
+ import { assert } from "../../../../../core/assert.js";
2
+ import { v3_morton_encode_magicbits } from "../../../../../core/geom/3d/morton/v3_morton_encode_magicbits.js";
3
+ import { MESH_SDF_BRICK_TEXEL_COUNT, MESH_SDF_EMPTY } from "../MESH_SDF.js";
4
+ import {
5
+ MESH_SURFACE_PLANE_BLOCK_WORDS,
6
+ MESH_SURFACE_PRESENCE_BLOCK_WORDS,
7
+ MESH_SURFACE_TABLE_MASK_BITS
8
+ } from "../surface/MESH_SURFACE_BLOCK.js";
9
+ import { ModelCacheBundle, ModelCacheBundleCache, ModelCacheBundleField } from "./ModelCacheBundle.js";
10
+
11
+ /**
12
+ * Bricks along an axis a level's Morton code holds: 10 bits an axis.
13
+ * @type {number}
14
+ */
15
+ const MORTON_AXIS_LIMIT = 1 << 10;
16
+
17
+ /**
18
+ * @param {number} v
19
+ * @returns {number}
20
+ */
21
+ function popcount8(v) {
22
+ let c = 0;
23
+
24
+ for (let b = 0; b < 8; b++) {
25
+ c += (v >>> b) & 1;
26
+ }
27
+
28
+ return c;
29
+ }
30
+
31
+ /**
32
+ * Each entry's place in (level, Morton code of its brick) order, levels coarsening as `MeshSDFLayout`'s
33
+ * do: level k has ⌈bricks / 2^k⌉ along each axis, its entries after every finer level's, x fastest.
34
+ *
35
+ * @param {ModelCacheBundleField} field
36
+ * @returns {Float64Array} a key an entry
37
+ */
38
+ function entry_keys(field) {
39
+ const keys = new Float64Array(field.entries.length);
40
+
41
+ let e = 0;
42
+
43
+ for (let level = 0; level < field.level_count; level++) {
44
+ const nx = Math.ceil(field.bricks[0] / 2 ** level);
45
+ const ny = Math.ceil(field.bricks[1] / 2 ** level);
46
+ const nz = Math.ceil(field.bricks[2] / 2 ** level);
47
+
48
+ assert.ok(nx <= MORTON_AXIS_LIMIT && ny <= MORTON_AXIS_LIMIT && nz <= MORTON_AXIS_LIMIT, 'field.bricks: past the 10 bits an axis a Morton code holds');
49
+
50
+ for (let z = 0; z < nz; z++) {
51
+ for (let y = 0; y < ny; y++) {
52
+ for (let x = 0; x < nx; x++) {
53
+ // 30 bits of code under the level: exact in a double
54
+ keys[e++] = level * 2 ** 30 + v3_morton_encode_magicbits(x, y, z);
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ assert.equal(e, field.entries.length, 'field.entries: one a brick of its levels');
61
+
62
+ return keys;
63
+ }
64
+
65
+ /**
66
+ * `words` holding `per_block` words for each block, its blocks moved: run r of `runs` (old first block,
67
+ * new first block, blocks) from its old place to its new.
68
+ *
69
+ * @param {Uint32Array} words
70
+ * @param {number} per_block
71
+ * @param {number} blocks
72
+ * @param {number[]|null} runs null for a field with no table, whose blocks no brick numbers
73
+ * @returns {Uint32Array}
74
+ */
75
+ function move_blocks(words, per_block, blocks, runs) {
76
+ if (words.length === 0 || runs === null) {
77
+ return words.slice();
78
+ }
79
+
80
+ assert.equal(words.length, blocks * per_block, 'a cache\'s blocks: its field\'s, each of its plane\'s words');
81
+
82
+ const out = new Uint32Array(words.length);
83
+
84
+ for (let r = 0; r < runs.length; r += 3) {
85
+ out.set(words.subarray(runs[r] * per_block, (runs[r] + runs[r + 2]) * per_block), runs[r + 1] * per_block);
86
+ }
87
+
88
+ return out;
89
+ }
90
+
91
+ /**
92
+ * A copy of a {@link ModelCacheBundle} laid out for locality, holding the same fields and caches: what
93
+ * every entry reads, the bytes of its brick and its surface blocks, is unchanged.
94
+ *
95
+ * - each field's stored bricks are numbered in (level, Morton code of the brick) order, and its block
96
+ * table and its caches' blocks follow: a brick's blocks keep its mask and come in number order;
97
+ * - the bundle's bricks are ordered as the fields first name them, field by field in that numbering,
98
+ * with bricks no field names after them. `upload_bundle` places a bundle's bricks in that order, and its
99
+ * fresh pass pops their slots in about that order (an atomic a thread), so a field's neighbouring bricks
100
+ * mostly sit in neighbouring slots.
101
+ *
102
+ * Measured (2026-11-11, a 69k-brick library loaded into the probe clipmap on an RTX 4090 and a Radeon
103
+ * RDNA2 iGPU): the SDF batch pass does not change, and the brick material gather is about 0.5% faster.
104
+ * Bake order is already near this one, so the sort is for offline asset preparation, where it costs
105
+ * nothing at load, and is off unless asked for (`GPUGeometrySDFManager.export_bundle`).
106
+ *
107
+ * @param {ModelCacheBundle} bundle
108
+ * @returns {ModelCacheBundle} a new bundle; `bundle` is left as it was
109
+ */
110
+ export function model_cache_bundle_sort_morton(bundle) {
111
+ const out = new ModelCacheBundle();
112
+
113
+ out.voxel_size = bundle.voxel_size;
114
+ out.max_bricks = bundle.max_bricks;
115
+
116
+ const brick_count = bundle.brick_count;
117
+ /** the new index of each old brick, -1 until a field names it */
118
+ const brick_to = new Int32Array(brick_count).fill(-1);
119
+ let next_brick = 0;
120
+
121
+ /** each field's runs of moved blocks, for its caches */
122
+ const field_runs = [];
123
+
124
+ for (let f = 0; f < bundle.fields.length; f++) {
125
+ const field = bundle.fields[f];
126
+ const stored = field.numbered.length;
127
+ const keys = entry_keys(field);
128
+
129
+ // brick n's new number is its place in key order; entries are distinct, so no two keys tie
130
+ const order = Array.from({ length: stored }, (_, n) => n);
131
+
132
+ order.sort((a, b) => keys[field.numbered[a]] - keys[field.numbered[b]]);
133
+
134
+ const sorted = new ModelCacheBundleField();
135
+
136
+ sorted.origin.set(field.origin);
137
+ sorted.voxel = field.voxel;
138
+ sorted.bricks.set(field.bricks);
139
+ sorted.level_count = field.level_count;
140
+ sorted.two_sided = field.two_sided;
141
+ sorted.blocks = field.blocks;
142
+ sorted.numbered = new Uint32Array(stored);
143
+
144
+ for (let m = 0; m < stored; m++) {
145
+ sorted.numbered[m] = field.numbered[order[m]];
146
+ }
147
+
148
+ // without a table no block is numbered by a brick: a cache's blocks, if any, stay where they are
149
+ let runs = null;
150
+
151
+ if (field.table.length > 0) {
152
+ runs = [];
153
+ assert.equal(field.table.length, stored, 'field.table: a word a stored brick, or none');
154
+
155
+ sorted.table = new Uint32Array(stored);
156
+
157
+ // every block in exactly one brick's run, as a survey hands them out: what moves them losslessly
158
+ const covered = new Uint8Array(field.blocks);
159
+
160
+ let first = 0;
161
+
162
+ for (let m = 0; m < stored; m++) {
163
+ const word = field.table[order[m]];
164
+ const mask = word & ((1 << MESH_SURFACE_TABLE_MASK_BITS) - 1);
165
+ const count = popcount8(mask);
166
+ const from = word >>> MESH_SURFACE_TABLE_MASK_BITS;
167
+
168
+ sorted.table[m] = ((first << MESH_SURFACE_TABLE_MASK_BITS) | mask) >>> 0;
169
+
170
+ if (count > 0) {
171
+ assert.lessThanOrEqual(from + count, field.blocks, 'field.table: a run past the field\'s blocks');
172
+
173
+ for (let b = from; b < from + count; b++) {
174
+ assert.equal(covered[b], 0, 'field.table: two bricks\' runs share a block');
175
+ covered[b] = 1;
176
+ }
177
+
178
+ runs.push(from, first, count);
179
+ }
180
+
181
+ first += count;
182
+ }
183
+
184
+ assert.equal(first, field.blocks, 'field.blocks: the blocks its table\'s masks keep');
185
+ }
186
+
187
+ field_runs.push(runs);
188
+
189
+ // the bricks as this field first names them, in its new numbering
190
+ for (let m = 0; m < stored; m++) {
191
+ const brick = field.entries[sorted.numbered[m]];
192
+
193
+ assert.lessThan(brick, brick_count, 'a numbered entry names a brick of the bundle');
194
+
195
+ if (brick_to[brick] === -1) {
196
+ brick_to[brick] = next_brick++;
197
+ }
198
+ }
199
+
200
+ out.fields.push(sorted);
201
+ }
202
+
203
+ // bricks no field numbers: after the rest, as they were
204
+ for (let b = 0; b < brick_count; b++) {
205
+ if (brick_to[b] === -1) {
206
+ brick_to[b] = next_brick++;
207
+ }
208
+ }
209
+
210
+ out.bricks = new Uint8Array(bundle.bricks.length);
211
+
212
+ for (let b = 0; b < brick_count; b++) {
213
+ out.bricks.set(bundle.bricks.subarray(b * MESH_SDF_BRICK_TEXEL_COUNT, (b + 1) * MESH_SDF_BRICK_TEXEL_COUNT), brick_to[b] * MESH_SDF_BRICK_TEXEL_COUNT);
214
+ }
215
+
216
+ for (let f = 0; f < bundle.fields.length; f++) {
217
+ const entries = bundle.fields[f].entries;
218
+ const renamed = new Uint32Array(entries.length);
219
+
220
+ for (let e = 0; e < entries.length; e++) {
221
+ const entry = entries[e];
222
+
223
+ renamed[e] = entry < MESH_SDF_EMPTY ? brick_to[entry] : entry;
224
+ }
225
+
226
+ out.fields[f].entries = renamed;
227
+ }
228
+
229
+ for (const cache of bundle.caches) {
230
+ const sorted = new ModelCacheBundleCache();
231
+ const runs = field_runs[cache.field];
232
+ const blocks = bundle.fields[cache.field].blocks;
233
+
234
+ sorted.field = cache.field;
235
+ sorted.texels = cache.texels;
236
+ sorted.codes.set(cache.codes);
237
+ sorted.presence = move_blocks(cache.presence, MESH_SURFACE_PRESENCE_BLOCK_WORDS, blocks, runs);
238
+
239
+ for (let p = 0; p < cache.planes.length; p++) {
240
+ sorted.planes[p] = move_blocks(cache.planes[p], MESH_SURFACE_PLANE_BLOCK_WORDS[p], blocks, runs);
241
+ }
242
+
243
+ out.caches.push(sorted);
244
+ }
245
+
246
+ return out;
247
+ }
@@ -88,6 +88,56 @@ export class GPUProbeClipmapGI {
88
88
  * @returns {boolean}
89
89
  */
90
90
  get has_probes(): boolean;
91
+ /**
92
+ * Record the wants of a screen surface drawn apart from the G-buffer whose reader picks the frustum's probes a
93
+ * pixel (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): the water's interface. A pixel of each screen tile wants
94
+ * the cages its pick reads, as the G-buffer's pixels do (`ProbeClipmapScreenWants`).
95
+ *
96
+ * For a pass after this frame's {@link graph_update}, once the surface is drawn. Its wants are taken by the
97
+ * next frame's lifetime, so a probe the surface newly reads is there a frame after the surface is. Records
98
+ * nothing where there are no probes ({@link has_probes}): out of the mode it costs nothing.
99
+ *
100
+ * @param {Object} options
101
+ * @param {FrameGraph} options.graph
102
+ * @param {number} options.depth graph handle of the surface's reverse-Z depth, zero where it has none
103
+ * @param {number} options.normal graph handle of its normals, a `uint` texture: a channel holds a normal
104
+ * octahedral, as the G-buffer packs its own
105
+ * @param {number} [options.normal_channel] the channel that holds the normal, 0 to 3
106
+ * @param {boolean} [options.two_sided] whether the reader turns a normal that faces away from the eye to face it
107
+ * @param {GPUBuffer} options.camera the camera uniform the surface was drawn with
108
+ * @param {ArrayLike<number>} options.resolution the surface's pixels, x and y
109
+ */
110
+ graph_want_surface({ graph, depth, normal, normal_channel, two_sided, camera, resolution }: {
111
+ graph: FrameGraph;
112
+ depth: number;
113
+ normal: number;
114
+ normal_channel?: number;
115
+ two_sided?: boolean;
116
+ camera: GPUBuffer;
117
+ resolution: ArrayLike<number>;
118
+ }): void;
119
+ /**
120
+ * Record the wants of a list of meshlets a forward pass draws, whose fragments pick the frustum's probes
121
+ * (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): each wants the cages a reader anywhere inside its box can
122
+ * read (`graph_probe_clipmap_want_meshlets`).
123
+ *
124
+ * For a pass after this frame's {@link graph_update}; taken by the next frame's lifetime, as
125
+ * {@link graph_want_surface}'s are. Records nothing where there are no probes ({@link has_probes}).
126
+ *
127
+ * @param {Object} options
128
+ * @param {FrameGraph} options.graph
129
+ * @param {import("../../scene/GPUSceneContext.js").GPUSceneContext} options.scene the meshlets' scene
130
+ * @param {number} options.camera graph handle of the view's camera uniform
131
+ * @param {number} options.meshlet_collection graph handle of the list, `MESHLET_COLLECTION_STRUCT`
132
+ * @param {number} options.meshlet_iterator_command graph handle of the indirect dispatch that walks the list
133
+ */
134
+ graph_want_meshlets({ graph, scene, camera, meshlet_collection, meshlet_iterator_command }: {
135
+ graph: FrameGraph;
136
+ scene: import("../../scene/GPUSceneContext.js").GPUSceneContext;
137
+ camera: number;
138
+ meshlet_collection: number;
139
+ meshlet_iterator_command: number;
140
+ }): void;
91
141
  /**
92
142
  * Put what the probes' readers bind into `bindings`, `PROBE_CLIPMAP_SAMPLING_GROUP` but its sampler:
93
143
  * once {@link has_probes}, the probes as this frame's {@link graph_update} left them
@@ -1 +1 @@
1
- {"version":3,"file":"GPUProbeClipmapGI.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js"],"names":[],"mappings":"AA8BA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAwTI;;;;OAIG;IACH,oDAJW,eAAe,YACf,oBAAoB,GAClB,OAAO,CAUnB;IA5OD;;OAEG;IACH,sBAFW,eAAe,EAMzB;IAED;;OAEG;IACH,qCAEC;IAED;;OAEG;IACH,qCAEC;IAED;;OAEG;IACH,mCAEC;IAED;;OAEG;IACH,oCAEC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH;QAZ+B,KAAK,EAAzB,UAAU;QACc,IAAI,EAA5B,cAAc;QACgB,QAAQ,EAAtC,oBAAoB;QACJ,KAAK,EAArB,MAAM;QACU,MAAM,EAAtB,MAAM;QACK,IAAI;QACE,MAAM,GAAvB,MAAM;QAEU,QAAQ,EAAxB,MAAM;aAsIhB;IAqDD;;;OAGG;IACH,0BAEC;IAED;;;;;;;;;OASG;IACH,4CAUC;IAwDD;;;;;;;;;;;;;;;;OAgBG;IACH;QAR+B,KAAK,EAAzB,UAAU;QACc,IAAI,EAA5B,cAAc;QACgB,QAAQ,EAAtC,oBAAoB;QACF,UAAU,EAA5B,MAAM,EAAE;QACQ,QAAQ;QACtB,MAAM,CA8ClB;IAED;;;;;OAKG;IACH,uBAFW,aAAa,QASvB;IAED;;;OAGG;IACH,0BAHW,aAAa,GACX,OAAO,CAanB;IAqED;;;OAGG;IACH,gBA2BC;IAED,gBAcC;;CACJ;yBA1oBY,OAAO,8DAA8D,EAAE,UAAU;8BACjF,OAAO,0BAA0B,EAAE,eAAe;6BAClD,OAAO,8BAA8B,EAAE,cAAc;mCACrD,OAAO,2BAA2B,EAAE,oBAAoB;4BACxD,OAAO,4BAA4B,EAAE,aAAa;gCA1B/B,4BAA4B;gCAa5B,4BAA4B;uCAKrB,6BAA6B"}
1
+ {"version":3,"file":"GPUProbeClipmapGI.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js"],"names":[],"mappings":"AA+BA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAsUI;;;;OAIG;IACH,oDAJW,eAAe,YACf,oBAAoB,GAClB,OAAO,CAUnB;IA/OD;;OAEG;IACH,sBAFW,eAAe,EAMzB;IAED;;OAEG;IACH,qCAEC;IAED;;OAEG;IACH,qCAEC;IAED;;OAEG;IACH,mCAEC;IAED;;OAEG;IACH,oCAEC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH;QAZ+B,KAAK,EAAzB,UAAU;QACc,IAAI,EAA5B,cAAc;QACgB,QAAQ,EAAtC,oBAAoB;QACJ,KAAK,EAArB,MAAM;QACU,MAAM,EAAtB,MAAM;QACK,IAAI;QACE,MAAM,GAAvB,MAAM;QAEU,QAAQ,EAAxB,MAAM;aAyIhB;IAqDD;;;OAGG;IACH,0BAEC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH;QAT+B,KAAK,EAAzB,UAAU;QACM,KAAK,EAArB,MAAM;QACU,MAAM,EAAtB,MAAM;QAEW,cAAc,GAA/B,MAAM;QACY,SAAS,GAA3B,OAAO;QACY,MAAM;QACE,UAAU,EAArC,UAAU,MAAM,CAAC;aAmC3B;IAED;;;;;;;;;;;;;;OAcG;IACH;QAN+B,KAAK,EAAzB,UAAU;QACwD,KAAK,EAAvE,OAAO,gCAAgC,EAAE,eAAe;QACxC,MAAM,EAAtB,MAAM;QACU,kBAAkB,EAAlC,MAAM;QACU,wBAAwB,EAAxC,MAAM;aAiBhB;IAED;;;;;;;;;OASG;IACH,4CAUC;IAwDD;;;;;;;;;;;;;;;;OAgBG;IACH;QAR+B,KAAK,EAAzB,UAAU;QACc,IAAI,EAA5B,cAAc;QACgB,QAAQ,EAAtC,oBAAoB;QACF,UAAU,EAA5B,MAAM,EAAE;QACQ,QAAQ;QACtB,MAAM,CA8ClB;IAED;;;;;OAKG;IACH,uBAFW,aAAa,QASvB;IAED;;;OAGG;IACH,0BAHW,aAAa,GACX,OAAO,CAanB;IAqED;;;OAGG;IACH,gBA2BC;IAED,gBAcC;;CACJ;yBA9uBY,OAAO,8DAA8D,EAAE,UAAU;8BACjF,OAAO,0BAA0B,EAAE,eAAe;6BAClD,OAAO,8BAA8B,EAAE,cAAc;mCACrD,OAAO,2BAA2B,EAAE,oBAAoB;4BACxD,OAAO,4BAA4B,EAAE,aAAa;gCA3B/B,4BAA4B;gCAa5B,4BAA4B;uCAMrB,6BAA6B"}