@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.
- package/package.json +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +59 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +285 -0
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
- package/src/engine/graphics3/PickingSystem.d.ts +3 -3
- package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
- package/src/engine/graphics3/PickingSystem.js +52 -55
- package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
- package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
- package/src/engine/graphics3/shader_picking_gather.js +120 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +1632 -0
- package/src/engine/physics/cloth/PLAN.md +738 -95
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
- package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
- package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +101 -29
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +110 -31
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +71 -81
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +135 -856
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +323 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.js +1248 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +192 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +578 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +85 -3
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +366 -271
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +95 -12
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +170 -27
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
- package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
- package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
- package/src/engine/physics/cloth/playground/README.md +73 -2
- package/src/engine/physics/cloth/playground/collide_main.js +1 -1
- package/src/engine/physics/cloth/playground/wind.html +166 -0
- package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
- package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/wind_build.js +141 -0
- package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
- package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/wind_main.js +681 -0
- package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +273 -12
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +45 -2
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +46 -2
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +102 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.js +114 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +87 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.js +185 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.js +213 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +106 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +297 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
- package/src/shade/device/mock/texture_copy.js +28 -0
- package/src/shade/playground/vgeo_runtime/README.md +94 -0
- package/src/shade/playground/vgeo_runtime/index.html +62 -0
- package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
- package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
- package/src/shade/playground/vgeo_runtime/main.js +399 -0
- package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
- package/src/shade/renderer/camera/Camera.d.ts +14 -0
- package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
- package/src/shade/renderer/camera/Camera.js +7 -1
- package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
- package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
- package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
- package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
- package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
- package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
- package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
- package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
- package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
- package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
- package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
- package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
- package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
- package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
- package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
- package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
- package/src/shade/renderer/scene/Mesh.d.ts +0 -55
- package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
- package/src/shade/renderer/scene/Node3D.d.ts +0 -159
- package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
- package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
- package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
- package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
- package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
- package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
- package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
- package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
- package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { atomic_u32, u32 } from "../../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../../../../shader/type/WebGPUArray.js";
|
|
3
|
+
import { CAMERA_UNIFORM_STRUCT } from "../../../../camera/CAMERA_UNIFORM_STRUCT.js";
|
|
4
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
5
|
+
import { COLLECTION_U32_STRUCT_READ } from "../../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
|
|
6
|
+
import { COLLECTION_U32_STRUCT_WRITE } from "../../../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
|
|
7
|
+
import { ComputeShader } from "../../../../shader/ComputeShader.js";
|
|
8
|
+
import { GEOMETRY_METADATA_STRUCT } from "../../../GEOMETRY_METADATA_STRUCT.js";
|
|
9
|
+
import { chunk_mat3_singular_values } from "../../../../shader/chunk/geometry/mat3/chunk_mat3_singular_values.js";
|
|
10
|
+
import { chunk_mat4_inverse } from "../../../../shader/chunk/geometry/mat4/chunk_mat4_inverse.js";
|
|
11
|
+
import { chunk_scene_database_access } from "../../../../scene/chunk_scene_database_access.js";
|
|
12
|
+
import { ShaderResourceSetDescriptor } from "../../../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
13
|
+
import { VGEO_CUT_STAT } from "../layout/VGEO_CUT_STAT.js";
|
|
14
|
+
import { VGEO_FEEDBACK_OFFSET } from "../layout/VGEO_FEEDBACK_OFFSET.js";
|
|
15
|
+
import { VGEO_GEOMETRY_ROW_NONE } from "../layout/VGEO_GEOMETRY_ROW_NONE.js";
|
|
16
|
+
import { VGEO_GEOMETRY_ROW_OFFSET } from "../layout/VGEO_GEOMETRY_ROW_OFFSET.js";
|
|
17
|
+
import { VGEO_GEOMETRY_ROW_WORDS } from "../layout/VGEO_GEOMETRY_ROW_WORDS.js";
|
|
18
|
+
import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
|
|
19
|
+
import { VGEO_INSTANCE_WORDS } from "../layout/VGEO_INSTANCE_WORDS.js";
|
|
20
|
+
import { VGEO_CUT_PARAMS_STRUCT } from "./VGEO_CUT_PARAMS_STRUCT.js";
|
|
21
|
+
import { VGEO_CUT_WORKGROUP_SIZE } from "./VGEO_CUT_WORKGROUP_SIZE.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Pick the virtual-geometry instances out of a list of visible meshes, and put each one into object
|
|
25
|
+
* space once.
|
|
26
|
+
*
|
|
27
|
+
* This is `MICRON_COMPARISON_2026_08_20.md` §2.7 as design §3.1 adopted it, and it is the only
|
|
28
|
+
* place the transform is touched: multiply the camera's view-projection by the instance transform,
|
|
29
|
+
* take the frustum out of the result, invert the transform once for the eye, and every cull and
|
|
30
|
+
* error test downstream runs against untransformed cluster bounds. One matrix per instance instead
|
|
31
|
+
* of a transform per cluster — with thousands of instances sharing one geometry, that difference is
|
|
32
|
+
* the entire cost.
|
|
33
|
+
*
|
|
34
|
+
* It also emits each instance's claim width, which the prefix scan turns into the base the seed
|
|
35
|
+
* pass writes back. The width is the geometry's **ordinal capacity** rather than its resident page
|
|
36
|
+
* count, because ordinals come from a free list and can be sparse; a bitmask indexed by a sparse
|
|
37
|
+
* ordinal has to be as wide as the highest one handed out.
|
|
38
|
+
*
|
|
39
|
+
* @author Alex Goldring
|
|
40
|
+
* @copyright Company Named Limited (c) 2026
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
44
|
+
|
|
45
|
+
resources.createGroup()
|
|
46
|
+
.addUniform("params", VGEO_CUT_PARAMS_STRUCT)
|
|
47
|
+
.addUniform("camera", CAMERA_UNIFORM_STRUCT)
|
|
48
|
+
.addStorageBuffer("scene_database", WebGPUArray.from(u32), false)
|
|
49
|
+
.addStorageBuffer("geometries", WebGPUArray.from(GEOMETRY_METADATA_STRUCT), false)
|
|
50
|
+
.addStorageBuffer("vg_geometries", WebGPUArray.from(u32), false)
|
|
51
|
+
;
|
|
52
|
+
|
|
53
|
+
resources.createGroup()
|
|
54
|
+
.addStorageBuffer("input_meshes", COLLECTION_U32_STRUCT_READ, false)
|
|
55
|
+
.addStorageBuffer("instances", WebGPUArray.from(u32), true)
|
|
56
|
+
.addStorageBuffer("claim_widths", COLLECTION_U32_STRUCT_WRITE, true)
|
|
57
|
+
// the frame's counters, so an instance this pass refuses is counted where every other drop is
|
|
58
|
+
.addStorageBuffer("feedback", WebGPUArray.from(atomic_u32), true)
|
|
59
|
+
;
|
|
60
|
+
|
|
61
|
+
const body = CodeChunk.from(
|
|
62
|
+
//language=WGSL
|
|
63
|
+
`
|
|
64
|
+
const VG_GEOMETRY_ROW_NONE = ${VGEO_GEOMETRY_ROW_NONE}u;
|
|
65
|
+
const VG_INSTANCE_WORDS = ${VGEO_INSTANCE_WORDS}u;
|
|
66
|
+
const VG_GEOMETRY_ROW_WORDS = ${VGEO_GEOMETRY_ROW_WORDS}u;
|
|
67
|
+
|
|
68
|
+
fn vg_store(base: u32, field: u32, value: f32) {
|
|
69
|
+
instances[base + field] = bitcast<u32>(value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* One frustum plane out of a row combination of the object-space view-projection, normalized so a
|
|
74
|
+
* sphere test is a plain signed distance.
|
|
75
|
+
*
|
|
76
|
+
* Gribb-Hartmann, and the far plane is simply not extracted: the projection is infinite reverse-Z,
|
|
77
|
+
* so its row is degenerate and normalizing it produces nothing a test can use. Ordering near last
|
|
78
|
+
* is what makes the traversal's "test the first five" true by construction.
|
|
79
|
+
*
|
|
80
|
+
* **The near plane is w − z, and it was w + z here.** Under reverse-Z the near plane is the one
|
|
81
|
+
* clip space bounds by z <= w; w + z is the row an *infinite* projection makes degenerate, which is
|
|
82
|
+
* exactly the row this function then normalized into a plane the test could not use.
|
|
83
|
+
* Camera.construct_frustum_planes has had the sign right all along and is worth comparing against
|
|
84
|
+
* rather than re-deriving.
|
|
85
|
+
*/
|
|
86
|
+
fn vg_store_plane(base: u32, plane: u32, row_w: vec4<f32>, row: vec4<f32>, sign: f32) {
|
|
87
|
+
let raw = row_w + row * sign;
|
|
88
|
+
|
|
89
|
+
let length_xyz = length(raw.xyz);
|
|
90
|
+
|
|
91
|
+
let normalized = select(raw, raw / length_xyz, length_xyz > 0.0);
|
|
92
|
+
|
|
93
|
+
let word = base + ${VGEO_INSTANCE_OFFSET.FRUSTUM}u + plane * 4u;
|
|
94
|
+
|
|
95
|
+
instances[word] = bitcast<u32>(normalized.x);
|
|
96
|
+
instances[word + 1u] = bitcast<u32>(normalized.y);
|
|
97
|
+
instances[word + 2u] = bitcast<u32>(normalized.z);
|
|
98
|
+
instances[word + 3u] = bitcast<u32>(normalized.w);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@compute @workgroup_size(${VGEO_CUT_WORKGROUP_SIZE})
|
|
102
|
+
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
103
|
+
let input_index = global_id.x;
|
|
104
|
+
|
|
105
|
+
if (input_index >= input_meshes.count) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let mesh_index = input_meshes.elements[input_index];
|
|
110
|
+
|
|
111
|
+
let mesh = scene_read_mesh(&scene_database, mesh_index);
|
|
112
|
+
|
|
113
|
+
let geometry_row = geometries[mesh.geometry].vg_row;
|
|
114
|
+
|
|
115
|
+
if (geometry_row == VG_GEOMETRY_ROW_NONE) {
|
|
116
|
+
// an ordinary mesh; the static expansion beside this pass is what draws it
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
let node = scene_read_node(&scene_database, mesh.node);
|
|
121
|
+
|
|
122
|
+
let linear = mat3x3<f32>(
|
|
123
|
+
node.global[0].xyz, node.global[1].xyz, node.global[2].xyz
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
Error and distance are both object-space, so a **uniform** scale cancels out of r_e * k / d
|
|
128
|
+
exactly and needs no term at all. A non-uniform one does not, and the correction is the ratio
|
|
129
|
+
of the largest stretch this transform applies to any direction to the smallest — which is the
|
|
130
|
+
ratio of its singular values, not of its column lengths. A shear has unit columns and stretches
|
|
131
|
+
space without bound, so column lengths report 1 and under-refine, which is the direction a
|
|
132
|
+
conservative correction is not allowed to fail in.
|
|
133
|
+
*/
|
|
134
|
+
let stretch = mat3_singular_values(linear);
|
|
135
|
+
|
|
136
|
+
if (!(abs(determinant(linear)) > 0.0) || !(stretch.y > 0.0)) {
|
|
137
|
+
/*
|
|
138
|
+
A singular transform — an instance scaled to zero in some direction. mat4_inverse says so
|
|
139
|
+
by dividing by a zero determinant, and the NaN that comes back makes **every** comparison
|
|
140
|
+
in vg_project and the frustum test fail open, so one zero-scaled instance draws its whole
|
|
141
|
+
resident set. It covers no pixels, so dropping it is also the right picture.
|
|
142
|
+
|
|
143
|
+
**The determinant is the test, and sigma_min alone was not.** This guard used to be
|
|
144
|
+
!(sigma_min > 0) on its own, and the closed form's own doc offered sigma_min as a
|
|
145
|
+
degeneracy test — true in exact arithmetic, false in f32. An axis-aligned flatten makes
|
|
146
|
+
MtM exactly diagonal and takes the exact branch, which does return zero. A ROTATED one
|
|
147
|
+
takes the trigonometric branch, where sigma_min is a difference of nearly equal numbers
|
|
148
|
+
with an absolute error of about sqrt(eps_f32) * sigma_max — so it came back near 1e-4
|
|
149
|
+
rather than 0, and thirty-six of forty rotated zero-scale instances passed this line with
|
|
150
|
+
a NaN eye and a projection scale of 6.2e10 behind it (REVIEW_LEDGER M3, re-review
|
|
151
|
+
2026-09-12). The determinant does not have that problem: a flattened instance has one
|
|
152
|
+
exactly-zero column at every rotation, and every term of the expansion carries a factor
|
|
153
|
+
from it. It is also, exactly, the number mat4_inverse divides by two lines below.
|
|
154
|
+
|
|
155
|
+
sigma_min is kept beside it because it is not redundant: a matrix that is merely very
|
|
156
|
+
close to singular has a non-zero determinant and can still report sigma_min as zero, and
|
|
157
|
+
the ratio below would then be an infinity rather than a correction.
|
|
158
|
+
|
|
159
|
+
Both written as !(x > 0) rather than x <= 0 so that a NaN — which compares false against
|
|
160
|
+
everything — is caught rather than passed through.
|
|
161
|
+
*/
|
|
162
|
+
atomicAdd(
|
|
163
|
+
&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.INSTANCES_DROPPED}u], 1u
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let slot = atomicAdd(&claim_widths.count, 1u);
|
|
170
|
+
|
|
171
|
+
if (slot >= params.instance_capacity) {
|
|
172
|
+
/*
|
|
173
|
+
Bounded like every other append in the cut. As the seam is wired this cannot fire — one
|
|
174
|
+
instance record per element of input_meshes, and both collections are sized from the same
|
|
175
|
+
limit — but the invariant lives a call away and the buffer is created here, so the check
|
|
176
|
+
belongs here too. Dropping the instance is the safe direction: a cut run without a claim
|
|
177
|
+
slice draws every page once per parent that reaches it.
|
|
178
|
+
*/
|
|
179
|
+
atomicAdd(
|
|
180
|
+
&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.INSTANCES_DROPPED}u], 1u
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let base = slot * VG_INSTANCE_WORDS;
|
|
187
|
+
|
|
188
|
+
let to_object = mat4_inverse(node.global);
|
|
189
|
+
|
|
190
|
+
// the camera's position in this instance's object space, out of the camera's own world transform
|
|
191
|
+
let eye = to_object * vec4<f32>(camera.transform[3].xyz, 1.0);
|
|
192
|
+
|
|
193
|
+
vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE}u, eye.x / eye.w);
|
|
194
|
+
vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE + 1}u, eye.y / eye.w);
|
|
195
|
+
vg_store(base, ${VGEO_INSTANCE_OFFSET.EYE + 2}u, eye.z / eye.w);
|
|
196
|
+
|
|
197
|
+
vg_store(
|
|
198
|
+
base, ${VGEO_INSTANCE_OFFSET.PROJECTION_K}u,
|
|
199
|
+
params.projection_k * (stretch.x / stretch.y)
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// one matrix multiply, and every plane below comes out of it
|
|
203
|
+
let object_view_projection = camera.view_projection_matrix * node.global;
|
|
204
|
+
|
|
205
|
+
// WGSL matrices are column-major, so a row of the matrix is a component across its columns
|
|
206
|
+
let row_x = vec4<f32>(
|
|
207
|
+
object_view_projection[0].x, object_view_projection[1].x,
|
|
208
|
+
object_view_projection[2].x, object_view_projection[3].x
|
|
209
|
+
);
|
|
210
|
+
let row_y = vec4<f32>(
|
|
211
|
+
object_view_projection[0].y, object_view_projection[1].y,
|
|
212
|
+
object_view_projection[2].y, object_view_projection[3].y
|
|
213
|
+
);
|
|
214
|
+
let row_z = vec4<f32>(
|
|
215
|
+
object_view_projection[0].z, object_view_projection[1].z,
|
|
216
|
+
object_view_projection[2].z, object_view_projection[3].z
|
|
217
|
+
);
|
|
218
|
+
let row_w = vec4<f32>(
|
|
219
|
+
object_view_projection[0].w, object_view_projection[1].w,
|
|
220
|
+
object_view_projection[2].w, object_view_projection[3].w
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
vg_store_plane(base, 0u, row_w, row_x, 1.0);
|
|
224
|
+
vg_store_plane(base, 1u, row_w, row_x, -1.0);
|
|
225
|
+
vg_store_plane(base, 2u, row_w, row_y, 1.0);
|
|
226
|
+
vg_store_plane(base, 3u, row_w, row_y, -1.0);
|
|
227
|
+
vg_store_plane(base, 4u, row_w, row_z, -1.0);
|
|
228
|
+
|
|
229
|
+
let geometry_base = geometry_row * VG_GEOMETRY_ROW_WORDS;
|
|
230
|
+
|
|
231
|
+
let ordinal_capacity = vg_geometries[
|
|
232
|
+
geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.ORDINAL_CAPACITY}u
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
instances[base + ${VGEO_INSTANCE_OFFSET.MESH_INDEX}u] = mesh_index;
|
|
236
|
+
instances[base + ${VGEO_INSTANCE_OFFSET.ROOT_PAGE_ROW}u] =
|
|
237
|
+
vg_geometries[geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.ROOT_PAGE_ROW}u];
|
|
238
|
+
instances[base + ${VGEO_INSTANCE_OFFSET.LOOKUP_WORD_OFFSET}u] =
|
|
239
|
+
vg_geometries[geometry_base + ${VGEO_GEOMETRY_ROW_OFFSET.LOOKUP_WORD_OFFSET}u];
|
|
240
|
+
instances[base + ${VGEO_INSTANCE_OFFSET.ORDINAL_CAPACITY}u] = ordinal_capacity;
|
|
241
|
+
instances[base + ${VGEO_INSTANCE_OFFSET.CLAIM_BASE}u] = 0u;
|
|
242
|
+
|
|
243
|
+
claim_widths.elements[slot] = ordinal_capacity;
|
|
244
|
+
}
|
|
245
|
+
`, [
|
|
246
|
+
chunk_scene_database_access,
|
|
247
|
+
chunk_mat3_singular_values,
|
|
248
|
+
chunk_mat4_inverse,
|
|
249
|
+
]);
|
|
250
|
+
|
|
251
|
+
export const shader_vgeo_cut_collect = ComputeShader.from({
|
|
252
|
+
label: "VGeo cut collect instances",
|
|
253
|
+
body,
|
|
254
|
+
resources,
|
|
255
|
+
});
|
package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_vgeo_cut_queue_prepare.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js"],"names":[],"mappings":"AA2EA,0DAIG;8BA3E2B,qCAAqC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { atomic_u32 } from "../../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../../../../shader/type/WebGPUArray.js";
|
|
3
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
4
|
+
import { COLLECTION_U32_STRUCT_WRITE } from "../../../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
|
|
5
|
+
import { ComputeShader } from "../../../../shader/ComputeShader.js";
|
|
6
|
+
import {
|
|
7
|
+
STRUCT_DISPATCH_COMPUTE_COMMAND
|
|
8
|
+
} from "../../../../gpu_primitive/indirect/STRUCT_DISPATCH_COMPUTE_COMMAND.js";
|
|
9
|
+
import { ShaderResourceSetDescriptor } from "../../../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
10
|
+
import { chunk_divide_round_up_u32 } from "../../../../shader/chunk/math/chunk_divide_round_up_u32.js";
|
|
11
|
+
import { VGEO_CUT_STAT } from "../layout/VGEO_CUT_STAT.js";
|
|
12
|
+
import { VGEO_FEEDBACK_OFFSET } from "../layout/VGEO_FEEDBACK_OFFSET.js";
|
|
13
|
+
import { VGEO_CUT_PARAMS_STRUCT } from "./VGEO_CUT_PARAMS_STRUCT.js";
|
|
14
|
+
import { VGEO_CUT_WORKGROUP_SIZE } from "./VGEO_CUT_WORKGROUP_SIZE.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Between two wavefronts: clamp what the last one produced, turn it into a dispatch, and empty the
|
|
18
|
+
* queue the next one will write.
|
|
19
|
+
*
|
|
20
|
+
* The clamp is the load-bearing half. A wavefront reserves its output slots with `atomicAdd` and
|
|
21
|
+
* bounds-checks each write, so an overflowing iteration writes what fits and counts the rest — but
|
|
22
|
+
* the count itself runs past capacity, and handing *that* to an indirect dispatch would dispatch
|
|
23
|
+
* lanes over the end of a pooled buffer. Clamping here is what keeps the overflow a lost subtree
|
|
24
|
+
* rather than a read of somebody else's transient.
|
|
25
|
+
*
|
|
26
|
+
* Zeroing the *other* queue is here for the same reason it is here at all: the two ping-pong, so
|
|
27
|
+
* the buffer this iteration reads is the one the next iteration writes, and there is exactly one
|
|
28
|
+
* moment when neither pass is touching it.
|
|
29
|
+
*
|
|
30
|
+
* @author Alex Goldring
|
|
31
|
+
* @copyright Company Named Limited (c) 2026
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
35
|
+
|
|
36
|
+
resources.createGroup()
|
|
37
|
+
.addUniform("params", VGEO_CUT_PARAMS_STRUCT)
|
|
38
|
+
// what the wavefront just produced, and what the next one consumes
|
|
39
|
+
.addStorageBuffer("queue_ready", COLLECTION_U32_STRUCT_WRITE, true)
|
|
40
|
+
// what the next wavefront will produce into
|
|
41
|
+
.addStorageBuffer("queue_spare", COLLECTION_U32_STRUCT_WRITE, true)
|
|
42
|
+
.addStorageBuffer("command", STRUCT_DISPATCH_COMPUTE_COMMAND, true)
|
|
43
|
+
// the frame's counters: this is the only pass that can see how deep the descent went
|
|
44
|
+
.addStorageBuffer("feedback", WebGPUArray.from(atomic_u32), true)
|
|
45
|
+
;
|
|
46
|
+
|
|
47
|
+
const body = CodeChunk.from(
|
|
48
|
+
//language=WGSL
|
|
49
|
+
`
|
|
50
|
+
@compute @workgroup_size(1)
|
|
51
|
+
fn main() {
|
|
52
|
+
let produced = atomicLoad(&queue_ready.count);
|
|
53
|
+
|
|
54
|
+
let count = min(produced, params.queue_capacity);
|
|
55
|
+
|
|
56
|
+
atomicStore(&queue_ready.count, count);
|
|
57
|
+
atomicStore(&queue_spare.count, 0u);
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
What was outstanding when this pass ran. A plain store rather than an add, so the last prepare
|
|
61
|
+
of the frame is the one that is read — and the seam records one extra prepare after the
|
|
62
|
+
wavefront loop, whose whole purpose is to leave this number behind. A descent that stops with
|
|
63
|
+
work still queued is the one degradation that costs a hole rather than coarseness, and until
|
|
64
|
+
now nothing anywhere counted it (REVIEW_LEDGER M8).
|
|
65
|
+
*/
|
|
66
|
+
atomicStore(&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.QUEUE_REMAINING}u], count);
|
|
67
|
+
|
|
68
|
+
command.workgroupCountX = divide_round_up_u32(count, ${VGEO_CUT_WORKGROUP_SIZE}u);
|
|
69
|
+
command.workgroupCountY = 1u;
|
|
70
|
+
command.workgroupCountZ = 1u;
|
|
71
|
+
}
|
|
72
|
+
`, [
|
|
73
|
+
chunk_divide_round_up_u32,
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
export const shader_vgeo_cut_queue_prepare = ComputeShader.from({
|
|
77
|
+
label: "VGeo cut queue prepare",
|
|
78
|
+
body,
|
|
79
|
+
resources,
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_vgeo_cut_seed.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js"],"names":[],"mappings":"AA2IA,iDAIG;8BA1I2B,qCAAqC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { atomic_u32, u32 } from "../../../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
|
|
2
|
+
import { WebGPUArray } from "../../../../shader/type/WebGPUArray.js";
|
|
3
|
+
import { CodeChunk } from "../../../../shader/compiler/CodeChunk.js";
|
|
4
|
+
import { COLLECTION_U32_STRUCT_READ } from "../../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
|
|
5
|
+
import { COLLECTION_U32_STRUCT_WRITE } from "../../../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
|
|
6
|
+
import { ComputeShader } from "../../../../shader/ComputeShader.js";
|
|
7
|
+
import { ShaderResourceSetDescriptor } from "../../../../shader/resource/ShaderResourceSetDescriptor.js";
|
|
8
|
+
import { VGEO_CUT_STAT } from "../layout/VGEO_CUT_STAT.js";
|
|
9
|
+
import { VGEO_FEEDBACK_OFFSET } from "../layout/VGEO_FEEDBACK_OFFSET.js";
|
|
10
|
+
import { VGEO_INSTANCE_OFFSET } from "../layout/VGEO_INSTANCE_OFFSET.js";
|
|
11
|
+
import { VGEO_INSTANCE_WORDS } from "../layout/VGEO_INSTANCE_WORDS.js";
|
|
12
|
+
import { VGEO_PAGE_ROW_NONE } from "../layout/VGEO_PAGE_ROW_NONE.js";
|
|
13
|
+
import { VGEO_PAGE_ROW_OFFSET } from "../layout/VGEO_PAGE_ROW_OFFSET.js";
|
|
14
|
+
import { VGEO_CUT_PARAMS_STRUCT } from "./VGEO_CUT_PARAMS_STRUCT.js";
|
|
15
|
+
import { VGEO_CUT_WORKGROUP_SIZE } from "./VGEO_CUT_WORKGROUP_SIZE.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Seed the wavefront: one item per visible VG instance, naming its root page's node 0.
|
|
19
|
+
*
|
|
20
|
+
* This is also where each instance learns where its slice of the claim bitmask starts, out of the
|
|
21
|
+
* prefix scan over instance ordinal capacities — the same scan shape `graph_expand_meshes_to_meshlets`
|
|
22
|
+
* runs to size its meshlet output, for the same reason.
|
|
23
|
+
*
|
|
24
|
+
* **An instance whose slice does not fit is refused**, and that direction is not arbitrary. A cut
|
|
25
|
+
* run without a claim visits every page once per parent page that reaches it and emits its whole
|
|
26
|
+
* cut that many times over; the failure reads as corrupt geometry rather than as a missing
|
|
27
|
+
* instance, and a missing instance is the one a human can see and attribute.
|
|
28
|
+
*
|
|
29
|
+
* @author Alex Goldring
|
|
30
|
+
* @copyright Company Named Limited (c) 2026
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const resources = new ShaderResourceSetDescriptor();
|
|
34
|
+
|
|
35
|
+
resources.createGroup()
|
|
36
|
+
.addUniform("params", VGEO_CUT_PARAMS_STRUCT)
|
|
37
|
+
// the page slots; this pass reads one header field out of one of them
|
|
38
|
+
.addStorageBuffer("vg_arena", WebGPUArray.from(u32), false)
|
|
39
|
+
.addStorageBuffer("prefix_sums", COLLECTION_U32_STRUCT_READ, false)
|
|
40
|
+
;
|
|
41
|
+
|
|
42
|
+
resources.createGroup()
|
|
43
|
+
.addStorageBuffer("instances", WebGPUArray.from(u32), true)
|
|
44
|
+
.addStorageBuffer("queue_out", COLLECTION_U32_STRUCT_WRITE, true)
|
|
45
|
+
.addStorageBuffer("claim", WebGPUArray.from(atomic_u32), true)
|
|
46
|
+
.addStorageBuffer("feedback", WebGPUArray.from(atomic_u32), true)
|
|
47
|
+
;
|
|
48
|
+
|
|
49
|
+
const body = CodeChunk.from(
|
|
50
|
+
//language=WGSL
|
|
51
|
+
`
|
|
52
|
+
@compute @workgroup_size(${VGEO_CUT_WORKGROUP_SIZE})
|
|
53
|
+
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
|
|
54
|
+
let instance_slot = global_id.x;
|
|
55
|
+
|
|
56
|
+
if (instance_slot >= prefix_sums.count) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let instance_base = instance_slot * ${VGEO_INSTANCE_WORDS}u;
|
|
61
|
+
|
|
62
|
+
// inclusive scan: this instance's base is the total below it
|
|
63
|
+
var claim_base = 0u;
|
|
64
|
+
|
|
65
|
+
if (instance_slot > 0u) {
|
|
66
|
+
claim_base = prefix_sums.elements[instance_slot - 1u];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let capacity = instances[instance_base + ${VGEO_INSTANCE_OFFSET.ORDINAL_CAPACITY}u];
|
|
70
|
+
|
|
71
|
+
if ((claim_base + capacity + 31u) >> 5u > params.claim_word_count) {
|
|
72
|
+
atomicAdd(
|
|
73
|
+
&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.INSTANCES_DROPPED}u], 1u
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// left with a capacity of zero, so nothing downstream can claim on its behalf either
|
|
77
|
+
instances[instance_base + ${VGEO_INSTANCE_OFFSET.ORDINAL_CAPACITY}u] = 0u;
|
|
78
|
+
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
instances[instance_base + ${VGEO_INSTANCE_OFFSET.CLAIM_BASE}u] = claim_base;
|
|
83
|
+
|
|
84
|
+
let page_row = instances[instance_base + ${VGEO_INSTANCE_OFFSET.ROOT_PAGE_ROW}u];
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
A geometry whose root page is not resident draws nothing, and saying so here is one compare.
|
|
88
|
+
The host refuses to register such a geometry at all, but it used to say so through
|
|
89
|
+
\`assert.notEqual\`, and this engine ships with \`assert.*\` stripped — so in a shipped build the
|
|
90
|
+
sentinel reached this line, was multiplied by the slot stride as a u32, and wrapped into a live
|
|
91
|
+
word of the feedback buffer (REVIEW_LEDGER C7). A guard the build cannot remove costs less than
|
|
92
|
+
the failure it prevents is worth diagnosing.
|
|
93
|
+
*/
|
|
94
|
+
if (page_row == ${VGEO_PAGE_ROW_NONE}u) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
The root page is pinned, so this claim always wins — but it is taken rather than assumed,
|
|
100
|
+
because it is also what stamps the root page as touched, and a root that never reports a touch
|
|
101
|
+
is a root that ages out of the touch-LRU while it is on screen.
|
|
102
|
+
*/
|
|
103
|
+
let ordinal = vg_arena[
|
|
104
|
+
page_row * params.page_slot_words + ${VGEO_PAGE_ROW_OFFSET.ORDINAL}u
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
let bit = claim_base + ordinal;
|
|
108
|
+
|
|
109
|
+
atomicOr(&claim[bit >> 5u], 1u << (bit & 31u));
|
|
110
|
+
|
|
111
|
+
atomicAdd(&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.PAGES}u], 1u);
|
|
112
|
+
|
|
113
|
+
if (atomicExchange(&feedback[params.touch_stamp_base + page_row], 1u) == 0u) {
|
|
114
|
+
let touch_slot = atomicAdd(&feedback[${VGEO_FEEDBACK_OFFSET.TOUCH_COUNT}u], 1u);
|
|
115
|
+
|
|
116
|
+
if (touch_slot < params.touch_capacity) {
|
|
117
|
+
atomicStore(&feedback[params.touch_base + touch_slot], page_row);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let slot = atomicAdd(&queue_out.count, 1u);
|
|
122
|
+
|
|
123
|
+
if (slot >= params.queue_capacity) {
|
|
124
|
+
atomicAdd(
|
|
125
|
+
&feedback[${VGEO_FEEDBACK_OFFSET.STATS}u + ${VGEO_CUT_STAT.QUEUE_DROPPED}u], 1u
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let base = slot * 4u;
|
|
132
|
+
|
|
133
|
+
queue_out.elements[base] = instance_slot;
|
|
134
|
+
queue_out.elements[base + 1u] = page_row;
|
|
135
|
+
queue_out.elements[base + 2u] = 0u;
|
|
136
|
+
queue_out.elements[base + 3u] = 0u;
|
|
137
|
+
}
|
|
138
|
+
`, []);
|
|
139
|
+
|
|
140
|
+
export const shader_vgeo_cut_seed = ComputeShader.from({
|
|
141
|
+
label: "VGeo cut seed",
|
|
142
|
+
body,
|
|
143
|
+
resources,
|
|
144
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shader_vgeo_cut_traverse.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js"],"names":[],"mappings":"AA6gBA,qDAIG;8BA9gB2B,qCAAqC"}
|