@woosh/meep-engine 3.64.1 → 3.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/core/binary/BinaryBuffer.d.ts +5 -0
- package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
- package/src/core/binary/BinaryBuffer.js +39 -5
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
- package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
- package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
- package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
- package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
- package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
- package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
- package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
- package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
- package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
- package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
- package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
- package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
- package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
- package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
- package/src/engine/graphics3/GroundCoverSystem.js +58 -0
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +372 -110
- package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
- package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
- package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
- package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
- package/src/engine/network/sim/SimActionExecutor.js +65 -9
- package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
- package/src/engine/network/state/PredictionHistory.js +6 -1
- package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
- package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
- package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
- package/src/engine/network/time/RenderPlayout.d.ts +23 -3
- package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
- package/src/engine/network/time/RenderPlayout.js +40 -4
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
- package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
- package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
- package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
- package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
- package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
- package/src/shade/playground/grass_surfaces/index.html +75 -0
- package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
- package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
- package/src/shade/playground/grass_surfaces/main.js +593 -0
- package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
- package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
- package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
- package/src/shade/playground/probe_clipmap_box/README.md +5 -1
- package/src/shade/playground/probe_clipmap_box/index.html +12 -0
- package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap_box/main.js +15 -0
- package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
- package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
- package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +47 -43
- package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
- package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
- package/src/shade/renderer/extension/ViewTextures.js +19 -5
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
- package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
- package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
- package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
- package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
- package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
- package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
- package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
- package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
- package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
- package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
- package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
- package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
- package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
- package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
- package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
- package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
- package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
- package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
- package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
- package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
- package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
- package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
- package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
- package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
- package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
- package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
- package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
- package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
- package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
- package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
- package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
- package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
- package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
- package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
- package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
- package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
- package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
- package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
- package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
- package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
- package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
- package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
- package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
- package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
- package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
- package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
- package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
- package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
- package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
- package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
- package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
- package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
- package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
- package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
- package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
- package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
- package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
- package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
- package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
- package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
- package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
- package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
- package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
- package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
- package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
- package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
- package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
- package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
- package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
- package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
- package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
- package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
- package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
- package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
- package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
- package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
- package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
- package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
- package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
- package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
- package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
- package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
- package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
- package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
- package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
- package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
- package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
- package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
- package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts
CHANGED
|
@@ -4,8 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* ```wgsl
|
|
6
6
|
* fn probe_clipmap_want(wants: bool, position: vec3<f32>, bias_direction: vec3<f32>, cascade_count: u32, resolution: u32, anchor: vec3<f32>, select_half: f32, wanted_capacity: u32)
|
|
7
|
+
* fn probe_clipmap_want_cage(wants: bool, cascade: u32, cage: vec3<i32>, resolution: u32, wanted_capacity: u32)
|
|
7
8
|
* ```
|
|
8
9
|
*
|
|
10
|
+
* `probe_clipmap_want_cage` wants one cage by name, the cage whose least point is `cage` in `cascade`, for a
|
|
11
|
+
* caller that knows its cages without a point to read them from; the cascade's cage window must hold it
|
|
12
|
+
* (`clipmap_contains`). `probe_clipmap_want` is the two it reads from a point.
|
|
13
|
+
*
|
|
9
14
|
* The cages are the pick's: the cascade `probe_clipmap_select_in` answers for the point, by the windows'
|
|
10
15
|
* `anchor` and `select_half` as the pick reads them, the cage of the point biased along `bias_direction` by
|
|
11
16
|
* that cascade's spacing, and in the cascade's blend skirt the next cascade's cage too, biased by its own. A cage a bias moved out of its window is not wanted. Each cage
|
|
@@ -16,8 +21,8 @@
|
|
|
16
21
|
* workgroup's table and sets its bits; the rest want it through that lane. Measured on the AMD iGPU at
|
|
17
22
|
* 1280×720 on Sponza before the claims, the bits' atomics were 140 of want's 345 µs and the appends 90.
|
|
18
23
|
*
|
|
19
|
-
* Every lane of the workgroup calls
|
|
20
|
-
* the subgroup's.
|
|
24
|
+
* Every lane of the workgroup calls `probe_clipmap_want` once, or `probe_clipmap_want_cage` at most twice, which
|
|
25
|
+
* the claim table is sized for, wanting or not, from uniform control flow: the appends are the subgroup's.
|
|
21
26
|
*
|
|
22
27
|
* @type {CodeChunk}
|
|
23
28
|
*/
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk_probe_clipmap_want.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js"],"names":[],"mappings":"AA0BA
|
|
1
|
+
{"version":3,"file":"chunk_probe_clipmap_want.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js"],"names":[],"mappings":"AA0BA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,uCAFU,SAAS,CA+EZ;0BAlImB,uCAAuC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js
CHANGED
|
@@ -13,7 +13,7 @@ import { PROBE_THREAD_WORKGROUP_SIZE } from "./PROBE_CLIPMAP.js";
|
|
|
13
13
|
/**
|
|
14
14
|
* Slots of a workgroup's claim table: twice the claims its lanes make at most, a cage in each of two
|
|
15
15
|
* cascades a lane, so a probe finds a slot within a few. Sized for {@link PROBE_THREAD_WORKGROUP_SIZE}
|
|
16
|
-
* lanes: want's 8×8 tiles, and the hits' wants' 64.
|
|
16
|
+
* lanes: want's 8×8 tiles, and the hits' wants' 64; the meshlets' wants' lanes are twice as many, a cage each.
|
|
17
17
|
* @type {number}
|
|
18
18
|
*/
|
|
19
19
|
const WANT_CLAIM_SLOTS = 2 * 2 * PROBE_THREAD_WORKGROUP_SIZE;
|
|
@@ -30,8 +30,13 @@ const WANT_CLAIM_PROBES = 16;
|
|
|
30
30
|
*
|
|
31
31
|
* ```wgsl
|
|
32
32
|
* fn probe_clipmap_want(wants: bool, position: vec3<f32>, bias_direction: vec3<f32>, cascade_count: u32, resolution: u32, anchor: vec3<f32>, select_half: f32, wanted_capacity: u32)
|
|
33
|
+
* fn probe_clipmap_want_cage(wants: bool, cascade: u32, cage: vec3<i32>, resolution: u32, wanted_capacity: u32)
|
|
33
34
|
* ```
|
|
34
35
|
*
|
|
36
|
+
* `probe_clipmap_want_cage` wants one cage by name, the cage whose least point is `cage` in `cascade`, for a
|
|
37
|
+
* caller that knows its cages without a point to read them from; the cascade's cage window must hold it
|
|
38
|
+
* (`clipmap_contains`). `probe_clipmap_want` is the two it reads from a point.
|
|
39
|
+
*
|
|
35
40
|
* The cages are the pick's: the cascade `probe_clipmap_select_in` answers for the point, by the windows'
|
|
36
41
|
* `anchor` and `select_half` as the pick reads them, the cage of the point biased along `bias_direction` by
|
|
37
42
|
* that cascade's spacing, and in the cascade's blend skirt the next cascade's cage too, biased by its own. A cage a bias moved out of its window is not wanted. Each cage
|
|
@@ -42,8 +47,8 @@ const WANT_CLAIM_PROBES = 16;
|
|
|
42
47
|
* workgroup's table and sets its bits; the rest want it through that lane. Measured on the AMD iGPU at
|
|
43
48
|
* 1280×720 on Sponza before the claims, the bits' atomics were 140 of want's 345 µs and the appends 90.
|
|
44
49
|
*
|
|
45
|
-
* Every lane of the workgroup calls
|
|
46
|
-
* the subgroup's.
|
|
50
|
+
* Every lane of the workgroup calls `probe_clipmap_want` once, or `probe_clipmap_want_cage` at most twice, which
|
|
51
|
+
* the claim table is sized for, wanting or not, from uniform control flow: the appends are the subgroup's.
|
|
47
52
|
*
|
|
48
53
|
* @type {CodeChunk}
|
|
49
54
|
*/
|
|
@@ -80,46 +85,45 @@ fn probe_want_claim(key: u32) -> bool {
|
|
|
80
85
|
return true;
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
fn
|
|
84
|
-
let selection = probe_clipmap_select_in(&probe_levels, cascade_count, anchor, select_half, position);
|
|
85
|
-
|
|
86
|
-
let held = wants && selection.level != CLIPMAP_LEVEL_NONE;
|
|
87
|
-
let finest = select(0u, selection.level, held);
|
|
88
|
-
let next = min(finest + 1u, cascade_count - 1u);
|
|
89
|
-
|
|
90
|
-
var cage_finest: vec3<i32>;
|
|
91
|
-
var cage_next: vec3<i32>;
|
|
92
|
-
|
|
88
|
+
fn probe_clipmap_want_cage(wants: bool, cascade: u32, cage: vec3<i32>, resolution: u32, wanted_capacity: u32) {
|
|
93
89
|
// storage wraps by the window's side, a power of two: the low bits of a point, negative ones too
|
|
94
90
|
let wrap = vec3<u32>(resolution - 1u);
|
|
95
91
|
|
|
96
|
-
let
|
|
97
|
-
&& probe_want_claim(probe_clipmap_key(finest, vec3<u32>(cage_finest) & wrap, resolution));
|
|
98
|
-
let wants_next = held && selection.edge_weight > 0.0 && finest + 1u < cascade_count
|
|
99
|
-
&& probe_clipmap_cage(next, position, bias_direction, &cage_next)
|
|
100
|
-
&& probe_want_claim(probe_clipmap_key(next, vec3<u32>(cage_next) & wrap, resolution));
|
|
101
|
-
|
|
102
|
-
// every lane through all sixteen corners, so that the appends stay in uniform control flow
|
|
103
|
-
for (var k = 0u; k < 16u; k++) {
|
|
104
|
-
let coarse = k >= 8u;
|
|
105
|
-
let cascade = select(finest, next, coarse);
|
|
106
|
-
let wanted = select(wants_finest, wants_next, coarse);
|
|
107
|
-
let corner = vec3<i32>(vec3<u32>(k & 1u, (k >> 1u) & 1u, (k >> 2u) & 1u));
|
|
108
|
-
let point = select(cage_finest, cage_next, coarse) + corner;
|
|
92
|
+
let claimed = wants && probe_want_claim(probe_clipmap_key(cascade, vec3<u32>(cage) & wrap, resolution));
|
|
109
93
|
|
|
110
|
-
|
|
111
|
-
|
|
94
|
+
// every lane through all eight corners, so that the appends stay in uniform control flow
|
|
95
|
+
for (var k = 0u; k < 8u; k++) {
|
|
96
|
+
let corner = vec3<i32>(vec3<u32>(k & 1u, (k >> 1u) & 1u, (k >> 2u) & 1u));
|
|
97
|
+
let key = probe_clipmap_key(cascade, vec3<u32>(cage + corner) & wrap, resolution);
|
|
112
98
|
let bit = 1u << (key & 31u);
|
|
113
99
|
|
|
114
100
|
var first = false;
|
|
115
101
|
|
|
116
|
-
if (
|
|
102
|
+
if (claimed) {
|
|
117
103
|
first = (atomicOr(&probe_wanted_bits[key >> 5u], bit) & bit) == 0u;
|
|
118
104
|
}
|
|
119
105
|
|
|
120
106
|
collection_u32_append(&probe_wanted, first, key, wanted_capacity);
|
|
121
107
|
}
|
|
122
108
|
}
|
|
109
|
+
|
|
110
|
+
fn probe_clipmap_want(wants: bool, position: vec3<f32>, bias_direction: vec3<f32>, cascade_count: u32, resolution: u32, anchor: vec3<f32>, select_half: f32, wanted_capacity: u32) {
|
|
111
|
+
let selection = probe_clipmap_select_in(&probe_levels, cascade_count, anchor, select_half, position);
|
|
112
|
+
|
|
113
|
+
let held = wants && selection.level != CLIPMAP_LEVEL_NONE;
|
|
114
|
+
let finest = select(0u, selection.level, held);
|
|
115
|
+
let next = min(finest + 1u, cascade_count - 1u);
|
|
116
|
+
|
|
117
|
+
var cage_finest: vec3<i32>;
|
|
118
|
+
var cage_next: vec3<i32>;
|
|
119
|
+
|
|
120
|
+
let wants_finest = held && probe_clipmap_cage(finest, position, bias_direction, &cage_finest);
|
|
121
|
+
let wants_next = held && selection.edge_weight > 0.0 && finest + 1u < cascade_count
|
|
122
|
+
&& probe_clipmap_cage(next, position, bias_direction, &cage_next);
|
|
123
|
+
|
|
124
|
+
probe_clipmap_want_cage(wants_finest, finest, cage_finest, resolution, wanted_capacity);
|
|
125
|
+
probe_clipmap_want_cage(wants_next, next, cage_next, resolution, wanted_capacity);
|
|
126
|
+
}
|
|
123
127
|
`, [
|
|
124
128
|
chunk_probe_clipmap,
|
|
125
129
|
chunk_probe_clipmap_select_in,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record the wants of a list of meshlets whose fragments pick probes (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3):
|
|
3
|
+
* the meshlets a forward pass draws, which no pixel of the G-buffer stands for. Each wants the cages a reader
|
|
4
|
+
* anywhere inside its world box can read, a thread a cage: its cages are counted
|
|
5
|
+
* (`shader_probe_clipmap_want_meshlet_count`), the counts summed (`graph_prefix_scan_csdldf`), and the sums
|
|
6
|
+
* launch the wants (`shader_probe_clipmap_want_meshlets`), as the meshes' expansion to meshlets is launched.
|
|
7
|
+
*
|
|
8
|
+
* The wants go into the clipmap's late set (`GPUProbeClipmap.write_want_bindings`), so the pass belongs after the
|
|
9
|
+
* clipmap's lifetime in the frame, and its probes are admitted by the next frame's.
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} options
|
|
12
|
+
* @param {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} options.graph
|
|
13
|
+
* @param {import("./GPUProbeClipmap.js").GPUProbeClipmap} options.clipmap the clipmap the fragments pick from
|
|
14
|
+
* @param {import("../../../scene/GPUSceneContext.js").GPUSceneContext} options.scene the meshlets' scene
|
|
15
|
+
* @param {number} options.camera graph handle of the view's camera uniform
|
|
16
|
+
* @param {number} options.meshlet_collection graph handle of the list, `MESHLET_COLLECTION_STRUCT`
|
|
17
|
+
* @param {number} options.meshlet_iterator_command graph handle of the indirect dispatch that walks the list, a
|
|
18
|
+
* workgroup of `COMPUTE_SHADER_DEFAULT_GROUP_SIZE` meshlets, folded
|
|
19
|
+
*/
|
|
20
|
+
export function graph_probe_clipmap_want_meshlets({ graph, clipmap, scene, camera, meshlet_collection, meshlet_iterator_command }: {
|
|
21
|
+
graph: import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
|
|
22
|
+
clipmap: import("./GPUProbeClipmap.js").GPUProbeClipmap;
|
|
23
|
+
scene: import("../../../scene/GPUSceneContext.js").GPUSceneContext;
|
|
24
|
+
camera: number;
|
|
25
|
+
meshlet_collection: number;
|
|
26
|
+
meshlet_iterator_command: number;
|
|
27
|
+
}): void;
|
|
28
|
+
//# sourceMappingURL=graph_probe_clipmap_want_meshlets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph_probe_clipmap_want_meshlets.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IARyG,KAAK,EAAnG,OAAO,iEAAiE,EAAE,UAAU;IAC5B,OAAO,EAA/D,OAAO,sBAAsB,EAAE,eAAe;IACuB,KAAK,EAA1E,OAAO,mCAAmC,EAAE,eAAe;IAC3C,MAAM,EAAtB,MAAM;IACU,kBAAkB,EAAlC,MAAM;IACU,wBAAwB,EAAxC,MAAM;SAoGhB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { assert } from "../../../../../core/assert.js";
|
|
2
|
+
import { BufferResourceDescriptor } from "../../../../device/graph/BufferResourceDescriptor.js";
|
|
3
|
+
import { MESHLET_DEFINITION_STRUCT } from "../../../geometry/meshlet/encoding/MESHLET_DEFINITION_STRUCT.js";
|
|
4
|
+
import { INDIRECT_COMPUTE_COMMAND_DESCRIPTOR } from "../../../gpu_primitive/indirect/IndirectComputeCommandBuildPass.js";
|
|
5
|
+
import {
|
|
6
|
+
graph_prefix_scan_csdldf,
|
|
7
|
+
prefix_scan_csdldf_output_descriptor
|
|
8
|
+
} from "../../../gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js";
|
|
9
|
+
import { shader_prefix_sum_to_command } from "../../../rasterize/expand/mesh/shader_prefix_sum_to_command.js";
|
|
10
|
+
import { graph_create_buffer } from "../../../shader/graph/graph_create_buffer.js";
|
|
11
|
+
import {
|
|
12
|
+
shader_probe_clipmap_want_meshlet_count,
|
|
13
|
+
shader_probe_clipmap_want_meshlets
|
|
14
|
+
} from "./shader_probe_clipmap_want_meshlets.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Bytes a meshlet list's count takes ahead of its elements, which sit on a 16-byte boundary.
|
|
18
|
+
* @type {number}
|
|
19
|
+
*/
|
|
20
|
+
const MESHLET_LIST_HEADER_BYTES = 16;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Record the wants of a list of meshlets whose fragments pick probes (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3):
|
|
24
|
+
* the meshlets a forward pass draws, which no pixel of the G-buffer stands for. Each wants the cages a reader
|
|
25
|
+
* anywhere inside its world box can read, a thread a cage: its cages are counted
|
|
26
|
+
* (`shader_probe_clipmap_want_meshlet_count`), the counts summed (`graph_prefix_scan_csdldf`), and the sums
|
|
27
|
+
* launch the wants (`shader_probe_clipmap_want_meshlets`), as the meshes' expansion to meshlets is launched.
|
|
28
|
+
*
|
|
29
|
+
* The wants go into the clipmap's late set (`GPUProbeClipmap.write_want_bindings`), so the pass belongs after the
|
|
30
|
+
* clipmap's lifetime in the frame, and its probes are admitted by the next frame's.
|
|
31
|
+
*
|
|
32
|
+
* @param {Object} options
|
|
33
|
+
* @param {import("../../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} options.graph
|
|
34
|
+
* @param {import("./GPUProbeClipmap.js").GPUProbeClipmap} options.clipmap the clipmap the fragments pick from
|
|
35
|
+
* @param {import("../../../scene/GPUSceneContext.js").GPUSceneContext} options.scene the meshlets' scene
|
|
36
|
+
* @param {number} options.camera graph handle of the view's camera uniform
|
|
37
|
+
* @param {number} options.meshlet_collection graph handle of the list, `MESHLET_COLLECTION_STRUCT`
|
|
38
|
+
* @param {number} options.meshlet_iterator_command graph handle of the indirect dispatch that walks the list, a
|
|
39
|
+
* workgroup of `COMPUTE_SHADER_DEFAULT_GROUP_SIZE` meshlets, folded
|
|
40
|
+
*/
|
|
41
|
+
export function graph_probe_clipmap_want_meshlets({ graph, clipmap, scene, camera, meshlet_collection, meshlet_iterator_command }) {
|
|
42
|
+
assert.defined(graph, 'graph');
|
|
43
|
+
assert.defined(clipmap, 'clipmap');
|
|
44
|
+
assert.defined(scene, 'scene');
|
|
45
|
+
assert.isNonNegativeInteger(camera, 'camera');
|
|
46
|
+
assert.isNonNegativeInteger(meshlet_collection, 'meshlet_collection');
|
|
47
|
+
assert.isNonNegativeInteger(meshlet_iterator_command, 'meshlet_iterator_command');
|
|
48
|
+
|
|
49
|
+
graph.push_scope("probe clipmap want meshlets");
|
|
50
|
+
|
|
51
|
+
// a count for every meshlet the list has room for
|
|
52
|
+
const capacity = Math.floor((graph.getDescriptor(meshlet_collection).size - MESHLET_LIST_HEADER_BYTES) / MESHLET_DEFINITION_STRUCT.size);
|
|
53
|
+
|
|
54
|
+
// what the clipmap binds for a late want: its levels and settings for both passes, its late list and bits for the wants'
|
|
55
|
+
const want = {};
|
|
56
|
+
|
|
57
|
+
const count_data = {};
|
|
58
|
+
|
|
59
|
+
const count_pass = graph.add("count cages", count_data, (data, resources, context) => {
|
|
60
|
+
clipmap.write_want_bindings(want);
|
|
61
|
+
|
|
62
|
+
shader_probe_clipmap_want_meshlet_count.dispatchIndirect({
|
|
63
|
+
encoder: context.encoder,
|
|
64
|
+
command: resources.get(data.command),
|
|
65
|
+
bindings: {
|
|
66
|
+
scene_database: scene.scene_database_buffer,
|
|
67
|
+
meshlet_metadata: scene.geometries.meshlets.buffer_metadata,
|
|
68
|
+
input: resources.get(data.input),
|
|
69
|
+
output: resources.get(data.output),
|
|
70
|
+
probe_levels: want.probe_levels,
|
|
71
|
+
settings: want.settings,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
count_data.command = count_pass.read(meshlet_iterator_command);
|
|
77
|
+
count_data.input = count_pass.read(meshlet_collection);
|
|
78
|
+
count_data.output = count_pass.create("cage counts", BufferResourceDescriptor.from(
|
|
79
|
+
MESHLET_LIST_HEADER_BYTES + Math.max(1, Math.ceil(capacity / 4)) * 16,
|
|
80
|
+
GPUBufferUsage.STORAGE,
|
|
81
|
+
// the count, which no thread writes for a list of no meshlet
|
|
82
|
+
0, MESHLET_LIST_HEADER_BYTES,
|
|
83
|
+
));
|
|
84
|
+
|
|
85
|
+
const sums = graph_prefix_scan_csdldf({
|
|
86
|
+
graph,
|
|
87
|
+
input: count_data.output,
|
|
88
|
+
output: graph_create_buffer(graph, "cage offsets", prefix_scan_csdldf_output_descriptor(capacity)),
|
|
89
|
+
element_max_count: capacity,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const command_data = {};
|
|
93
|
+
|
|
94
|
+
const command_pass = graph.add("make want command", command_data, (data, resources, context) => {
|
|
95
|
+
shader_prefix_sum_to_command.dispatch({
|
|
96
|
+
encoder: context.encoder,
|
|
97
|
+
bindings: {
|
|
98
|
+
prefix_sums: resources.get(data.prefix_sums),
|
|
99
|
+
command: resources.get(data.command),
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
command_data.prefix_sums = command_pass.read(sums);
|
|
105
|
+
command_data.command = command_pass.create("command", INDIRECT_COMPUTE_COMMAND_DESCRIPTOR);
|
|
106
|
+
|
|
107
|
+
const want_data = {};
|
|
108
|
+
|
|
109
|
+
const want_pass = graph.add("want cages", want_data, (data, resources, context) => {
|
|
110
|
+
clipmap.write_want_bindings(want);
|
|
111
|
+
|
|
112
|
+
shader_probe_clipmap_want_meshlets.dispatchIndirect({
|
|
113
|
+
encoder: context.encoder,
|
|
114
|
+
command: resources.get(data.command),
|
|
115
|
+
bindings: {
|
|
116
|
+
camera: resources.get(data.camera),
|
|
117
|
+
scene_database: scene.scene_database_buffer,
|
|
118
|
+
meshlet_metadata: scene.geometries.meshlets.buffer_metadata,
|
|
119
|
+
input: resources.get(data.input),
|
|
120
|
+
prefix_sums: resources.get(data.prefix_sums),
|
|
121
|
+
probe_levels: want.probe_levels,
|
|
122
|
+
probe_wanted: want.probe_wanted,
|
|
123
|
+
probe_wanted_bits: want.probe_wanted_bits,
|
|
124
|
+
settings: want.settings,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
want_data.command = want_pass.read(command_data.command);
|
|
130
|
+
want_data.camera = want_pass.read(camera);
|
|
131
|
+
want_data.input = want_pass.read(meshlet_collection);
|
|
132
|
+
want_data.prefix_sums = want_pass.read(sums);
|
|
133
|
+
|
|
134
|
+
// it writes the clipmap's own late set, which the graph does not hold
|
|
135
|
+
want_pass.make_side_effect();
|
|
136
|
+
|
|
137
|
+
graph.pop_scope();
|
|
138
|
+
}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts
CHANGED
|
@@ -4,13 +4,17 @@
|
|
|
4
4
|
export const PROBE_DUE_SETTINGS: WebGPUStruct;
|
|
5
5
|
/**
|
|
6
6
|
* Due (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.5): a thread an entry of the frame's active list,
|
|
7
|
-
* dispatched twice through `PROBE_DISPATCH_ACTIVE` after schedule has set the period T. A probe is due
|
|
8
|
-
*
|
|
9
|
-
* - it is
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* dispatched twice through `PROBE_DISPATCH_ACTIVE` after schedule has set the period T. A probe is due:
|
|
8
|
+
* - in the first pass, which lists them first, when it is NEW: it has had no update;
|
|
9
|
+
* - in the second pass, when it is ALIVE or DEAD and `(frame + h(slot)) mod P` is 0, where P is
|
|
10
|
+
* - T when a want waits on it: a pixel or a hit wanted it since its last update, its wanted time past
|
|
11
|
+
* its traced time;
|
|
12
|
+
* - T · `idle_periods` when it is idle, none waiting on it. Every live probe keeps being updated, so one
|
|
13
|
+
* that readers reach without wanting it, the bounce at a hit among them, and one a want comes back to,
|
|
14
|
+
* holds light no older than that. Its update is any other probe's.
|
|
15
|
+
*
|
|
16
|
+
* A DEAD probe is due like an ALIVE one, its update casting `PROBE_DEAD_RAYS`, so that a probe inside a
|
|
17
|
+
* solid notices when the scene changes (Enshrouded's dead probes trace 16 a frame).
|
|
14
18
|
*
|
|
15
19
|
* Wanted since its last update, not this frame: a hit wants a probe the frame after its own probe's
|
|
16
20
|
* update, so a probe that only hits keep is wanted on few of its turns. Measured on Sponza with the
|
|
@@ -19,8 +23,8 @@ export const PROBE_DUE_SETTINGS: WebGPUStruct;
|
|
|
19
23
|
* waits on nothing: the update comes after admit in its frame, so its traced time is the want's or later.
|
|
20
24
|
*
|
|
21
25
|
* The due go on the trace list, which holds the frame's updates, at most U: past it the count still
|
|
22
|
-
* rises and nothing is written, and a probe not listed waits its next turn.
|
|
23
|
-
*
|
|
26
|
+
* rises and nothing is written, and a probe not listed waits its next turn. Schedule's T keeps the
|
|
27
|
+
* expected count a frame under U, so only NEW probes past U, a camera cut, wait.
|
|
24
28
|
*
|
|
25
29
|
* @type {ComputeShader}
|
|
26
30
|
*/
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_due.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js"],"names":[],"mappings":"AAkBA;;GAEG;AACH,iCAFU,YAAY,
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_due.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js"],"names":[],"mappings":"AAkBA;;GAEG;AACH,iCAFU,YAAY,CAaC;AAavB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,uCAFU,aAAa,CA6CpB;6BA3G0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js
CHANGED
|
@@ -28,6 +28,8 @@ export const PROBE_DUE_SETTINGS = WebGPUStruct.from({
|
|
|
28
28
|
frame: u32,
|
|
29
29
|
/** 1 for the pass that lists the NEW probes, 0 for the one that lists the rest */
|
|
30
30
|
new_only: u32,
|
|
31
|
+
/** periods between an idle probe's turns, `probe_clipmap_idle_periods`, at least 1 */
|
|
32
|
+
idle_periods: u32,
|
|
31
33
|
}, "ProbeDueSettings");
|
|
32
34
|
|
|
33
35
|
const resources = new ShaderResourceSetDescriptor();
|
|
@@ -43,13 +45,17 @@ resources.createGroup()
|
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* Due (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.5): a thread an entry of the frame's active list,
|
|
46
|
-
* dispatched twice through `PROBE_DISPATCH_ACTIVE` after schedule has set the period T. A probe is due
|
|
47
|
-
*
|
|
48
|
-
* - it is
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
48
|
+
* dispatched twice through `PROBE_DISPATCH_ACTIVE` after schedule has set the period T. A probe is due:
|
|
49
|
+
* - in the first pass, which lists them first, when it is NEW: it has had no update;
|
|
50
|
+
* - in the second pass, when it is ALIVE or DEAD and `(frame + h(slot)) mod P` is 0, where P is
|
|
51
|
+
* - T when a want waits on it: a pixel or a hit wanted it since its last update, its wanted time past
|
|
52
|
+
* its traced time;
|
|
53
|
+
* - T · `idle_periods` when it is idle, none waiting on it. Every live probe keeps being updated, so one
|
|
54
|
+
* that readers reach without wanting it, the bounce at a hit among them, and one a want comes back to,
|
|
55
|
+
* holds light no older than that. Its update is any other probe's.
|
|
56
|
+
*
|
|
57
|
+
* A DEAD probe is due like an ALIVE one, its update casting `PROBE_DEAD_RAYS`, so that a probe inside a
|
|
58
|
+
* solid notices when the scene changes (Enshrouded's dead probes trace 16 a frame).
|
|
53
59
|
*
|
|
54
60
|
* Wanted since its last update, not this frame: a hit wants a probe the frame after its own probe's
|
|
55
61
|
* update, so a probe that only hits keep is wanted on few of its turns. Measured on Sponza with the
|
|
@@ -58,8 +64,8 @@ resources.createGroup()
|
|
|
58
64
|
* waits on nothing: the update comes after admit in its frame, so its traced time is the want's or later.
|
|
59
65
|
*
|
|
60
66
|
* The due go on the trace list, which holds the frame's updates, at most U: past it the count still
|
|
61
|
-
* rises and nothing is written, and a probe not listed waits its next turn.
|
|
62
|
-
*
|
|
67
|
+
* rises and nothing is written, and a probe not listed waits its next turn. Schedule's T keeps the
|
|
68
|
+
* expected count a frame under U, so only NEW probes past U, a camera cut, wait.
|
|
63
69
|
*
|
|
64
70
|
* @type {ComputeShader}
|
|
65
71
|
*/
|
|
@@ -87,13 +93,14 @@ fn main(
|
|
|
87
93
|
// wanted since its last update
|
|
88
94
|
let waiting = probe_records[slot].wanted_frame > probe_records[slot].traced_frame;
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
// an idle probe's turn comes once in as many periods as the settings give
|
|
97
|
+
let period = max(probe_counters[PROBE_COUNTER_PERIOD], 1u) * select(max(settings.idle_periods, 1u), 1u, waiting);
|
|
91
98
|
let turn = settings.frame + hash_lowbias32(slot);
|
|
92
99
|
|
|
93
100
|
if (settings.new_only != 0u) {
|
|
94
101
|
due = kind == PROBE_STATE_NEW;
|
|
95
102
|
} else {
|
|
96
|
-
due =
|
|
103
|
+
due = (kind == PROBE_STATE_ALIVE || kind == PROBE_STATE_DEAD) && turn % period == 0u;
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js
CHANGED
|
@@ -204,7 +204,7 @@ fn probe_clipmap_local_irradiance(cascade: u32, position: vec3<f32>, normal: vec
|
|
|
204
204
|
return estimate;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
let shadow = brick_clipmap_trace(lifted, to_light / span, 0.0, reach, settings.brick_cascade_count);
|
|
207
|
+
let shadow = brick_clipmap_trace(lifted, to_light / span, 0.0, reach, settings.brick_cascade_count, settings.brick_atlas_shift);
|
|
208
208
|
|
|
209
209
|
return select(vec3<f32>(0.0), estimate, shadow.kind == BRICK_TRACE_MISS);
|
|
210
210
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_relocate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js"],"names":[],"mappings":"AAyBA;;GAEG;AACH,sCAFU,YAAY,
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_relocate.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js"],"names":[],"mappings":"AAyBA;;GAEG;AACH,sCAFU,YAAY,CASM;AAkB5B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,4CAFU,aAAa,CAyDpB;6BA3H0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js
CHANGED
|
@@ -31,6 +31,8 @@ export const PROBE_RELOCATE_SETTINGS = WebGPUStruct.from({
|
|
|
31
31
|
trace_capacity: u32,
|
|
32
32
|
/** the brick clipmap's cascades, what its field is read through */
|
|
33
33
|
brick_cascade_count: u32,
|
|
34
|
+
/** the brick atlas's footprint as shifts, `GPUBrickClipmap#atlas_shift` */
|
|
35
|
+
brick_atlas_shift: u32,
|
|
34
36
|
}, "ProbeRelocateSettings");
|
|
35
37
|
|
|
36
38
|
const resources = new ShaderResourceSetDescriptor();
|
|
@@ -97,13 +99,13 @@ fn main(
|
|
|
97
99
|
var position = lattice;
|
|
98
100
|
|
|
99
101
|
for (var step = 0u; step < ${PROBE_RELOCATION_STEPS}u; step++) {
|
|
100
|
-
let distance = brick_clipmap_distance(position, settings.brick_cascade_count);
|
|
102
|
+
let distance = brick_clipmap_distance(position, settings.brick_cascade_count, settings.brick_atlas_shift);
|
|
101
103
|
|
|
102
104
|
if (distance >= clearance) {
|
|
103
105
|
break;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
let gradient = brick_clipmap_gradient(position, settings.brick_cascade_count);
|
|
108
|
+
let gradient = brick_clipmap_gradient(position, settings.brick_cascade_count, settings.brick_atlas_shift);
|
|
107
109
|
|
|
108
110
|
if (all(gradient == vec3<f32>(0.0))) {
|
|
109
111
|
break;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_retire.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js"],"names":[],"mappings":"AAyBA;;GAEG;AACH,oCAFU,YAAY,CASI;AAiB1B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,0CAFU,aAAa,
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_retire.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js"],"names":[],"mappings":"AAyBA;;GAEG;AACH,oCAFU,YAAY,CASI;AAiB1B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,0CAFU,aAAa,CAqFpB;6BAvJ0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js
CHANGED
|
@@ -120,10 +120,9 @@ fn main(
|
|
|
120
120
|
|
|
121
121
|
// the oldest buckets whole, and as many of the one below them as are asked for; one that left its
|
|
122
122
|
// window goes anyway and takes none of those
|
|
123
|
-
|
|
124
|
-
var evicted = evictable && counted >= whole;
|
|
123
|
+
var evicted = evictable && age_eviction_whole(counted, probe_eviction.buckets);
|
|
125
124
|
|
|
126
|
-
if (held && evictable && counted
|
|
125
|
+
if (held && evictable && age_eviction_partial(counted, probe_eviction.buckets) && probe_eviction.remaining > 0u) {
|
|
127
126
|
evicted = atomicAdd(&probe_counters[PROBE_COUNTER_EVICTED], 1u) < probe_eviction.remaining;
|
|
128
127
|
}
|
|
129
128
|
|
|
@@ -6,9 +6,11 @@ export const PROBE_SCHEDULE_SETTINGS: WebGPUStruct;
|
|
|
6
6
|
* Schedule (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3, §8.5): one thread, after admit, when the frame's
|
|
7
7
|
* active list is whole.
|
|
8
8
|
* - The period: with P_w the probes waiting for an update, the NEW and those wanted since their last
|
|
9
|
-
* update,
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* update, P_i the idle, every other live probe, and m `idle_periods`,
|
|
10
|
+
* `T = max(1, ⌈(P_w + P_i / m) / U⌉)` frames. Every probe a want waits on is updated within a period and
|
|
11
|
+
* every idle one within m of them, a frame's updates U at most on average, and the period follows the
|
|
12
|
+
* live count. Retire and admit counted the waiting in `probe_counters[PROBE_COUNTER_WAITING]`, which it
|
|
13
|
+
* empties for the next frame's; the idle are the rest of the frame's active list. The period goes to
|
|
12
14
|
* `probe_counters[PROBE_COUNTER_PERIOD]` for the due passes.
|
|
13
15
|
* - The next frame's eviction, `probe_eviction`: as many slots as the free ones fall short of the frame's
|
|
14
16
|
* wanted points and the slack, the probes wanted longest ago first. Walking retire's age buckets from the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_schedule.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js"],"names":[],"mappings":"AAgBA;;GAEG;AACH,sCAFU,YAAY,
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_schedule.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js"],"names":[],"mappings":"AAgBA;;GAEG;AACH,sCAFU,YAAY,CAaM;AAa5B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,4CAFU,aAAa,CA2CpB;6BA1G0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js
CHANGED
|
@@ -26,6 +26,8 @@ export const PROBE_SCHEDULE_SETTINGS = WebGPUStruct.from({
|
|
|
26
26
|
trace_capacity: u32,
|
|
27
27
|
/** slots kept free beyond the frame's wanted points, ⌈capacity · PROBE_FREE_SLACK⌉ */
|
|
28
28
|
slack: u32,
|
|
29
|
+
/** idle probes the period counts as one waiting, `probe_clipmap_idle_periods`, at least 1 */
|
|
30
|
+
idle_periods: u32,
|
|
29
31
|
}, "ProbeScheduleSettings");
|
|
30
32
|
|
|
31
33
|
const resources = new ShaderResourceSetDescriptor();
|
|
@@ -43,9 +45,11 @@ resources.createGroup()
|
|
|
43
45
|
* Schedule (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3, §8.5): one thread, after admit, when the frame's
|
|
44
46
|
* active list is whole.
|
|
45
47
|
* - The period: with P_w the probes waiting for an update, the NEW and those wanted since their last
|
|
46
|
-
* update,
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* update, P_i the idle, every other live probe, and m `idle_periods`,
|
|
49
|
+
* `T = max(1, ⌈(P_w + P_i / m) / U⌉)` frames. Every probe a want waits on is updated within a period and
|
|
50
|
+
* every idle one within m of them, a frame's updates U at most on average, and the period follows the
|
|
51
|
+
* live count. Retire and admit counted the waiting in `probe_counters[PROBE_COUNTER_WAITING]`, which it
|
|
52
|
+
* empties for the next frame's; the idle are the rest of the frame's active list. The period goes to
|
|
49
53
|
* `probe_counters[PROBE_COUNTER_PERIOD]` for the due passes.
|
|
50
54
|
* - The next frame's eviction, `probe_eviction`: as many slots as the free ones fall short of the frame's
|
|
51
55
|
* wanted points and the slack, the probes wanted longest ago first. Walking retire's age buckets from the
|
|
@@ -73,47 +77,28 @@ export const shader_probe_clipmap_schedule = ComputeShader.from({
|
|
|
73
77
|
`
|
|
74
78
|
@compute @workgroup_size(1)
|
|
75
79
|
fn main() {
|
|
80
|
+
let live = min(probe_active_write.count, settings.capacity);
|
|
76
81
|
let waiting = atomicLoad(&probe_counters[PROBE_COUNTER_WAITING]);
|
|
82
|
+
let idle = live - min(waiting, live);
|
|
83
|
+
let idle_periods = max(settings.idle_periods, 1u);
|
|
77
84
|
let traced = max(settings.trace_capacity, 1u);
|
|
78
85
|
|
|
79
86
|
atomicStore(&probe_counters[PROBE_COUNTER_WAITING], 0u);
|
|
80
|
-
|
|
87
|
+
// ⌈(P_w + P_i / m) / U⌉ in whole numbers
|
|
88
|
+
atomicStore(&probe_counters[PROBE_COUNTER_PERIOD], max(divide_round_up_u32(waiting * idle_periods + idle, traced * idle_periods), 1u));
|
|
81
89
|
|
|
82
90
|
// the slots short of the frame's wanted points and the slack
|
|
83
91
|
let wanted = min(probe_wanted.count, settings.wanted_capacity);
|
|
84
92
|
let room = wanted + settings.slack;
|
|
85
93
|
let free = atomicLoad(&probe_counters[PROBE_COUNTER_FREE]);
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
var buckets = 0u;
|
|
89
|
-
var remaining = 0u;
|
|
90
|
-
|
|
91
|
-
for (var k = 0u; k < PROBE_AGE_BUCKETS; k++) {
|
|
92
|
-
let at = PROBE_COUNTER_AGES + PROBE_AGE_BUCKETS - 1u - k;
|
|
93
|
-
let aged = atomicLoad(&probe_counters[at]);
|
|
94
|
-
|
|
95
|
-
atomicStore(&probe_counters[at], 0u);
|
|
95
|
+
let plan = age_eviction_plan(&probe_counters, PROBE_COUNTER_AGES, select(0u, room - free, room > free));
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (lacking > 0u && aged > 0u) {
|
|
100
|
-
if (aged <= lacking) {
|
|
101
|
-
lacking -= aged;
|
|
102
|
-
buckets = k + 1u;
|
|
103
|
-
} else {
|
|
104
|
-
buckets = k;
|
|
105
|
-
remaining = lacking;
|
|
106
|
-
lacking = 0u;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
probe_eviction.buckets = buckets;
|
|
112
|
-
probe_eviction.remaining = remaining;
|
|
97
|
+
probe_eviction.buckets = plan.x;
|
|
98
|
+
probe_eviction.remaining = plan.y;
|
|
113
99
|
|
|
114
100
|
atomicStore(&probe_counters[PROBE_COUNTER_EVICTED], 0u);
|
|
115
101
|
|
|
116
|
-
let live = min(probe_active_write.count, settings.capacity);
|
|
117
102
|
let folded = folded_dispatch(divide_round_up_u32(live, PROBE_THREAD_WORKGROUP_SIZE));
|
|
118
103
|
|
|
119
104
|
probe_dispatch[PROBE_DISPATCH_ACTIVE] = folded.x;
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js
CHANGED
|
@@ -110,7 +110,7 @@ fn main(
|
|
|
110
110
|
let cascade = (record.flags >> PROBE_RAY_CASCADE_SHIFT) & PROBE_RAY_CASCADE_MASK;
|
|
111
111
|
|
|
112
112
|
let draw = hash_to_float01(pcg4d(vec4<u32>(probe_trace.elements[k], record.direction, 0x510E527Fu, 0u)).x);
|
|
113
|
-
let surface = probe_clipmap_hit_material_pick(position, normal, cascade, draw);
|
|
113
|
+
let surface = probe_clipmap_hit_material_pick(position, normal, cascade, draw, settings.brick_atlas_shift);
|
|
114
114
|
let direct = rgbe9995_decode(record.light);
|
|
115
115
|
|
|
116
116
|
radiance = surface.emissive + surface.albedo * direct * RECIPROCAL_PI;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader_probe_clipmap_trace.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js"],"names":[],"mappings":"AAkDA;;GAEG;AACH,mCAFU,YAAY,
|
|
1
|
+
{"version":3,"file":"shader_probe_clipmap_trace.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js"],"names":[],"mappings":"AAkDA;;GAEG;AACH,mCAFU,YAAY,CAiBG;AAsBzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,yCAFU,aAAa,CAuJpB;6BAzP0B,sCAAsC;8BAHrC,kCAAkC"}
|
package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js
CHANGED
|
@@ -64,6 +64,8 @@ export const PROBE_TRACE_SETTINGS = WebGPUStruct.from({
|
|
|
64
64
|
t_max: f32,
|
|
65
65
|
/** updates between a probe's uniform ones, `PROBE_UNIFORM_PERIOD` */
|
|
66
66
|
uniform_period: u32,
|
|
67
|
+
/** the brick atlas's footprint as shifts, `GPUBrickClipmap#atlas_shift` */
|
|
68
|
+
brick_atlas_shift: u32,
|
|
67
69
|
}, "ProbeTraceSettings");
|
|
68
70
|
|
|
69
71
|
const resources = new ShaderResourceSetDescriptor();
|
|
@@ -198,7 +200,7 @@ fn main(
|
|
|
198
200
|
let start = brick_clipmap_start(origin, cascade_count);
|
|
199
201
|
let t_min = brick_levels[min(start, cascade_count - 1u)].cell_size / ${MESH_SDF_BRICK_VOXELS}.0;
|
|
200
202
|
|
|
201
|
-
let hit = brick_clipmap_trace(origin, direction, t_min, settings.t_max, cascade_count);
|
|
203
|
+
let hit = brick_clipmap_trace(origin, direction, t_min, settings.t_max, cascade_count, settings.brick_atlas_shift);
|
|
202
204
|
|
|
203
205
|
let is_hit = hit.kind == BRICK_TRACE_HIT;
|
|
204
206
|
let back_face = is_hit && dot(hit.normal, direction) > 0.0;
|
|
@@ -229,7 +231,7 @@ fn main(
|
|
|
229
231
|
// a point of the disk of its own for each light, apart from the origin's draw
|
|
230
232
|
let hash = pcg3d(vec3<u32>(slot, packed, 0x3C6EF372u + shadowed));
|
|
231
233
|
let toward = cone_sample_direction(-light.direction, light.disk_radius, vec2<f32>(hash_to_float01(hash.x), hash_to_float01(hash.y)));
|
|
232
|
-
let shadow = brick_clipmap_trace(lifted, toward, 0.0, settings.t_max, cascade_count);
|
|
234
|
+
let shadow = brick_clipmap_trace(lifted, toward, 0.0, settings.t_max, cascade_count, settings.brick_atlas_shift);
|
|
233
235
|
|
|
234
236
|
visible = select(0.0, 1.0, shadow.kind == BRICK_TRACE_MISS);
|
|
235
237
|
}
|