@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
@@ -104,6 +104,34 @@ function texture_endpoint_refusal(info, role, required_usage, required_usage_nam
104
104
  return `${role} copySize.height (${extent.height}) is not a multiple of the ${format.block_height}-texel block height of ${texture.format}`;
105
105
  }
106
106
 
107
+ /*
108
+ WebGPU's rule for `copyTextureToBuffer`/`copyBufferToTexture`/`writeTexture`: "if the
109
+ GPUTexture.format is a depth-or-stencil format or GPUTexture.sampleCount is more than 1, the
110
+ subresource size is equal to size". A depth buffer is copied whole or not at all — there is no
111
+ reading one texel of one, and the one-pixel read that looks like the obvious way to pick an
112
+ entity off the frame's depth is the thing this forbids. The restriction comes from D3D12, so
113
+ it is enforced everywhere rather than being a Windows-only surprise.
114
+
115
+ Only the two axes a region is named in: this does not also require a layered copy to take every
116
+ layer, which WebGPU's definition of a subresource's size does.
117
+ */
118
+ const depth_or_stencil = !format.aspects.includes("all");
119
+
120
+ if (depth_or_stencil || texture.sampleCount > 1) {
121
+ const full_width = texture.mip_width(mip);
122
+ const full_height = texture.mip_height(mip);
123
+
124
+ if (origin.x !== 0 || origin.y !== 0 || extent.width !== full_width || extent.height !== full_height) {
125
+ const why = depth_or_stencil
126
+ ? `is ${texture.format}, a depth-or-stencil format`
127
+ : `has sampleCount ${texture.sampleCount}`;
128
+
129
+ return `${role} texture '${texture.label}' ${why}, so a copy must cover the whole`
130
+ + ` subresource; mip ${mip} is ${full_width}x${full_height} and the region asked for`
131
+ + ` is ${extent.width}x${extent.height} at (${origin.x}, ${origin.y})`;
132
+ }
133
+ }
134
+
107
135
  return null;
108
136
  }
109
137
 
@@ -0,0 +1,94 @@
1
+ # `vgeo_runtime` — the cut, on the GPU, through the engine
2
+
3
+ A `.vgeo` container drawn as an ordinary `Mesh`, in an ordinary `Scene`, with an ordinary material.
4
+ This page draws nothing itself: every triangle on screen is there because the compute cut appended
5
+ `MESHLET_DEFINITION_STRUCT` records into the same collection a static mesh's meshlets go into, and
6
+ the HZB meshlet filter, the material bucket, the indirect draw and the G-buffer took it from there
7
+ without knowing that virtual geometry exists.
8
+
9
+ That is the whole difference from [`../vgeo_viewer/`](../vgeo_viewer/README.md), and the two are
10
+ worth keeping apart. The viewer draws a **CPU** cut through Shade's direct geometry path — it
11
+ proves the DAG, the format and the residency clamp, and by construction it proves nothing about the
12
+ engine. This page proves the engine seam and nothing about the DAG, because the DAG has its own
13
+ tests and its own oracle.
14
+
15
+ ## What it shows
16
+
17
+ The container is built in the page and opened holding **only its root page**. Everything else
18
+ arrives because the cut asked for it: a clamped cluster emits a want, the want names the page it
19
+ was discovered through, the feedback readback resolves it to a byte range out of that page's own
20
+ child table, and the page installs. Nothing is prefetched and no directory is read.
21
+
22
+ Measured on an nvidia/lovelace adapter, a 128×48 torus at 64 KB pages — 13 pages, built in ~0.5 s
23
+ in-page — and **re-measured on the same adapter after the review campaign**, which rewrote the VRAM
24
+ tier onto fixed-stride page slots, moved selectability off the RAM tier, corrected the near plane's
25
+ sign and replaced the scale correction. Every row is identical:
26
+
27
+ | τ (px) | drawn clusters | pages visited | clamped | wavefronts | queue remaining |
28
+ |---:|---:|---:|---:|---:|---:|
29
+ | 0.5 | 50 | 9 | 0 | 14 | 0 |
30
+ | 1 | 31 | 8 | 0 | 14 | 0 |
31
+ | 2 | 18 | 6 | 0 | 11 | 0 |
32
+ | 4 | 17 | 6 | 0 | 11 | 0 |
33
+ | 8 | 9 | 5 | 0 | 8 | 0 |
34
+ | 16 | 8 | 5 | 0 | 8 | 0 |
35
+
36
+ The last two columns are new and are what the review's M8 was about: the descent ran fourteen
37
+ wavefronts at its deepest against a budget of 64, and stopped with nothing still queued. A non-zero
38
+ `queue remaining` is the one reading here that means a **hole** rather than a coarser surface.
39
+
40
+ The cut is monotone in τ and it is a *fraction* of the asset at every setting, which is design §1's
41
+ whole claim: rendering cost is a function of the threshold and the resolution, not of the source
42
+ triangle count. Residency settles at 9 of 13 pages and 230 KB — the four it never fetches are the
43
+ ones the cut never wanted.
44
+
45
+ Two readings are worth watching for what they say about the loop rather than the picture:
46
+
47
+ - **`clamped` goes to zero.** The first frames draw a coarse, watertight surface because the pages
48
+ holding the refinement have not arrived. That is not a fallback — it is the correct surface over
49
+ exactly that region — and the count falling to zero is the streaming finishing.
50
+ - **`feedback skipped` is about half the frames.** The readback cap is two in flight, and a frame
51
+ that finds it saturated drops its feedback entirely. That is the virtual-texture contract, it
52
+ costs streaming latency and nothing on screen, and a loop that insisted on a reading every frame
53
+ would stall the frame it was reading.
54
+
55
+ ## Driving it
56
+
57
+ `__state()` is the whole surface a headless session needs — frames, the cut's counters, and both
58
+ residency tiers. `__page.runtime.tau` is the threshold. The panel shows nothing `__state()` does
59
+ not.
60
+
61
+ ```
62
+ npm run dev --workspace @woosh/meep-engine
63
+ # then open /src/shade/playground/vgeo_runtime/index.html
64
+ ```
65
+
66
+ **This page is the only thing that exercises the engine-integration path**, and that is not a
67
+ rhetorical claim: 18,569 passing specs did not notice it failing to boot at all, because
68
+ `scene.add(make_sunlight())` had outlived `Scene.add` and the page threw before defining
69
+ `__state`. Treat a green suite without a drive as unverified.
70
+
71
+ ### The headless recipe, and the two things that cost an hour
72
+
73
+ Start the dev server, then launch Chrome with a debugging port and connect over CDP:
74
+
75
+ ```
76
+ node node_modules/vite/bin/vite.js --port 5199 --strictPort # from packages/meep-engine
77
+ chrome --headless=new --enable-unsafe-webgpu --remote-debugging-port=9333 \
78
+ --user-data-dir=<a fresh one> \
79
+ http://localhost:5199/src/shade/playground/vgeo_runtime/index.html
80
+ ```
81
+
82
+ - **`--enable-unsafe-webgpu` and nothing else.** Adding `--enable-features=Vulkan`,
83
+ `--use-angle=vulkan` or `--disable-gpu-sandbox` — all of which appear in the recipes people write
84
+ down for headless WebGPU — makes `requestAdapter()` return nothing on this machine, and the page
85
+ reports it as "the browser supports WebGPU but would not provide a GPU to run on". The plain flag
86
+ gives a real nvidia/lovelace adapter.
87
+ - **Pick the CDP target by URL.** `/json/list` returns extension background pages and
88
+ `chrome://omnibox-popup` targets as well, and the first entry is routinely not the page. Attaching
89
+ to one of those and asking it for `navigator.gpu` answers `undefined`, which reads exactly like a
90
+ browser without WebGPU.
91
+
92
+ Open the page as Chrome's startup URL rather than with `Page.navigate` — the `load` event is not a
93
+ reliable signal here, so poll for `__state` itself. Then set `__page.runtime.tau` and read
94
+ `__state()` back.
@@ -0,0 +1,62 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>meep — virtual geometry runtime</title>
6
+
7
+ <link rel="icon" href="data:,">
8
+
9
+ <style>
10
+ :root { color-scheme: dark; }
11
+
12
+ html, body { height: 100%; margin: 0; overflow: hidden; background: #070b10; }
13
+
14
+ #panel {
15
+ position: absolute; top: 0; right: 0; width: 320px; max-height: 100vh; overflow-y: auto;
16
+ z-index: 10; padding: 12px 14px; box-sizing: border-box;
17
+ font: 12px/1.45 ui-monospace, "Cascadia Mono", Consolas, monospace;
18
+ color: #dfe6ee; background: rgba(12, 16, 22, 0.88);
19
+ border-left: 1px solid #2b3947;
20
+ }
21
+
22
+ #panel h1 { margin: 0 0 8px; font-size: 13px; letter-spacing: 0.06em; color: #7fd2ff; }
23
+
24
+ #panel h2 {
25
+ margin: 14px 0 6px; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
26
+ color: #6b7c8d; border-bottom: 1px solid #24313d; padding-bottom: 3px;
27
+ }
28
+
29
+ #panel .row { display: flex; justify-content: space-between; gap: 8px; }
30
+ #panel .row span:last-child { color: #f2f6fa; text-align: right; }
31
+ #panel .muted { color: #6b7c8d; }
32
+ #panel .bad { color: #ff8a7a; }
33
+ #panel .good { color: #8fe388; }
34
+ #panel input[type=range] { width: 100%; }
35
+ #panel label { display: block; margin: 6px 0 2px; }
36
+
37
+ #status { white-space: pre-wrap; }
38
+ #status.error { color: #ff8a7a; }
39
+ </style>
40
+ </head>
41
+ <body tabindex="0">
42
+
43
+ <div id="panel">
44
+ <h1>virtual geometry runtime</h1>
45
+ <div id="status" class="muted">starting…</div>
46
+
47
+ <label>threshold τ <span id="tau-value">1.0</span> px</label>
48
+ <input id="tau" type="range" min="0.25" max="16" step="0.25" value="1">
49
+
50
+ <h2>cut</h2>
51
+ <div id="cut"></div>
52
+
53
+ <h2>residency</h2>
54
+ <div id="residency"></div>
55
+ </div>
56
+
57
+ <canvas id="view" width="960" height="600"></canvas>
58
+
59
+ <script type="module" src="./main.js"></script>
60
+
61
+ </body>
62
+ </html>
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/vgeo_runtime/main.js"],"names":[],"mappings":""}
@@ -0,0 +1,399 @@
1
+ import { Color } from "../../../core/color/Color.js";
2
+ import Vector3 from "../../../core/geom/Vector3.js";
3
+ import { DEG_TO_RAD } from "../../../core/math/DEG_TO_RAD.js";
4
+ import { EntityComponentDataset } from "../../../engine/ecs/EntityComponentDataset.js";
5
+ import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
6
+ import { OrbitalCameraController } from "../../renderer/camera/OrbitalCameraController.js";
7
+ import { PerspectiveCamera } from "../../renderer/camera/PerspectiveCamera.js";
8
+ import { FramePhase } from "../../renderer/extension/FramePhase.js";
9
+ import { RenderExtension } from "../../renderer/extension/RenderExtension.js";
10
+ import { VGEO_CUT_STAT } from "../../renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js";
11
+ import { VGeoFeedbackLoop } from "../../renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js";
12
+ import { VirtualGeometry } from "../../renderer/geometry/virtual/runtime/VirtualGeometry.js";
13
+ import {
14
+ VGeoContainerReader
15
+ } from "../../renderer/geometry/virtual/format/read/VGeoContainerReader.js";
16
+ import {
17
+ VGeoReadOptions
18
+ } from "../../renderer/geometry/virtual/format/read/VGeoReadOptions.js";
19
+ import {
20
+ VGeoResidencyManager
21
+ } from "../../renderer/geometry/virtual/residency/VGeoResidencyManager.js";
22
+ import { make_sunlight } from "../../renderer/light/make_sunlight.js";
23
+ import { place_light } from "../../renderer/light/place_light.js";
24
+ import { StandardShadeMaterial } from "../../renderer/material/StandardShadeMaterial.js";
25
+ import { Renderer } from "../../renderer/Renderer.js";
26
+ import { place_primitive } from "../../renderer/scene/rows/place_primitive.js";
27
+ import { Scene } from "../../renderer/scene/Scene.js";
28
+ import { vgeo_sample_source } from "../vgeo_viewer/sample_asset.js";
29
+
30
+ /**
31
+ * A `.vgeo` container drawn **through the meshlet pipeline**, by a cut selected on the GPU.
32
+ *
33
+ * This is the other half of what `playground/vgeo_viewer/` proves, and the two are worth keeping
34
+ * apart. The viewer draws a CPU cut through Shade's direct geometry path: it proves the DAG, the
35
+ * format and the clamp, and by construction it proves nothing about the engine. This page draws
36
+ * nothing itself. It puts an ordinary mesh row in an ordinary `Scene` with an ordinary material,
37
+ * and every triangle on screen arrives because the compute cut appended `MESHLET_DEFINITION_STRUCT`
38
+ * records into the same collection a static mesh's meshlets go into — through the HZB meshlet
39
+ * filter, the material bucket, the indirect draw and the G-buffer, none of which know that virtual
40
+ * geometry exists.
41
+ *
42
+ * So the interesting readings here are the ones about the engine rather than about the DAG:
43
+ *
44
+ * - **drawn triangles track τ and the resolution, not the source.** Design §1's whole claim. Move
45
+ * the slider and watch the cut, not the asset.
46
+ * - **clamped falls to zero as pages arrive.** The cut starts against a container holding only its
47
+ * root page, so the first frames are a coarse but watertight surface, and the wants the cut emits
48
+ * are what fetch the rest.
49
+ * - **nothing is drawn twice.** `drawn` against the triangle count the rasterizer reports.
50
+ *
51
+ * `__state()` is what a headless session asserts on; everything the panel shows comes from it.
52
+ *
53
+ * @author Alex Goldring
54
+ * @copyright Company Named Limited (c) 2026
55
+ */
56
+
57
+ const element = id => document.getElementById(id);
58
+
59
+ /**
60
+ * Opens the VG frame before anything records a rasterization pass, because the seam inside those
61
+ * passes writes into the feedback buffer this creates.
62
+ */
63
+ class VGeoFrameStart extends RenderExtension {
64
+ name = "vgeo/frame start";
65
+
66
+ phase = FramePhase.FrameStart;
67
+
68
+ /**
69
+ * @param {VGeoPlayground} page
70
+ */
71
+ constructor(page) {
72
+ super();
73
+
74
+ this.page = page;
75
+ }
76
+
77
+ record(frame) {
78
+ this.page.begin(frame);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Schedules the readback and closes the frame, after everything that could have cut has cut.
84
+ */
85
+ class VGeoFrameEnd extends RenderExtension {
86
+ name = "vgeo/frame end";
87
+
88
+ phase = FramePhase.BeforePresent;
89
+
90
+ /**
91
+ * @param {VGeoPlayground} page
92
+ */
93
+ constructor(page) {
94
+ super();
95
+
96
+ this.page = page;
97
+ }
98
+
99
+ record(frame) {
100
+ this.page.finish(frame);
101
+ }
102
+ }
103
+
104
+ class VGeoPlayground {
105
+ /**
106
+ * @type {VGeoContainerReader}
107
+ */
108
+ reader;
109
+
110
+ /**
111
+ * @type {GPUVirtualGeometryRuntime}
112
+ */
113
+ runtime;
114
+
115
+ /**
116
+ * @type {VGeoFeedbackLoop}
117
+ */
118
+ feedback;
119
+
120
+ /**
121
+ * @type {VGeoResidencyManager}
122
+ */
123
+ residency;
124
+
125
+ /**
126
+ * @type {number}
127
+ */
128
+ frames = 0;
129
+
130
+ /**
131
+ * @type {number}
132
+ */
133
+ canvas_height = 600;
134
+
135
+ /**
136
+ * @type {number}
137
+ */
138
+ fov_y = 50 * DEG_TO_RAD;
139
+
140
+ /**
141
+ * @param {FrameContext} frame
142
+ */
143
+ begin(frame) {
144
+ this.runtime.begin_frame(frame.graph, {
145
+ screen_height: this.canvas_height,
146
+ fov_y: this.fov_y,
147
+ });
148
+ }
149
+
150
+ /**
151
+ * @param {FrameContext} frame
152
+ */
153
+ finish(frame) {
154
+ // the RAM tier's clock moves inside this: a host that drives the loop gets a bounded
155
+ // second tier without having to know it had one to wind
156
+ this.feedback.read(frame.graph);
157
+
158
+ this.runtime.end_frame();
159
+
160
+ this.frames++;
161
+ }
162
+
163
+ /**
164
+ * Everything a headless session needs, and everything the panel shows.
165
+ *
166
+ * @returns {object}
167
+ */
168
+ state() {
169
+ const stats = this.feedback.stats;
170
+ const pool = this.runtime.pool;
171
+
172
+ return {
173
+ frames: this.frames,
174
+ tau: this.runtime.tau,
175
+ feedback_reads: this.feedback.read_count,
176
+ feedback_skipped: this.feedback.skipped_frames,
177
+ cut: {
178
+ drawn: stats[VGEO_CUT_STAT.DRAWN],
179
+ clamped: stats[VGEO_CUT_STAT.CLAMPED],
180
+ clamped_on_activation: stats[VGEO_CUT_STAT.CLAMPED_ON_ACTIVATION],
181
+ pages: stats[VGEO_CUT_STAT.PAGES],
182
+ items: stats[VGEO_CUT_STAT.ITEMS],
183
+ clusters_tested: stats[VGEO_CUT_STAT.CLUSTERS_TESTED],
184
+ culled_frustum: stats[VGEO_CUT_STAT.CULLED_FRUSTUM],
185
+ culled_lod: stats[VGEO_CUT_STAT.CULLED_LOD],
186
+ meshlets_dropped: stats[VGEO_CUT_STAT.MESHLETS_DROPPED],
187
+ wants_dropped: stats[VGEO_CUT_STAT.WANTS_DROPPED],
188
+ queue_dropped: stats[VGEO_CUT_STAT.QUEUE_DROPPED],
189
+ instances_dropped: stats[VGEO_CUT_STAT.INSTANCES_DROPPED],
190
+ wavefronts: stats[VGEO_CUT_STAT.WAVEFRONTS],
191
+ queue_remaining: stats[VGEO_CUT_STAT.QUEUE_REMAINING],
192
+ },
193
+ wants: this.feedback.last_want_count,
194
+ touches: this.feedback.last_touch_count,
195
+ vram: {
196
+ pages: pool.resident_page_count,
197
+ bytes: pool.resident_bytes,
198
+ evicted: pool.evicted_page_count,
199
+ refused: pool.refused_install_count,
200
+ },
201
+ ram: {
202
+ pages: this.reader.resident_page_count,
203
+ bytes: this.reader.resident_bytes,
204
+ total_pages: this.reader.header.total_pages,
205
+ },
206
+ };
207
+ }
208
+ }
209
+
210
+ async function start() {
211
+ const canvas = element('view');
212
+
213
+ const status = text => {
214
+ element('status').textContent = text;
215
+ };
216
+
217
+ const renderer = new Renderer();
218
+
219
+ await renderer.initialize({ context: canvas.getContext('webgpu'), pixelRatio: 1 });
220
+
221
+ renderer.feature_taa_enabled = false;
222
+ renderer.feature_ssao_enabled = false;
223
+ renderer.feature_bloom_enabled = false;
224
+
225
+ renderer.resize(canvas.width, canvas.height);
226
+
227
+ status('building a container in the page…');
228
+
229
+ /*
230
+ One number for the asset and for the tier that holds it. A page size is a bound the container
231
+ states (FORMAT §11.14) and the pool holds pages at exactly one, so a mismatch here is a refusal
232
+ at `register` rather than something that limps.
233
+ */
234
+ const page_size = 64 * 1024;
235
+
236
+ const { source, build_ms } = vgeo_sample_source(128, 48, page_size);
237
+
238
+ /*
239
+ Frame verification on, because this reader is a runtime's rather than a tool's — format §10
240
+ leaves it off by default precisely because a tool reading a file it just built is not
241
+ defending against a network, and a runtime is.
242
+ */
243
+ const options = new VGeoReadOptions();
244
+
245
+ options.verify_frames = true;
246
+
247
+ const reader = await VGeoContainerReader.open(source, options);
248
+
249
+ const page = new VGeoPlayground();
250
+
251
+ page.reader = reader;
252
+ page.canvas_height = canvas.height;
253
+
254
+ page.residency = new VGeoResidencyManager();
255
+ page.residency.register(reader);
256
+
257
+ const scene = new Scene();
258
+
259
+ // the sun stands at an entity, and so does the torus, so the scene names a dataset
260
+ scene.dataset = new EntityComponentDataset();
261
+
262
+ // a light stands at an entity of the dataset now, like everything else the scene holds
263
+ place_light(scene, make_sunlight());
264
+
265
+ const camera = new PerspectiveCamera();
266
+
267
+ camera.near = 0.02;
268
+ camera.far = 200;
269
+ camera.fov = page.fov_y;
270
+ camera.aspect = canvas.width / canvas.height;
271
+
272
+ const controller = new OrbitalCameraController(camera, document.body);
273
+
274
+ controller.look(new Vector3(0, 1.6, 3.6), new Vector3(0, 0, 0));
275
+
276
+ // one frame to let the renderer build its scene context, which is what owns the geometry manager
277
+ renderer.render(camera, scene, 1 / 60);
278
+
279
+ const scene_context = renderer.scenes.obtain(scene);
280
+
281
+ const runtime = scene_context.enable_virtual_geometry({ page_size });
282
+
283
+ page.runtime = runtime;
284
+
285
+ /*
286
+ Only the root page is resident. Everything else arrives because the cut asked for it, which is
287
+ the loop this page exists to show — and it means the first frames draw a coarse, watertight
288
+ surface rather than nothing at all.
289
+ */
290
+ const geometry_row = runtime.pool.register(reader);
291
+
292
+ const geometry = new VirtualGeometry(reader);
293
+
294
+ geometry.vg_row = geometry_row;
295
+
296
+ const material = new StandardShadeMaterial();
297
+
298
+ material.diffuse_color.copy(new Color(0.72, 0.74, 0.78));
299
+ material.roughness_factor = 0.55;
300
+ material.metallic_factor = 0;
301
+
302
+ place_primitive(
303
+ scene_context, geometry, material, new Transform64(), { name: 'virtual torus' }
304
+ );
305
+
306
+ page.feedback = new VGeoFeedbackLoop({ runtime, residency: page.residency });
307
+
308
+ /*
309
+ The loop's only teardown caller anywhere, and worth having for the same reason M12's clock was:
310
+ `abort()` existed and nothing pulled it, so the one thing the `AbortSignal` was added for was
311
+ never exercised outside a spec. Nothing in the engine constructs a feedback loop yet — a scene
312
+ context gives you a runtime and a pool, and the host wires the loop — so this page is the whole
313
+ population of hosts, and it is what a real one should do on the way out.
314
+ */
315
+ globalThis.addEventListener('pagehide', () => page.feedback.destroy());
316
+
317
+ renderer.add_extension(new VGeoFrameStart(page));
318
+ renderer.add_extension(new VGeoFrameEnd(page));
319
+
320
+ element('tau').addEventListener('input', event => {
321
+ runtime.tau = Number(event.target.value);
322
+
323
+ element('tau-value').textContent = runtime.tau.toFixed(2);
324
+ });
325
+
326
+ globalThis.__state = () => page.state();
327
+ globalThis.__page = page;
328
+
329
+ status(`container built in ${build_ms.toFixed(0)} ms · ${reader.header.total_pages} pages`);
330
+
331
+ let stopped = false;
332
+ let last_time;
333
+
334
+ function paint() {
335
+ const state = page.state();
336
+
337
+ element('cut').innerHTML = [
338
+ ['drawn clusters', state.cut.drawn],
339
+ ['clamped', state.cut.clamped],
340
+ ['pages visited', state.cut.pages],
341
+ ['clusters tested', state.cut.clusters_tested],
342
+ ['subtrees culled', state.cut.culled_frustum + state.cut.culled_lod],
343
+ ['wants', state.wants],
344
+ ].map(([name, value]) => `<div class="row"><span>${name}</span><span>${value}</span></div>`)
345
+ .join('');
346
+
347
+ const dropped = state.cut.meshlets_dropped + state.cut.queue_dropped
348
+ + state.cut.instances_dropped;
349
+
350
+ element('residency').innerHTML = [
351
+ ['VRAM pages', `${state.vram.pages}`],
352
+ ['VRAM bytes', `${(state.vram.bytes / 1024).toFixed(0)} KB`],
353
+ ['RAM pages', `${state.ram.pages} / ${state.ram.total_pages}`],
354
+ ['evicted', state.vram.evicted],
355
+ ['dropped', `<span class="${dropped > 0 ? 'bad' : 'good'}">${dropped}</span>`],
356
+ ].map(([name, value]) => `<div class="row"><span>${name}</span><span>${value}</span></div>`)
357
+ .join('');
358
+ }
359
+
360
+ function tick(time) {
361
+ if (stopped) {
362
+ return;
363
+ }
364
+
365
+ const dt = last_time === undefined ? 1 / 60 : Math.min((time - last_time) / 1000, 0.05);
366
+
367
+ last_time = time;
368
+
369
+ try {
370
+ controller.update(dt);
371
+
372
+ renderer.render(camera, scene, dt);
373
+ } catch (error) {
374
+ stopped = true;
375
+
376
+ status(error.message ?? String(error));
377
+ element('status').classList.add('error');
378
+
379
+ console.error(error);
380
+
381
+ return;
382
+ }
383
+
384
+ paint();
385
+
386
+ requestAnimationFrame(tick);
387
+ }
388
+
389
+ requestAnimationFrame(tick);
390
+ }
391
+
392
+ start().catch(error => {
393
+ element('status').textContent = error.message ?? String(error);
394
+ element('status').classList.add('error');
395
+
396
+ globalThis.__state = () => ({ error: error.message ?? String(error) });
397
+
398
+ console.error(error);
399
+ });
@@ -99,7 +99,7 @@ function torus(major, minor) {
99
99
  * @param {number} [page_size] target decoded bytes per page
100
100
  * @returns {{source: VGeoByteSource, build_ms: number}}
101
101
  */
102
- export function vgeo_sample_source(major = 128, minor = 48, page_size = 8 * 1024) {
102
+ export function vgeo_sample_source(major = 128, minor = 48, page_size = 16 * 1024) {
103
103
  const options = new VGeoBuildOptions();
104
104
 
105
105
  options.nominal_page_size = page_size;
@@ -1,3 +1,17 @@
1
+ /**
2
+ * ref: Gribb-Hartmann
3
+ * Updates frustum planes from a View-Projection matrix.
4
+ * Geared for Reverse-Z (WebGPU/DirectX range [0,1]).
5
+ *
6
+ * Exported because it is the engine's **one** answer to this question and somebody else asks it:
7
+ * the virtual-geometry cut extracts the same six rows from an object-space view-projection, in a
8
+ * shader, and shipped with the near plane's sign wrong. A spec that holds the two against each
9
+ * other is worth more than a second derivation with a comment saying it matches.
10
+ *
11
+ * @param {Float32Array} planes
12
+ * @param {Float32Array} vp ViewProjection matrix
13
+ */
14
+ export function construct_frustum_planes(planes: Float32Array, vp: Float32Array): void;
1
15
  export class Camera {
2
16
  transform: Transform64;
3
17
  view_matrix: Float32Array;
@@ -1 +1 @@
1
- {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/camera/Camera.js"],"names":[],"mappings":"AAiFA;IAMI,uBAA8B;IAE9B,0BAA4B;IAC5B,gCAAkC;IAClC,qCAAuC;IAEvC;;;OAGG;IACH,SAFU,YAAY,CAES;IAoB/B,oBAEC;IAED,mBAEC;IAED,mBAEC;IAED,kBAEC;IAED,sBAKC;IAED,qBAEC;IAED,0BAEC;IAED,6BAEC;IAED;;;OAGG;IACH,YAFW,MAAM,QAchB;IAED,aAQC;IAED,iBAEC;IAED,eAMC;IAED;;;OAGG;IACH,cAFW,MAAM,WAQhB;IAED,wBAKC;IAED,0BAEC;IAED,2BAuDC;IAED,uBAIC;IAED,eAQC;;CACJ;4BAvR2B,8CAA8C"}
1
+ {"version":3,"file":"Camera.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/camera/Camera.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;GAYG;AACH,iDAHW,YAAY,MACZ,YAAY,QA8DtB;AAED;IAMI,uBAA8B;IAE9B,0BAA4B;IAC5B,gCAAkC;IAClC,qCAAuC;IAEvC;;;OAGG;IACH,SAFU,YAAY,CAES;IAoB/B,oBAEC;IAED,mBAEC;IAED,mBAEC;IAED,kBAEC;IAED,sBAKC;IAED,qBAEC;IAED,0BAEC;IAED,6BAEC;IAED;;;OAGG;IACH,YAFW,MAAM,QAchB;IAED,aAQC;IAED,iBAEC;IAED,eAMC;IAED;;;OAGG;IACH,cAFW,MAAM,WAQhB;IAED,wBAKC;IAED,0BAEC;IAED,2BAuDC;IAED,uBAIC;IAED,eAQC;;CACJ;4BA7R2B,8CAA8C"}
@@ -14,10 +14,16 @@ let id_counter = 0;
14
14
  * ref: Gribb-Hartmann
15
15
  * Updates frustum planes from a View-Projection matrix.
16
16
  * Geared for Reverse-Z (WebGPU/DirectX range [0,1]).
17
+ *
18
+ * Exported because it is the engine's **one** answer to this question and somebody else asks it:
19
+ * the virtual-geometry cut extracts the same six rows from an object-space view-projection, in a
20
+ * shader, and shipped with the near plane's sign wrong. A spec that holds the two against each
21
+ * other is worth more than a second derivation with a comment saying it matches.
22
+ *
17
23
  * @param {Float32Array} planes
18
24
  * @param {Float32Array} vp ViewProjection matrix
19
25
  */
20
- function construct_frustum_planes(planes, vp) {
26
+ export function construct_frustum_planes(planes, vp) {
21
27
  // Left Plane (w + x)
22
28
  // Row 3 + Row 0
23
29
  plane3_normalize(
@@ -1 +1 @@
1
- {"version":3,"file":"GEOMETRY_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js"],"names":[],"mappings":"AAKA,oDAgB8B;6BAnBD,gCAAgC"}
1
+ {"version":3,"file":"GEOMETRY_METADATA_STRUCT.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js"],"names":[],"mappings":"AAKA,oDA+B8B;6BAlCD,gCAAgC"}
@@ -18,5 +18,20 @@ export const GEOMETRY_METADATA_STRUCT = WebGPUStruct.from({
18
18
  meshlets_count: u32,
19
19
 
20
20
  bounding_sphere: vec4f,
21
- bounding_box: WebGPUArray.from(f32, 6)
21
+ bounding_box: WebGPUArray.from(f32, 6),
22
+
23
+ /**
24
+ * Row in the virtual-geometry table, or {@link VGEO_GEOMETRY_ROW_NONE}.
25
+ *
26
+ * A VG geometry has no static meshlets — `meshlets_count` is zero, so the mesh-to-meshlet
27
+ * expansion contributes nothing for it by construction — and everything it draws comes from a
28
+ * cut selected that frame. This field is how a pass handed a list of visible instances tells
29
+ * the two apart, and it is the only change virtual geometry asks of the engine's record
30
+ * formats: the draw records, the meshlet metadata, the material buckets and the indirect draws
31
+ * are all unchanged.
32
+ *
33
+ * Appended rather than inserted. Every other consumer reads this struct by field name or
34
+ * computes an offset from it, so a field at the end costs them nothing.
35
+ */
36
+ vg_row: u32,
22
37
  }, "GeometryMetadata").pack();