@woosh/meep-engine 3.24.0 → 3.26.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 (349) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +59 -0
  3. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  4. package/src/core/geom/3d/shape/HeightMapShape3D.js +285 -0
  5. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
  7. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
  9. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
  11. package/src/engine/graphics3/PickingSystem.d.ts +3 -3
  12. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  13. package/src/engine/graphics3/PickingSystem.js +52 -55
  14. package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
  15. package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
  16. package/src/engine/graphics3/shader_picking_gather.js +120 -0
  17. package/src/engine/physics/cloth/MEASUREMENTS.md +1632 -0
  18. package/src/engine/physics/cloth/PLAN.md +738 -95
  19. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
  20. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  21. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
  22. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
  23. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
  24. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
  25. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
  26. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
  27. package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
  28. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +101 -29
  29. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  30. package/src/engine/physics/cloth/ecs/ClothInstance.js +110 -31
  31. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
  32. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
  33. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
  34. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +71 -81
  35. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  36. package/src/engine/physics/cloth/ecs/ClothSystem.js +135 -856
  37. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
  38. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
  39. package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
  40. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +323 -0
  41. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
  42. package/src/engine/physics/cloth/ecs/ClothWorld.js +1248 -0
  43. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +192 -0
  44. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
  45. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +578 -0
  46. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
  47. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
  48. package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
  49. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  50. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
  51. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +85 -3
  52. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  53. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +366 -271
  54. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +95 -12
  55. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  56. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +170 -27
  57. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
  58. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  59. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
  60. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
  61. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  62. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
  63. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
  64. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
  65. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
  66. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  67. package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
  68. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
  69. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
  70. package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
  71. package/src/engine/physics/cloth/playground/README.md +73 -2
  72. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  73. package/src/engine/physics/cloth/playground/wind.html +166 -0
  74. package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
  75. package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
  76. package/src/engine/physics/cloth/playground/wind_build.js +141 -0
  77. package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
  78. package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
  79. package/src/engine/physics/cloth/playground/wind_main.js +681 -0
  80. package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
  81. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  82. package/src/engine/physics/cloth/solver/ClothState.js +273 -12
  83. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
  84. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  85. package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
  86. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +45 -2
  87. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +46 -2
  89. package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
  90. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  91. package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
  92. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
  93. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
  94. package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
  95. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
  96. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
  98. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
  99. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
  101. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +102 -0
  102. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/wind/AbstractClothWind.js +114 -0
  104. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +87 -0
  105. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +185 -0
  107. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
  108. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/wind/ClothFluidWind.js +213 -0
  110. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +106 -0
  111. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
  112. package/src/engine/physics/cloth/wind/cloth_sample_air.js +297 -0
  113. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  114. package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
  115. package/src/shade/device/mock/texture_copy.js +28 -0
  116. package/src/shade/playground/vgeo_runtime/README.md +94 -0
  117. package/src/shade/playground/vgeo_runtime/index.html +62 -0
  118. package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
  119. package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
  120. package/src/shade/playground/vgeo_runtime/main.js +399 -0
  121. package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
  122. package/src/shade/renderer/camera/Camera.d.ts +14 -0
  123. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  124. package/src/shade/renderer/camera/Camera.js +7 -1
  125. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
  126. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
  127. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  128. package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
  129. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
  130. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
  132. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
  133. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
  134. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
  135. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
  136. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  137. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
  138. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
  139. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
  141. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
  142. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
  143. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
  144. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
  145. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  146. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
  147. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
  148. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
  149. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
  150. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
  151. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
  152. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
  153. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
  154. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  155. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
  156. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
  157. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  158. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
  159. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  160. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
  161. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  162. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
  163. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  164. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
  165. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  166. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
  167. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
  171. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
  172. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
  212. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
  213. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
  250. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
  251. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
  252. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
  262. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
  263. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
  264. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
  265. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
  271. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
  272. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
  273. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
  274. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
  275. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
  276. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
  277. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
  278. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
  279. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
  280. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
  281. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
  282. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
  283. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
  284. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
  285. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
  286. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
  287. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
  288. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
  289. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
  290. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
  291. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
  292. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
  293. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
  294. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
  295. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
  296. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
  297. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
  298. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  299. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  300. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  301. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
  302. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  303. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
  304. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  305. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
  306. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  307. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
  308. package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
  309. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  310. package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
  311. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  312. package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
  313. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
  314. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
  315. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
  316. package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
  317. package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
  318. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
  319. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
  320. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
  321. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
  322. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
  323. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
  324. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
  325. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
  326. package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
  327. package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
  328. package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
  329. package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
  330. package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
  331. package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
  332. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
  333. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
  334. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
  335. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
  336. package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
  337. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
  338. package/src/shade/renderer/scene/Mesh.d.ts +0 -55
  339. package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
  340. package/src/shade/renderer/scene/Node3D.d.ts +0 -159
  341. package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
  342. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
  343. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
  344. package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
  345. package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
  346. package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
  347. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
  348. package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
  349. package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
@@ -7,6 +7,7 @@ import { min2 } from "../../../math/min2.js";
7
7
  import { seededRandom } from "../../../math/random/seededRandom.js";
8
8
  import { number_compare_ascending } from "../../../primitives/numbers/number_compare_ascending.js";
9
9
  import { v3_dot } from "../../vec3/v3_dot.js";
10
+ import { Ray3 } from "../ray/Ray3.js";
10
11
  import { AbstractShape3D } from "./AbstractShape3D.js";
11
12
  import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
12
13
 
@@ -326,6 +327,69 @@ export class UnionShape3D extends AbstractShape3D {
326
327
 
327
328
  }
328
329
 
330
+ /**
331
+ * Nearest hit across the children, which all share the union's own frame — so, unlike the other
332
+ * two wrappers, there is no ray to re-frame and no answer to map back.
333
+ *
334
+ * Each child is handed the best distance so far as its `tMax`, so a child can only report a hit by
335
+ * beating every child before it. That is what makes it safe to let the children write straight into
336
+ * `hit`: a child that writes is a child that won, and a child that misses leaves `hit` untouched by
337
+ * the family convention, so the standing answer survives it.
338
+ *
339
+ * The distance to narrow on is recovered from the point the child wrote, as
340
+ * `(p − origin)·direction` — the shape-level API hands back a point where the narrowphase's
341
+ * `refine_ray_union` has the distance already. Two children closer together than a float32 ulp
342
+ * of the coordinates involved are therefore a tie, settled by whichever is listed last.
343
+ *
344
+ * That ulp is the API's, not this method's: a child writes `origin + direction · t` into a float32
345
+ * `hit` before anything here reads it, so the resolution is already spent by the time a LONE shape
346
+ * answers. Measured against the narrowphase over 4,000 rays per scale, this union's error tracks a
347
+ * lone sphere's within a factor of two everywhere — 3e-6 near the origin, 1e-3 at 1e4 out, 0.1 at
348
+ * 1e6, where one float32 ulp IS 0.06 world units. A compound collider that far out wants a float64
349
+ * ray, which is what the narrowphase path already gives it; it does not want a different union.
350
+ *
351
+ * DIVERGENCE from `refine_ray_union`: that one carries a sentinel for a shape it cannot answer and
352
+ * poisons the entire union with it, because reporting the nearest of the children it COULD answer
353
+ * would be a hit confidently too far. There is no sentinel in this API — a child that does not
354
+ * implement `raycast` throws from {@link AbstractShape3D#raycast} — but the effect is the one that
355
+ * matters: every child is visited unconditionally, so such a child is never quietly skipped, and
356
+ * the throw leaves the union with no answer rather than a partial one.
357
+ *
358
+ * @param {Float32Array|number[]} hit out: [px, py, pz, nx, ny, nz]
359
+ * @param {Ray3} ray union-frame ray (origin in [0..2], unit direction in [3..5], tMax in [6])
360
+ * @returns {boolean} whether anything was hit
361
+ */
362
+ raycast(hit, ray) {
363
+ const children = this.children;
364
+ const child_count = children.length;
365
+
366
+ const ox = ray[0], oy = ray[1], oz = ray[2];
367
+ const dx = ray[3], dy = ray[4], dz = ray[5];
368
+
369
+ // Allocated per call rather than kept as a module scratch: a union may hold another wrapper,
370
+ // and every level of that recursion needs its own narrowing ray alive across the loop below.
371
+ const child_ray = new Ray3();
372
+
373
+ child_ray[0] = ox; child_ray[1] = oy; child_ray[2] = oz;
374
+ child_ray[3] = dx; child_ray[4] = dy; child_ray[5] = dz;
375
+ child_ray[6] = ray[6];
376
+
377
+ let found = false;
378
+
379
+ for (let i = 0; i < child_count; i++) {
380
+ if (!children[i].raycast(hit, child_ray)) {
381
+ continue;
382
+ }
383
+
384
+ // The direction is unit, so the hit's projection onto it IS the distance travelled.
385
+ child_ray[6] = (hit[0] - ox) * dx + (hit[1] - oy) * dy + (hit[2] - oz) * dz;
386
+
387
+ found = true;
388
+ }
389
+
390
+ return found;
391
+ }
392
+
329
393
  /**
330
394
  *
331
395
  * @param {UnionShape3D} other
@@ -2,12 +2,12 @@
2
2
  * Answers "what is under this pixel" for entities that asked to be pickable.
3
3
  *
4
4
  * **Off the visibility buffer.** The rasterizer writes every pixel's `meshes` row — an entity's
5
- * row, one on — and its depth; a pick copies those two texels out of the frame that drew them and
5
+ * row, one on — and its depth; a pick reads those two texels out of the frame that drew them and
6
6
  * resolves the row to the entity that drew it, then up its parents to the one that opted in. What
7
7
  * was drawn is what is picked: at triangle precision, under skinning, with nothing kept on the CPU
8
8
  * for it — no bounds, no tree, no per-frame refresh.
9
9
  *
10
- * **Asynchronous and batched, of necessity.** The texels are copied by the frame after the query
10
+ * **Asynchronous and batched, of necessity.** The texels are gathered by the frame after the query
11
11
  * was asked and read back when the device has finished it, so an answer is a frame or two late and
12
12
  * arrives for the whole batch at once. A result is a promise for that reason, and nothing this
13
13
  * tick can come to depend on it.
@@ -79,7 +79,7 @@ export class PickingSystem extends System<any> {
79
79
  #private;
80
80
  }
81
81
  /**
82
- * Copies the queried texels out of the frame that drew them, after the G-buffer is written and
82
+ * Gathers the queried texels out of the frame that drew them, after the G-buffer is written and
83
83
  * before anything overwrites the visibility buffer, and answers the batch when they land.
84
84
  */
85
85
  export class PickingExtension extends RenderExtension {
@@ -1 +1 @@
1
- {"version":3,"file":"PickingSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/PickingSystem.js"],"names":[],"mappings":"AA2BA;;;;;;;;;;;;;;;;GAgBG;AACH;IAyBI;;OAEG;IACH,sCAQC;IADG,kCAA8B;IAGlC,2CAIC;IAED,4CAYC;IAED;;;OAGG;IACH,eAHW,QAAQ,UACR,MAAM,QAIhB;IAED;;;OAGG;IACH,iBAHW,QAAQ,UACR,MAAM,QAIhB;IAED;;;;OAIG;IACH,6BAEC;IAED;;;;OAIG;IACH,4BAEC;IAED;;;;;;;;;;;OAWG;IACH,cAHW,cAAc,GACZ,QAAQ,aAAa,EAAE,CAAC,CAYpC;IAED;;;;OAIG;IACH,gBAFa;QAAC,OAAO,EAAE,cAAc,CAAC;QAAC,OAAO,SAAW,aAAa,EAAE,KAAG,IAAI,CAAC;QAAC,MAAM,SAAW,KAAK,KAAG,IAAI,CAAA;KAAC,EAAE,CAIhH;IAED;;;;;;OAMG;IACH,iBAHW,MAAM,GACJ,MAAM,CAuBlB;;CACJ;AAED;;;GAGG;AACH;IASI;;OAEG;IACH,oBAFW,aAAa,EAMvB;;CA8IJ;uBAhWsB,kBAAkB;yBAChB,eAAe;8BACV,oBAAoB;gCAPlB,mDAAmD"}
1
+ {"version":3,"file":"PickingSystem.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/PickingSystem.js"],"names":[],"mappings":"AA0BA;;;;;;;;;;;;;;;;GAgBG;AACH;IAyBI;;OAEG;IACH,sCAQC;IADG,kCAA8B;IAGlC,2CAIC;IAED,4CAYC;IAED;;;OAGG;IACH,eAHW,QAAQ,UACR,MAAM,QAIhB;IAED;;;OAGG;IACH,iBAHW,QAAQ,UACR,MAAM,QAIhB;IAED;;;;OAIG;IACH,6BAEC;IAED;;;;OAIG;IACH,4BAEC;IAED;;;;;;;;;;;OAWG;IACH,cAHW,cAAc,GACZ,QAAQ,aAAa,EAAE,CAAC,CAYpC;IAED;;;;OAIG;IACH,gBAFa;QAAC,OAAO,EAAE,cAAc,CAAC;QAAC,OAAO,SAAW,aAAa,EAAE,KAAG,IAAI,CAAC;QAAC,MAAM,SAAW,KAAK,KAAG,IAAI,CAAA;KAAC,EAAE,CAIhH;IAED;;;;;;OAMG;IACH,iBAHW,MAAM,GACJ,MAAM,CAuBlB;;CACJ;AAED;;;GAGG;AACH;IASI;;OAEG;IACH,oBAFW,aAAa,EAMvB;;CA4IJ;uBA7VsB,kBAAkB;yBAChB,eAAe;8BACV,oBAAoB;gCAPlB,mDAAmD"}
@@ -11,30 +11,29 @@ import { ParentEntity } from "../ecs/parent/ParentEntity.js";
11
11
  import { System } from "../ecs/System.js";
12
12
  import { Pickable } from "./Pickable.js";
13
13
  import { PickingResult } from "./PickingResult.js";
14
+ import {
15
+ PICKING_GATHER_STRIDE_WORDS,
16
+ PICKING_QUERY_OFF_VIEW,
17
+ shader_picking_gather
18
+ } from "./shader_picking_gather.js";
14
19
 
15
20
  /**
16
- * Bytes one texel's copy occupies in the readback: WebGPU rounds `bytesPerRow` up to 256, and
17
- * each query copies two texels — the mesh row and the depth — one row each.
21
+ * Bytes a query occupies in the gather buffer: the mesh row and the depth, one word each.
18
22
  *
19
23
  * @type {number}
20
24
  */
21
- const TEXEL_STRIDE = 256;
22
-
23
- /**
24
- * @type {number}
25
- */
26
- const QUERY_STRIDE = TEXEL_STRIDE * 2;
25
+ const QUERY_STRIDE = PICKING_GATHER_STRIDE_WORDS * 4;
27
26
 
28
27
  /**
29
28
  * Answers "what is under this pixel" for entities that asked to be pickable.
30
29
  *
31
30
  * **Off the visibility buffer.** The rasterizer writes every pixel's `meshes` row — an entity's
32
- * row, one on — and its depth; a pick copies those two texels out of the frame that drew them and
31
+ * row, one on — and its depth; a pick reads those two texels out of the frame that drew them and
33
32
  * resolves the row to the entity that drew it, then up its parents to the one that opted in. What
34
33
  * was drawn is what is picked: at triangle precision, under skinning, with nothing kept on the CPU
35
34
  * for it — no bounds, no tree, no per-frame refresh.
36
35
  *
37
- * **Asynchronous and batched, of necessity.** The texels are copied by the frame after the query
36
+ * **Asynchronous and batched, of necessity.** The texels are gathered by the frame after the query
38
37
  * was asked and read back when the device has finished it, so an answer is a frame or two late and
39
38
  * arrives for the whole batch at once. A result is a promise for that reason, and nothing this
40
39
  * tick can come to depend on it.
@@ -199,7 +198,7 @@ export class PickingSystem extends System {
199
198
  }
200
199
 
201
200
  /**
202
- * Copies the queried texels out of the frame that drew them, after the G-buffer is written and
201
+ * Gathers the queried texels out of the frame that drew them, after the G-buffer is written and
203
202
  * before anything overwrites the visibility buffer, and answers the batch when they land.
204
203
  */
205
204
  export class PickingExtension extends RenderExtension {
@@ -251,61 +250,57 @@ export class PickingExtension extends RenderExtension {
251
250
  }
252
251
  }
253
252
 
253
+ /*
254
+ The pixel each query names, resolved here rather than in the shader: the fraction is the
255
+ caller's unit and the resolution is the frame's, and neither is the gather's business. A
256
+ query that is not on the view at all carries `PICKING_QUERY_OFF_VIEW` instead of a pixel.
257
+ */
258
+ const pixels = new Uint32Array(queries.length * PICKING_GATHER_STRIDE_WORDS);
259
+
260
+ for (let i = 0; i < queries.length; i++) {
261
+ const query = queries[i];
262
+ const base = i * PICKING_GATHER_STRIDE_WORDS;
263
+
264
+ if (on_view(query)) {
265
+ pixels[base] = texel(query.u, width);
266
+ pixels[base + 1] = texel(query.v, height);
267
+ } else {
268
+ pixels[base] = PICKING_QUERY_OFF_VIEW;
269
+ }
270
+ }
271
+
254
272
  const textures = frame.get(ViewTextures);
255
273
  const graph = frame.graph;
256
274
 
257
- // A transient pool buffer carries what its last tenant left: a query off the view has to
258
- // read as nothing rather than as whatever that was, so the buffer is cleared before the
259
- // copies land in it.
260
- const cleared = {};
261
- const clear = graph.add("Picking / clear texels", cleared, (d, resources, context) => {
262
- context.encoder.clearBuffer(resources.get(d.target));
263
- });
264
-
265
- cleared.target = clear.create("picking/texels", BufferResourceDescriptor.from(
266
- queries.length * QUERY_STRIDE,
267
- GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
268
- ));
269
-
270
275
  const data = {};
271
- const pass = graph.add("Picking / copy texels", data, (data, resources, context) => {
272
- const mesh = resources.get(data.mesh).gpu_texture;
273
- const depth = resources.get(data.depth).gpu_texture;
274
- const target = resources.get(data.target);
276
+ const pass = graph.add("Picking / gather texels", data, (data, resources, context) => {
275
277
  const encoder = context.encoder;
276
278
 
277
- for (let i = 0; i < queries.length; i++) {
278
- const query = queries[i];
279
-
280
- if (!on_view(query)) {
281
- // off the view: nothing is copied, and the texel reads as nothing
282
- continue;
283
- }
284
-
285
- const origin = { x: texel(query.u, width), y: texel(query.v, height) };
286
- const offset = i * QUERY_STRIDE;
287
-
288
- encoder.copyTextureToBuffer(
289
- { texture: mesh, origin },
290
- { buffer: target, offset, bytesPerRow: TEXEL_STRIDE },
291
- [1, 1, 1]
292
- );
293
-
294
- encoder.copyTextureToBuffer(
295
- { texture: depth, origin, aspect: "depth-only" },
296
- { buffer: target, offset: offset + TEXEL_STRIDE, bytesPerRow: TEXEL_STRIDE },
297
- [1, 1, 1]
298
- );
299
- }
279
+ shader_picking_gather.dispatchThreads({
280
+ encoder,
281
+ bindings: {
282
+ query_count: queries.length,
283
+ viz_mesh: resources.get(data.mesh),
284
+ viz_depth: resources.get(data.depth),
285
+ queries: encoder.allocateTransientBufferAndLoad(
286
+ pixels.buffer, GPUBufferUsage.STORAGE
287
+ ),
288
+ results: resources.get(data.results),
289
+ },
290
+ thread_count_x: queries.length,
291
+ });
300
292
  });
301
293
 
302
294
  data.mesh = pass.read(textures.visibility_mesh);
303
295
  data.depth = pass.read(textures.depth);
304
- data.target = pass.write(cleared.target);
296
+ data.results = pass.create("picking/results", BufferResourceDescriptor.from(
297
+ queries.length * QUERY_STRIDE,
298
+ GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
299
+ ));
305
300
 
306
301
  const system = this.#system;
307
302
 
308
- graph_read_buffer({ graph, buffer: data.target })
303
+ graph_read_buffer({ graph, buffer: data.results })
309
304
  .then(ref => {
310
305
  try {
311
306
  const words = new Uint32Array(ref.getValue());
@@ -323,10 +318,12 @@ export class PickingExtension extends RenderExtension {
323
318
  results.push(result);
324
319
 
325
320
  if (!on_view(query)) {
321
+ // the gather writes an invalid row here too; this is the same
322
+ // answer without depending on a dispatch having run
326
323
  continue;
327
324
  }
328
325
 
329
- const base = index * QUERY_STRIDE / 4;
326
+ const base = index * PICKING_GATHER_STRIDE_WORDS;
330
327
  const entity = system.resolve_row(words[base]);
331
328
 
332
329
  if (entity === PickingResult.NOTHING) {
@@ -338,7 +335,7 @@ export class PickingExtension extends RenderExtension {
338
335
  unproject(
339
336
  result.position, view_projection,
340
337
  texel(query.u, width), texel(query.v, height), width, height,
341
- floats[base + TEXEL_STRIDE / 4]
338
+ floats[base + 1]
342
339
  );
343
340
 
344
341
  result.distance = Math.hypot(
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Words a query occupies, on the way in and on the way back: a pixel's x and y going in, the mesh
3
+ * row and the depth's bit pattern coming out.
4
+ *
5
+ * @type {number}
6
+ */
7
+ export const PICKING_GATHER_STRIDE_WORDS: number;
8
+ /**
9
+ * The `x` of a query whose point is not on the view at all.
10
+ *
11
+ * A pick names a fraction of the view and a caller is free to ask outside it, so a query carries
12
+ * either a pixel or this. No pixel can collide with it: `maxTextureDimension2D` is nowhere near
13
+ * 2^32 - 1 in any WebGPU profile, so there is no view this is a column of.
14
+ *
15
+ * @type {number}
16
+ */
17
+ export const PICKING_QUERY_OFF_VIEW: number;
18
+ /**
19
+ * @type {number}
20
+ */
21
+ export const PICKING_GATHER_WORKGROUP_SIZE: number;
22
+ /**
23
+ * Reads the visibility buffer's mesh row and the frame's depth at a handful of pixels, into a
24
+ * buffer small enough to read back on a click.
25
+ *
26
+ * **A dispatch rather than a copy, twice over.** The obvious shape for this is
27
+ * `copyTextureToBuffer` of a 1x1 region per query, and it is not legal WebGPU for either texture.
28
+ * The visibility buffer is a render attachment the renderer never gave `COPY_SRC` — and should not
29
+ * have to, since the flag is for the whole frame and a pick happens on a click — while a depth
30
+ * format may not be sub-region copied **at all**: "if the format is a depth-or-stencil format [...]
31
+ * the subresource size is equal to size", so the only legal copy of a 1065x1668 depth buffer is all
32
+ * 7 MB of it. Both textures are already `TEXTURE_BINDING`, because the frame shades from them, and
33
+ * `textureLoad` has neither restriction.
34
+ *
35
+ * One thread per query. Nothing is sampled, filtered or interpolated: the answer has to be the row
36
+ * the rasterizer wrote at that exact pixel, which is what makes a pick as precise as the frame.
37
+ */
38
+ export const shader_picking_gather: ComputeShader;
39
+ import { ComputeShader } from "../../shade/renderer/shader/ComputeShader.js";
40
+ //# sourceMappingURL=shader_picking_gather.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_picking_gather.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/shader_picking_gather.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AACH,0CAFU,MAAM,CAE6B;AAE7C;;;;;;;;GAQG;AACH,qCAFU,MAAM,CAEiC;AAEjD;;GAEG;AACH,4CAFU,MAAM,CAEgC;AAkEhD;;;;;;;;;;;;;;;GAeG;AACH,kDAIG;8BAnH2B,8CAA8C"}
@@ -0,0 +1,120 @@
1
+ import {
2
+ VIZ_BUFFER_INVALID_MESH_VALUE
3
+ } from "../../shade/renderer/rasterize/native/viz/VIZ_BUFFER_INVALID_MESH_VALUE.js";
4
+ import { CodeChunk } from "../../shade/renderer/shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../shade/renderer/shader/ComputeShader.js";
6
+ import {
7
+ ShaderResourceSetDescriptor
8
+ } from "../../shade/renderer/shader/resource/ShaderResourceSetDescriptor.js";
9
+ import { u32 } from "../../shade/renderer/shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
10
+ import { WebGPUArray } from "../../shade/renderer/shader/type/WebGPUArray.js";
11
+
12
+ /**
13
+ * Words a query occupies, on the way in and on the way back: a pixel's x and y going in, the mesh
14
+ * row and the depth's bit pattern coming out.
15
+ *
16
+ * @type {number}
17
+ */
18
+ export const PICKING_GATHER_STRIDE_WORDS = 2;
19
+
20
+ /**
21
+ * The `x` of a query whose point is not on the view at all.
22
+ *
23
+ * A pick names a fraction of the view and a caller is free to ask outside it, so a query carries
24
+ * either a pixel or this. No pixel can collide with it: `maxTextureDimension2D` is nowhere near
25
+ * 2^32 - 1 in any WebGPU profile, so there is no view this is a column of.
26
+ *
27
+ * @type {number}
28
+ */
29
+ export const PICKING_QUERY_OFF_VIEW = 0xFFFFFFFF;
30
+
31
+ /**
32
+ * @type {number}
33
+ */
34
+ export const PICKING_GATHER_WORKGROUP_SIZE = 64;
35
+
36
+ const resources = new ShaderResourceSetDescriptor();
37
+
38
+ // per-dispatch, four bytes, read-only: immediate data rather than a uniform buffer
39
+ resources.setImmediate("query_count", u32);
40
+
41
+ resources.createGroup()
42
+ // The frame's visibility buffer — the `meshes` row the rasterizer wrote at each pixel — and the
43
+ // depth it wrote with it. Both are read as *bindings*, which is the whole reason this pass is a
44
+ // dispatch: see the note on {@link shader_picking_gather}.
45
+ .addTexture("viz_mesh", "uint")
46
+ .addTexture("viz_depth", "depth");
47
+
48
+ resources.createGroup()
49
+ // x, y per query; `PICKING_QUERY_OFF_VIEW` in x for a query that is off the view
50
+ .addStorageBuffer("queries", WebGPUArray.u32)
51
+ // mesh row, then the depth's bits, per query
52
+ .addStorageBuffer("results", WebGPUArray.u32, true);
53
+
54
+ const body = CodeChunk.from(
55
+ //language=WGSL
56
+ `
57
+ const PICKING_STRIDE : u32 = ${PICKING_GATHER_STRIDE_WORDS}u;
58
+ const PICKING_OFF_VIEW : u32 = ${PICKING_QUERY_OFF_VIEW}u;
59
+ const PICKING_VIZ_INVALID : u32 = ${VIZ_BUFFER_INVALID_MESH_VALUE}u;
60
+
61
+ @compute @workgroup_size(${PICKING_GATHER_WORKGROUP_SIZE},1,1)
62
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
63
+ let index = gid.x;
64
+
65
+ /*
66
+ The dispatch is sized to ceil(query_count / 64) workgroups, so the tail carries up to 63 idle
67
+ threads. Guarded on the immediate rather than on arrayLength: both buffers come from the
68
+ transient pool, which matches approximately, so their lengths are pool state rather than the
69
+ number of queries — a thread past the end would read a previous tenant's pixel and write a row
70
+ nobody asked for.
71
+ */
72
+ if index >= query_count {
73
+ return;
74
+ }
75
+
76
+ let base = index * PICKING_STRIDE;
77
+
78
+ let x = queries[base];
79
+ let y = queries[base + 1u];
80
+
81
+ /*
82
+ Every slot is written, the off-view ones included. A pooled buffer arrives carrying whatever its
83
+ last tenant left, and a query off the view has to read back as nothing rather than as that — so
84
+ the pass defines the whole of its output instead of a clear being encoded ahead of it.
85
+ */
86
+ if x == PICKING_OFF_VIEW {
87
+ results[base] = PICKING_VIZ_INVALID;
88
+ results[base + 1u] = 0u;
89
+
90
+ return;
91
+ }
92
+
93
+ let at = vec2<i32>(i32(x), i32(y));
94
+
95
+ results[base] = textureLoad(viz_mesh, at, 0).r;
96
+ results[base + 1u] = bitcast<u32>(textureLoad(viz_depth, at, 0));
97
+ }
98
+ `);
99
+
100
+ /**
101
+ * Reads the visibility buffer's mesh row and the frame's depth at a handful of pixels, into a
102
+ * buffer small enough to read back on a click.
103
+ *
104
+ * **A dispatch rather than a copy, twice over.** The obvious shape for this is
105
+ * `copyTextureToBuffer` of a 1x1 region per query, and it is not legal WebGPU for either texture.
106
+ * The visibility buffer is a render attachment the renderer never gave `COPY_SRC` — and should not
107
+ * have to, since the flag is for the whole frame and a pick happens on a click — while a depth
108
+ * format may not be sub-region copied **at all**: "if the format is a depth-or-stencil format [...]
109
+ * the subresource size is equal to size", so the only legal copy of a 1065x1668 depth buffer is all
110
+ * 7 MB of it. Both textures are already `TEXTURE_BINDING`, because the frame shades from them, and
111
+ * `textureLoad` has neither restriction.
112
+ *
113
+ * One thread per query. Nothing is sampled, filtered or interpolated: the answer has to be the row
114
+ * the rasterizer wrote at that exact pixel, which is what makes a pick as precise as the frame.
115
+ */
116
+ export const shader_picking_gather = ComputeShader.from({
117
+ label: "Picking/Gather",
118
+ resources,
119
+ body,
120
+ });