@woosh/meep-engine 3.64.1 → 3.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/build/bundle-worker-terrain.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/binary/BinaryBuffer.d.ts +5 -0
  6. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  7. package/src/core/binary/BinaryBuffer.js +39 -5
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
  10. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
  11. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
  12. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
  13. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
  14. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
  15. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
  16. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
  17. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
  19. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
  20. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
  21. package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
  22. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
  23. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
  25. package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
  26. package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
  28. package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
  29. package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
  30. package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
  31. package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
  32. package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
  33. package/src/engine/graphics3/GroundCoverSystem.js +58 -0
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +372 -110
  36. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  37. package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
  40. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  41. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
  42. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
  43. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  44. package/src/engine/network/sim/SimActionExecutor.js +65 -9
  45. package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
  46. package/src/engine/network/state/PredictionHistory.js +6 -1
  47. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
  48. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
  49. package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
  50. package/src/engine/network/time/RenderPlayout.d.ts +23 -3
  51. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  52. package/src/engine/network/time/RenderPlayout.js +40 -4
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
  55. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
  56. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
  57. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  58. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  59. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  60. package/src/shade/playground/grass_surfaces/index.html +75 -0
  61. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  62. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  63. package/src/shade/playground/grass_surfaces/main.js +593 -0
  64. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  65. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  66. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  67. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  68. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  69. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  70. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  71. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  72. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  73. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  74. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  75. package/src/shade/renderer/Renderer.js +47 -43
  76. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  77. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  78. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  79. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  80. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  81. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  82. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  83. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  84. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  88. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  89. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  91. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  92. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  103. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  104. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  106. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  108. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  110. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  113. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  115. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  168. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  169. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  170. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  171. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  172. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  173. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  174. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  175. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  176. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  177. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  178. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  179. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  180. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  181. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  182. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  183. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  184. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  185. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  186. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  187. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  188. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  189. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  190. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  191. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  192. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  193. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  194. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  195. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  196. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  197. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  198. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  199. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  200. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  201. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  202. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  203. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  204. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  205. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  206. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  207. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  208. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  209. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  210. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  211. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  212. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  213. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  214. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  215. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  216. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  217. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  218. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  219. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  220. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  221. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  222. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  223. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  224. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  225. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  226. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  227. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  228. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  229. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  230. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  231. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  232. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  233. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  234. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  235. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  236. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  237. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  238. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  239. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  240. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  241. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  242. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  243. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  244. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  245. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  246. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  247. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  248. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  249. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  250. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  251. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  252. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  253. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  254. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  255. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  256. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  257. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  258. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  259. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  260. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  261. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  262. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  263. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  264. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  265. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  266. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  267. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  268. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  269. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  270. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  271. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  272. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  273. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  274. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  275. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  276. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  277. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  278. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  280. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  281. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  282. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  283. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  284. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  285. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  286. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  287. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  288. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  289. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  290. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  291. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  292. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  293. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  294. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  295. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  296. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  297. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  298. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  299. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  300. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  301. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  302. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  303. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  304. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  305. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  306. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  307. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  308. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  309. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  310. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  311. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  312. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  313. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  314. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  315. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  316. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  317. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  319. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  320. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  321. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  322. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
@@ -3,11 +3,13 @@ import { PROBE_WANT_TILE, PROBE_WANT_WORKGROUP_TILES } from "./PROBE_CLIPMAP.js"
3
3
  import { shader_probe_clipmap_want } from "./shader_probe_clipmap_want.js";
4
4
 
5
5
  /**
6
- * A clipmap's probes wanted by the frame's pixels (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): one pixel of
7
- * each screen tile wants the cages its pick reads (`shader_probe_clipmap_want`). The wants of the frustum's
8
- * probes; a {@link GPUProbeClipmap} records them in its lifetime, between retire and admit.
6
+ * A clipmap's probes wanted by the pixels of a screen surface (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3): one
7
+ * pixel of each screen tile wants the cages its pick reads (`shader_probe_clipmap_want`).
9
8
  *
10
- * Give it the frame's G-buffer with {@link set} before the clipmap's `graph_update`.
9
+ * The frame's G-buffer is the frustum's probes' own wants, which a {@link GPUProbeClipmap} records in its
10
+ * lifetime, between retire and admit: give it the G-buffer with {@link set} before the clipmap's
11
+ * `graph_update`. A surface drawn apart from the G-buffer, whose reader picks probes per pixel, is another
12
+ * one's, encoded once that surface is drawn into what `GPUProbeClipmap.write_want_bindings` binds.
11
13
  */
12
14
  export class ProbeClipmapScreenWants {
13
15
  #depth = -1;
@@ -20,32 +22,48 @@ export class ProbeClipmapScreenWants {
20
22
 
21
23
  #groups = [0, 0];
22
24
 
25
+ #normal_channel = 0;
26
+
27
+ #two_sided = false;
28
+
29
+ /** The wanting clipmap's settings and how this surface's normals are read. */
30
+ #settings = { cascade_count: 0, resolution: 0, frame: 0, wanted_capacity: 0, anchor: null, select_half: 0, normal_channel: 0, two_sided: 0 };
31
+
23
32
  #tiles = 0;
24
33
 
25
34
  #bindings = {};
26
35
 
27
36
  /**
28
- * The frame's G-buffer and view.
37
+ * The frame's surface and view.
29
38
  *
30
39
  * @param {Object} options
31
- * @param {number} options.depth graph handle of the frame's depth
32
- * @param {number} options.normal graph handle of the G-buffer's normals
40
+ * @param {number} options.depth graph handle of the surface's reverse-Z depth, zero where it has none
41
+ * @param {number} options.normal graph handle of its normals, a `uint` texture: a channel holds a normal
42
+ * octahedral, as the G-buffer packs its own
33
43
  * @param {GPUBuffer} options.camera the view's camera uniform
34
44
  * @param {*} options.stbn the 2-channel spatio-temporal blue noise, `STATIC_GRAPHICS_ENGINE_ASSETS.stbn_vec2`
35
- * @param {ArrayLike<number>} options.resolution the frame's pixels, x and y
45
+ * @param {ArrayLike<number>} options.resolution the surface's pixels, x and y
46
+ * @param {number} [options.normal_channel] the channel that holds the normal, 0 to 3: the G-buffer's is 0
47
+ * @param {boolean} [options.two_sided] whether the surface's reader turns a normal that faces away from the eye
48
+ * to face it, as the reader of a surface seen from both sides does
36
49
  */
37
- set({ depth, normal, camera, stbn, resolution }) {
50
+ set({ depth, normal, camera, stbn, resolution, normal_channel = 0, two_sided = false }) {
38
51
  assert.isNonNegativeInteger(depth, 'depth');
39
52
  assert.isNonNegativeInteger(normal, 'normal');
40
53
  assert.defined(camera, 'camera');
41
54
  assert.defined(stbn, 'stbn');
42
55
  assert.isPositiveInteger(resolution[0], 'resolution[0]');
43
56
  assert.isPositiveInteger(resolution[1], 'resolution[1]');
57
+ assert.isNonNegativeInteger(normal_channel, 'normal_channel');
58
+ assert.lessThan(normal_channel, 4, 'normal_channel');
59
+ assert.isBoolean(two_sided, 'two_sided');
44
60
 
45
61
  this.#depth = depth;
46
62
  this.#normal = normal;
47
63
  this.#camera = camera;
48
64
  this.#stbn = stbn;
65
+ this.#normal_channel = normal_channel;
66
+ this.#two_sided = two_sided;
49
67
 
50
68
  const tiles_x = Math.ceil(resolution[0] / PROBE_WANT_TILE);
51
69
  const tiles_y = Math.ceil(resolution[1] / PROBE_WANT_TILE);
@@ -64,7 +82,7 @@ export class ProbeClipmapScreenWants {
64
82
  }
65
83
 
66
84
  /**
67
- * Declare what the wants read on the lifetime's pass.
85
+ * Declare what the wants read on the pass that encodes them.
68
86
  *
69
87
  * @param {import("../../../../../engine/graphics/render/frame_graph/FramePassBuilder.js").FramePassBuilder} pass
70
88
  * @param {Object} data the pass's data, which {@link encode} is given back
@@ -78,13 +96,19 @@ export class ProbeClipmapScreenWants {
78
96
 
79
97
  /**
80
98
  * @param {GPUCommandEncoder} encoder
81
- * @param {Object} data the lifetime pass's data
99
+ * @param {Object} data the encoding pass's data
82
100
  * @param {*} resources the frame graph's resources
83
101
  * @param {Object} clipmap what the wanting clipmap binds: `probe_levels`, `probe_wanted`,
84
102
  * `probe_wanted_bits` and its want settings as `settings`
85
103
  */
86
104
  encode(encoder, data, resources, clipmap) {
87
105
  const b = Object.assign(this.#bindings, clipmap);
106
+ const settings = Object.assign(this.#settings, clipmap.settings);
107
+
108
+ settings.normal_channel = this.#normal_channel;
109
+ settings.two_sided = this.#two_sided ? 1 : 0;
110
+
111
+ b.settings = settings;
88
112
 
89
113
  b.gBufferDepth = resources.get(data.want_depth);
90
114
  b.gBufferNormals = resources.get(data.want_normal);
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_probe_clipmap.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chunk_probe_clipmap.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { chunk_age_eviction } from "../../../gpu_primitive/age_eviction/chunk_age_eviction.js";
1
2
  import { COLLECTION_U32_STRUCT_READ } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
2
3
  import { COLLECTION_U32_STRUCT_WRITE } from "../../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
3
4
  import { chunk_clipmap_key } from "../../../shader/chunk/clipmap/chunk_clipmap_key.js";
@@ -616,7 +617,7 @@ fn probe_state(kind: u32, updates: u32) -> u32 {
616
617
  }
617
618
 
618
619
  fn probe_clipmap_age_bucket(age: u32) -> u32 {
619
- return min(32u - countLeadingZeros(age), PROBE_AGE_BUCKETS - 1u);
620
+ return age_eviction_bucket(age);
620
621
  }
621
622
 
622
623
  fn probe_record_flags(back_face: f32, cascade: u32) -> u32 {
@@ -661,6 +662,7 @@ fn probe_clipmap_offset_decode(word: u32, spacing: f32) -> vec3<f32> {
661
662
  return vec3<f32>(steps) * (${PROBE_RELOCATION_LIMIT} * spacing / 511.0);
662
663
  }
663
664
  `, [
665
+ chunk_age_eviction,
664
666
  PROBE_RECORD_STRUCT.declaration_chunk,
665
667
  chunk_brick4_sh3_color_pack,
666
668
  chunk_brick4_sh3_color_unpack,
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The cages a reader anywhere inside a world box can read (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3, §9.1), for
3
+ * a want that knows its readers by their bounds alone: a meshlet's, whose fragments pick probes.
4
+ *
5
+ * ```wgsl
6
+ * struct ProbeClipmapBoxCages { first: vec3<i32>, dims: vec3<u32> }
7
+ * fn probe_clipmap_box_cascades(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> vec2<u32>
8
+ * fn probe_clipmap_box_cages(box_min: vec3<f32>, box_max: vec3<f32>, cascade: u32, anchor: vec3<f32>, select_half: f32) -> ProbeClipmapBoxCages
9
+ * fn probe_clipmap_box_cage_count(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> u32
10
+ * fn probe_clipmap_cage_is_read(cascade: u32, cage: vec3<i32>, anchor: vec3<f32>, select_half: f32) -> bool
11
+ * fn probe_clipmap_cage_meets_box(cascade: u32, cage: vec3<i32>, local_min: vec3<f32>, local_max: vec3<f32>, transform: mat4x4<f32>) -> bool
12
+ * ```
13
+ *
14
+ * A reader at p reads the cage of p moved by at most {@link PROBE_RECEIVER_BIAS} of a spacing, in the cascade
15
+ * `probe_clipmap_select_in` answers for p and, in its blend skirt, in the next. So over a box:
16
+ *
17
+ * - `probe_clipmap_box_cascades`: the cascades its points can read, the first and one past the last, equal
18
+ * where the box lies outside every selection box. From the cascade its point nearest the anchor selects to
19
+ * the one its farthest does, and one more where the farthest lies in that one's skirt.
20
+ * - `probe_clipmap_box_cages`: in one of those, the block of cages such a reader can read: those of the box's
21
+ * part inside the cascade's selection box, grown by the bias, and kept to the cascade's cage window. `dims`
22
+ * holds a zero where there is none.
23
+ * - `probe_clipmap_box_cage_count`: the cages of every block.
24
+ *
25
+ * The blocks are a superset of what any surface inside the box reads. Two tests a thread a cage can afford
26
+ * narrow them, each still a superset:
27
+ *
28
+ * - `probe_clipmap_cage_is_read`: whether a point within the bias of the cage selects its cascade, or the
29
+ * finer one in its skirt; a block holds cages no point reads where its box crosses a selection box's face.
30
+ * - `probe_clipmap_cage_meets_box`: whether the cage, grown by the bias, meets the box as it lies in its own
31
+ * space, by its three axes: a flat box turned away from the world's axes fills its world box with cages
32
+ * it never crosses.
33
+ *
34
+ * Reads `probe_levels`.
35
+ *
36
+ * @type {CodeChunk}
37
+ */
38
+ export const chunk_probe_clipmap_box_cages: CodeChunk;
39
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
40
+ //# sourceMappingURL=chunk_probe_clipmap_box_cages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_probe_clipmap_box_cages.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,4CAFU,SAAS,CAmIZ;0BA1KmB,uCAAuC"}
@@ -0,0 +1,174 @@
1
+ import { CLIPMAP_LEVEL_LIMIT, CLIPMAP_LEVEL_STRUCT } from "../../../shader/chunk/clipmap/CLIPMAP_LEVEL_STRUCT.js";
2
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
3
+ import { chunk_probe_clipmap, PROBE_LEVELS_RESOURCE } from "./chunk_probe_clipmap.js";
4
+ import { PROBE_RECEIVER_BIAS } from "./PROBE_CLIPMAP.js";
5
+
6
+ /**
7
+ * The cages a reader anywhere inside a world box can read (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §8.3, §9.1), for
8
+ * a want that knows its readers by their bounds alone: a meshlet's, whose fragments pick probes.
9
+ *
10
+ * ```wgsl
11
+ * struct ProbeClipmapBoxCages { first: vec3<i32>, dims: vec3<u32> }
12
+ * fn probe_clipmap_box_cascades(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> vec2<u32>
13
+ * fn probe_clipmap_box_cages(box_min: vec3<f32>, box_max: vec3<f32>, cascade: u32, anchor: vec3<f32>, select_half: f32) -> ProbeClipmapBoxCages
14
+ * fn probe_clipmap_box_cage_count(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> u32
15
+ * fn probe_clipmap_cage_is_read(cascade: u32, cage: vec3<i32>, anchor: vec3<f32>, select_half: f32) -> bool
16
+ * fn probe_clipmap_cage_meets_box(cascade: u32, cage: vec3<i32>, local_min: vec3<f32>, local_max: vec3<f32>, transform: mat4x4<f32>) -> bool
17
+ * ```
18
+ *
19
+ * A reader at p reads the cage of p moved by at most {@link PROBE_RECEIVER_BIAS} of a spacing, in the cascade
20
+ * `probe_clipmap_select_in` answers for p and, in its blend skirt, in the next. So over a box:
21
+ *
22
+ * - `probe_clipmap_box_cascades`: the cascades its points can read, the first and one past the last, equal
23
+ * where the box lies outside every selection box. From the cascade its point nearest the anchor selects to
24
+ * the one its farthest does, and one more where the farthest lies in that one's skirt.
25
+ * - `probe_clipmap_box_cages`: in one of those, the block of cages such a reader can read: those of the box's
26
+ * part inside the cascade's selection box, grown by the bias, and kept to the cascade's cage window. `dims`
27
+ * holds a zero where there is none.
28
+ * - `probe_clipmap_box_cage_count`: the cages of every block.
29
+ *
30
+ * The blocks are a superset of what any surface inside the box reads. Two tests a thread a cage can afford
31
+ * narrow them, each still a superset:
32
+ *
33
+ * - `probe_clipmap_cage_is_read`: whether a point within the bias of the cage selects its cascade, or the
34
+ * finer one in its skirt; a block holds cages no point reads where its box crosses a selection box's face.
35
+ * - `probe_clipmap_cage_meets_box`: whether the cage, grown by the bias, meets the box as it lies in its own
36
+ * space, by its three axes: a flat box turned away from the world's axes fills its world box with cages
37
+ * it never crosses.
38
+ *
39
+ * Reads `probe_levels`.
40
+ *
41
+ * @type {CodeChunk}
42
+ */
43
+ export const chunk_probe_clipmap_box_cages = CodeChunk.from(
44
+ //language=WGSL
45
+ `
46
+ struct ProbeClipmapBoxCages {
47
+ // the least cage of the block
48
+ first: vec3<i32>,
49
+ // its cages along each axis
50
+ dims: vec3<u32>,
51
+ }
52
+
53
+ fn probe_clipmap_box_max3(v: vec3<f32>) -> f32 {
54
+ return max(max(v.x, v.y), v.z);
55
+ }
56
+
57
+ // the finest cascade whose selection box holds a point \`reach\` from the anchor along its longest axis, or the count
58
+ fn probe_clipmap_cascade_at_reach(reach: f32, cascade_count: u32, select_half: f32) -> u32 {
59
+ for (var i = 0u; i < ${CLIPMAP_LEVEL_LIMIT}u; i++) {
60
+ if (i >= cascade_count) {
61
+ break;
62
+ }
63
+
64
+ if (select_half * probe_levels[i].cell_size >= reach) {
65
+ return i;
66
+ }
67
+ }
68
+
69
+ return cascade_count;
70
+ }
71
+
72
+ fn probe_clipmap_box_cascades(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> vec2<u32> {
73
+ let reach_near = probe_clipmap_box_max3(abs(clamp(anchor, box_min, box_max) - anchor));
74
+ let reach_far = probe_clipmap_box_max3(max(abs(box_min - anchor), abs(box_max - anchor)));
75
+
76
+ let first = probe_clipmap_cascade_at_reach(reach_near, cascade_count, select_half);
77
+
78
+ if (first >= cascade_count) {
79
+ return vec2<u32>(cascade_count);
80
+ }
81
+
82
+ let last = min(probe_clipmap_cascade_at_reach(reach_far, cascade_count, select_half), cascade_count - 1u);
83
+ // past the last one's skirt line its farthest points read the next as well
84
+ let skirt = reach_far > (select_half - PROBE_BLEND_SKIRT) * probe_levels[last].cell_size;
85
+
86
+ return vec2<u32>(first, min(last + select(1u, 2u, skirt), cascade_count));
87
+ }
88
+
89
+ fn probe_clipmap_box_cages(box_min: vec3<f32>, box_max: vec3<f32>, cascade: u32, anchor: vec3<f32>, select_half: f32) -> ProbeClipmapBoxCages {
90
+ let level = probe_levels[cascade];
91
+ let cell = level.cell_size;
92
+ let bias = ${PROBE_RECEIVER_BIAS} * cell;
93
+
94
+ // the box's part whose points select this cascade or a finer one
95
+ let half = vec3<f32>(select_half * cell);
96
+ let a = max(box_min, anchor - half);
97
+ let b = min(box_max, anchor + half);
98
+
99
+ // their cages, the bias either way, inside the cage window
100
+ let first = max(vec3<i32>(floor((a - bias) / cell)), level.corner);
101
+ let last = min(vec3<i32>(floor((b + bias) / cell)), level.corner + level.size - vec3<i32>(1));
102
+
103
+ var out: ProbeClipmapBoxCages;
104
+
105
+ out.first = first;
106
+ out.dims = vec3<u32>(max(last - first + vec3<i32>(1), vec3<i32>(0)));
107
+
108
+ if (any(a > b)) {
109
+ out.dims = vec3<u32>(0u);
110
+ }
111
+
112
+ return out;
113
+ }
114
+
115
+ fn probe_clipmap_box_cage_count(box_min: vec3<f32>, box_max: vec3<f32>, cascade_count: u32, anchor: vec3<f32>, select_half: f32) -> u32 {
116
+ let cascades = probe_clipmap_box_cascades(box_min, box_max, cascade_count, anchor, select_half);
117
+
118
+ var count = 0u;
119
+
120
+ for (var i = 0u; i < ${CLIPMAP_LEVEL_LIMIT}u; i++) {
121
+ let cascade = cascades.x + i;
122
+
123
+ if (cascade >= cascades.y) {
124
+ break;
125
+ }
126
+
127
+ let cages = probe_clipmap_box_cages(box_min, box_max, cascade, anchor, select_half);
128
+
129
+ count += cages.dims.x * cages.dims.y * cages.dims.z;
130
+ }
131
+
132
+ return count;
133
+ }
134
+
135
+ fn probe_clipmap_cage_is_read(cascade: u32, cage: vec3<i32>, anchor: vec3<f32>, select_half: f32) -> bool {
136
+ let cell = probe_levels[cascade].cell_size;
137
+ // the points that read the cage lie within the bias of it
138
+ let half = (0.5 + ${PROBE_RECEIVER_BIAS}) * cell;
139
+ let from_anchor = abs((vec3<f32>(cage) + 0.5) * cell - anchor);
140
+
141
+ // one of them selects this cascade or a finer one
142
+ var read = probe_clipmap_box_max3(max(from_anchor - half, vec3<f32>(0.0))) <= select_half * cell;
143
+
144
+ if (cascade > 0u) {
145
+ // and not every one selects a finer one short of its skirt
146
+ read = read && probe_clipmap_box_max3(from_anchor + half) > (select_half - PROBE_BLEND_SKIRT) * probe_levels[cascade - 1u].cell_size;
147
+ }
148
+
149
+ return read;
150
+ }
151
+
152
+ fn probe_clipmap_cage_meets_box(cascade: u32, cage: vec3<i32>, local_min: vec3<f32>, local_max: vec3<f32>, transform: mat4x4<f32>) -> bool {
153
+ let cell = probe_levels[cascade].cell_size;
154
+ let half = (0.5 + ${PROBE_RECEIVER_BIAS}) * cell;
155
+ let local_half = 0.5 * (local_max - local_min);
156
+ let offset = (vec3<f32>(cage) + 0.5) * cell - (transform * vec4<f32>(0.5 * (local_min + local_max), 1.0)).xyz;
157
+
158
+ // each of the box's own axes by name: a dynamic index would put the matrix in local memory
159
+ let x = transform[0].xyz;
160
+ let y = transform[1].xyz;
161
+ let z = transform[2].xyz;
162
+
163
+ // along an axis, the cage's reach and the box's, against how far apart their centres are: the axis is
164
+ // left at the transform's scale, which every term carries
165
+ return abs(dot(offset, x)) <= half * (abs(x.x) + abs(x.y) + abs(x.z)) + local_half.x * dot(x, x)
166
+ && abs(dot(offset, y)) <= half * (abs(y.x) + abs(y.y) + abs(y.z)) + local_half.y * dot(y, y)
167
+ && abs(dot(offset, z)) <= half * (abs(z.x) + abs(z.y) + abs(z.z)) + local_half.z * dot(z, z);
168
+ }
169
+ `, [
170
+ chunk_probe_clipmap,
171
+ CLIPMAP_LEVEL_STRUCT.declaration_chunk,
172
+ ]);
173
+
174
+ chunk_probe_clipmap_box_cages.requireResource(PROBE_LEVELS_RESOURCE);
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * ```wgsl
5
5
  * struct ProbeClipmapHitMaterial { found: bool, albedo: vec3<f32>, emissive: vec3<f32> }
6
- * fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> ProbeClipmapHitMaterial
6
+ * fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> ProbeClipmapHitMaterial
7
7
  * ```
8
8
  *
9
9
  * The hit is at `position` in brick cascade `cascade`, its field's normal `normal`: the brick holding it,
10
10
  * looked up in the brick map at the hit's cascade as the march found it, and its material there
11
11
  * (`brick_material_surface`), albedo and emissive. A hit whose brick carries no material for its surface
12
- * is black, `found` false.
12
+ * is black, `found` false. `atlas_shift` is the brick atlas's footprint, as `chunk_brick_clipmap_sample` takes it.
13
13
  *
14
14
  * @type {CodeChunk}
15
15
  */
@@ -18,7 +18,7 @@ export const chunk_probe_clipmap_hit_material: CodeChunk;
18
18
  * The material a probe ray's hit takes its light with, from one texel of the brick material:
19
19
  *
20
20
  * ```wgsl
21
- * fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32) -> ProbeClipmapHitMaterial
21
+ * fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32, atlas_shift: u32) -> ProbeClipmapHitMaterial
22
22
  * ```
23
23
  *
24
24
  * As {@link chunk_probe_clipmap_hit_material} finds the hit's brick, one of the texels its blend weighs
@@ -33,7 +33,7 @@ export const chunk_probe_clipmap_hit_material_pick: CodeChunk;
33
33
  * surface, for the debug views: the GI's light takes none of it yet.
34
34
  *
35
35
  * ```wgsl
36
- * fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> vec3<f32> // (metalness, roughness, 1 if found)
36
+ * fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> vec3<f32> // (metalness, roughness, 1 if found)
37
37
  * ```
38
38
  *
39
39
  * @type {CodeChunk}
@@ -48,26 +48,26 @@ brick_at.requireResource(BRICK_MAP_TEXTURE_RESOURCE);
48
48
  *
49
49
  * ```wgsl
50
50
  * struct ProbeClipmapHitMaterial { found: bool, albedo: vec3<f32>, emissive: vec3<f32> }
51
- * fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> ProbeClipmapHitMaterial
51
+ * fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> ProbeClipmapHitMaterial
52
52
  * ```
53
53
  *
54
54
  * The hit is at `position` in brick cascade `cascade`, its field's normal `normal`: the brick holding it,
55
55
  * looked up in the brick map at the hit's cascade as the march found it, and its material there
56
56
  * (`brick_material_surface`), albedo and emissive. A hit whose brick carries no material for its surface
57
- * is black, `found` false.
57
+ * is black, `found` false. `atlas_shift` is the brick atlas's footprint, as `chunk_brick_clipmap_sample` takes it.
58
58
  *
59
59
  * @type {CodeChunk}
60
60
  */
61
61
  export const chunk_probe_clipmap_hit_material = CodeChunk.from(
62
62
  //language=WGSL
63
63
  `
64
- fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> ProbeClipmapHitMaterial {
64
+ fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> ProbeClipmapHitMaterial {
65
65
  var out: ProbeClipmapHitMaterial;
66
66
 
67
67
  let brick = probe_clipmap_hit_brick(position, cascade);
68
68
 
69
69
  if (brick_clipmap_entry_holds_slot(brick.entry)) {
70
- let seen = brick_material_surface(brick.entry, brick.local, normal);
70
+ let seen = brick_material_surface(brick.entry, brick.local, normal, atlas_shift);
71
71
 
72
72
  out.found = seen.found;
73
73
  out.albedo = seen.albedo;
@@ -82,7 +82,7 @@ fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u
82
82
  * The material a probe ray's hit takes its light with, from one texel of the brick material:
83
83
  *
84
84
  * ```wgsl
85
- * fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32) -> ProbeClipmapHitMaterial
85
+ * fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32, atlas_shift: u32) -> ProbeClipmapHitMaterial
86
86
  * ```
87
87
  *
88
88
  * As {@link chunk_probe_clipmap_hit_material} finds the hit's brick, one of the texels its blend weighs
@@ -94,13 +94,13 @@ fn probe_clipmap_hit_material(position: vec3<f32>, normal: vec3<f32>, cascade: u
94
94
  export const chunk_probe_clipmap_hit_material_pick = CodeChunk.from(
95
95
  //language=WGSL
96
96
  `
97
- fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32) -> ProbeClipmapHitMaterial {
97
+ fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, cascade: u32, u: f32, atlas_shift: u32) -> ProbeClipmapHitMaterial {
98
98
  var out: ProbeClipmapHitMaterial;
99
99
 
100
100
  let brick = probe_clipmap_hit_brick(position, cascade);
101
101
 
102
102
  if (brick_clipmap_entry_holds_slot(brick.entry)) {
103
- let seen = brick_material_surface_pick(brick.entry, brick.local, normal, u);
103
+ let seen = brick_material_surface_pick(brick.entry, brick.local, normal, u, atlas_shift);
104
104
 
105
105
  out.found = seen.found;
106
106
  out.albedo = seen.albedo;
@@ -116,7 +116,7 @@ fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, casca
116
116
  * surface, for the debug views: the GI's light takes none of it yet.
117
117
  *
118
118
  * ```wgsl
119
- * fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> vec3<f32> // (metalness, roughness, 1 if found)
119
+ * fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> vec3<f32> // (metalness, roughness, 1 if found)
120
120
  * ```
121
121
  *
122
122
  * @type {CodeChunk}
@@ -124,14 +124,14 @@ fn probe_clipmap_hit_material_pick(position: vec3<f32>, normal: vec3<f32>, casca
124
124
  export const chunk_probe_clipmap_hit_metal_rough = CodeChunk.from(
125
125
  //language=WGSL
126
126
  `
127
- fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32) -> vec3<f32> {
127
+ fn probe_clipmap_hit_metal_rough(position: vec3<f32>, normal: vec3<f32>, cascade: u32, atlas_shift: u32) -> vec3<f32> {
128
128
  let brick = probe_clipmap_hit_brick(position, cascade);
129
129
 
130
130
  if (!brick_clipmap_entry_holds_slot(brick.entry)) {
131
131
  return vec3<f32>(0.0);
132
132
  }
133
133
 
134
- let seen = brick_material_metal_rough(brick.entry, brick.local, normal);
134
+ let seen = brick_material_metal_rough(brick.entry, brick.local, normal, atlas_shift);
135
135
 
136
136
  return vec3<f32>(seen.metal_rough, select(0.0, 1.0, seen.found));
137
137
  }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A one-step sphere parallax for a probe's radiance tap (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §9.3, "Parallax
3
+ * correction"): the direction along which a probe sees what a ray from another point reaches.
4
+ *
5
+ * ```wgsl
6
+ * fn probe_clipmap_parallax(slot: u32, probe: vec3<f32>, spacing: f32, position: vec3<f32>, direction: vec3<f32>) -> vec3<f32>
7
+ * ```
8
+ *
9
+ * - `probe` is where the slot's probe stands, `spacing` its cascade's; `direction` is unit.
10
+ * - The ray from `position` along `direction` is met with a sphere about the probe whose radius is the probe's
11
+ * mean depth along `direction`, one bilinear tap of its depth tile. The far root is taken, so a point inside
12
+ * the sphere always meets it. The result is the unit direction from the probe to where they meet.
13
+ * - Where the ray misses the sphere, or meets it only behind the point, the result is `direction`.
14
+ *
15
+ * **Misses.** The depth is the visibility's (§8.2): a ray that missed, and a hit further than
16
+ * `PROBE_DEPTH_LIMIT` spacings, are both stored as the limit. The sphere therefore never stands further than
17
+ * the limit, and whatever lies past it, the sky included, is taken to be that near. A point a distance d from
18
+ * the probe has its direction toward such a thing turned by up to asin(d / (limit · spacing)), where the right
19
+ * turn for the sky is none. The probes of a cage each turn by their own angle, so their taps of one distant
20
+ * thing land on different texels. The depth cannot tell a miss from a hit at the limit, and its two moments say
21
+ * what share of a texel's rays went past the limit but not how far: a parallax that is right past the limit
22
+ * needs a distance the probe does not store.
23
+ *
24
+ * `probe_clipmap_sample_radiance` does not take this parallax, for that reason: it taps along the lobe. The
25
+ * chunk is kept for a reader whose probes see nothing past the limit.
26
+ *
27
+ * @type {CodeChunk}
28
+ */
29
+ export const chunk_probe_clipmap_parallax: CodeChunk;
30
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
31
+ //# sourceMappingURL=chunk_probe_clipmap_parallax.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_probe_clipmap_parallax.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,2CAFU,SAAS,CAwBZ;0BArDmB,uCAAuC"}
@@ -0,0 +1,54 @@
1
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
2
+ import { chunk_probe_clipmap_pick } from "./chunk_probe_clipmap_pick.js";
3
+
4
+ /**
5
+ * A one-step sphere parallax for a probe's radiance tap (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §9.3, "Parallax
6
+ * correction"): the direction along which a probe sees what a ray from another point reaches.
7
+ *
8
+ * ```wgsl
9
+ * fn probe_clipmap_parallax(slot: u32, probe: vec3<f32>, spacing: f32, position: vec3<f32>, direction: vec3<f32>) -> vec3<f32>
10
+ * ```
11
+ *
12
+ * - `probe` is where the slot's probe stands, `spacing` its cascade's; `direction` is unit.
13
+ * - The ray from `position` along `direction` is met with a sphere about the probe whose radius is the probe's
14
+ * mean depth along `direction`, one bilinear tap of its depth tile. The far root is taken, so a point inside
15
+ * the sphere always meets it. The result is the unit direction from the probe to where they meet.
16
+ * - Where the ray misses the sphere, or meets it only behind the point, the result is `direction`.
17
+ *
18
+ * **Misses.** The depth is the visibility's (§8.2): a ray that missed, and a hit further than
19
+ * `PROBE_DEPTH_LIMIT` spacings, are both stored as the limit. The sphere therefore never stands further than
20
+ * the limit, and whatever lies past it, the sky included, is taken to be that near. A point a distance d from
21
+ * the probe has its direction toward such a thing turned by up to asin(d / (limit · spacing)), where the right
22
+ * turn for the sky is none. The probes of a cage each turn by their own angle, so their taps of one distant
23
+ * thing land on different texels. The depth cannot tell a miss from a hit at the limit, and its two moments say
24
+ * what share of a texel's rays went past the limit but not how far: a parallax that is right past the limit
25
+ * needs a distance the probe does not store.
26
+ *
27
+ * `probe_clipmap_sample_radiance` does not take this parallax, for that reason: it taps along the lobe. The
28
+ * chunk is kept for a reader whose probes see nothing past the limit.
29
+ *
30
+ * @type {CodeChunk}
31
+ */
32
+ export const chunk_probe_clipmap_parallax = CodeChunk.from(
33
+ //language=WGSL
34
+ `
35
+ fn probe_clipmap_parallax(slot: u32, probe: vec3<f32>, spacing: f32, position: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {
36
+ // a miss reads the limit here, as a hit at the limit does: see the chunk's notes on misses
37
+ let radius = probe_clipmap_depth_moments(slot, direction).x * spacing;
38
+ let origin = position - probe;
39
+ let b = dot(direction, origin);
40
+ let discriminant = b * b - (dot(origin, origin) - radius * radius);
41
+
42
+ if (discriminant >= 0.0) {
43
+ let t = sqrt(discriminant) - b;
44
+
45
+ if (t > 0.0) {
46
+ return normalize(origin + t * direction);
47
+ }
48
+ }
49
+
50
+ return direction;
51
+ }
52
+ `, [
53
+ chunk_probe_clipmap_pick,
54
+ ]);
@@ -13,10 +13,14 @@
13
13
  * picked by, at the visibility it was picked at. The trilinear part cancels.
14
14
  * - **The sample vector** is Lagarde's dominant direction, `normalize(mix(r, n, α))` with r the
15
15
  * reflection of the view and α the roughness squared.
16
- * - **A radiance tap** a probe, along the sample vector after a one-step sphere parallax: the reflected ray
17
- * is met with a sphere about the probe whose radius is its mean depth along the vector. The depth is held
18
- * at the cage's diagonal (§8.2), past which no parallax is taken. One bilinear tap of the tile, through
19
- * its skirt and the depth's sampler.
16
+ * - **A radiance tap** a probe, along the sample vector: one bilinear tap of the tile, through its skirt and
17
+ * the depth's sampler. Every picked probe is tapped along the same direction, as if what it sees there were
18
+ * infinitely far.
19
+ * - **No parallax** is taken toward what a probe sees along the vector. The only distance a probe stores is its
20
+ * visibility depth, where a miss and a hit past `PROBE_DEPTH_LIMIT` both read the limit, so a sphere of
21
+ * that depth turns the taps of the sky and of everything distant, each probe's by its own angle
22
+ * (`chunk_probe_clipmap_parallax`, kept beside this chunk and not linked by it; §9.3, "Parallax
23
+ * correction"). A reflection of something nearer than the limit is therefore placed as if it were far.
20
24
  * - **The rough end** is the probes' SH, mixed by the same shares and resolved for the GGX lobe
21
25
  * (`sh3_color_get_radiance_with_GGX`, as Brick4 resolves its probes). The two are blended by
22
26
  * `roughness_to_mip_ratio`: SH alone from roughness 0.7.
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_probe_clipmap_sample_radiance.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,kDAFU,SAAS,CAmIZ;0BA1KmB,uCAAuC"}
1
+ {"version":3,"file":"chunk_probe_clipmap_sample_radiance.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,kDAFU,SAAS,CAoHZ;0BA/JmB,uCAAuC"}
@@ -41,10 +41,14 @@ import { PROBE_RECEIVER_BIAS_VIEW } from "./PROBE_CLIPMAP.js";
41
41
  * picked by, at the visibility it was picked at. The trilinear part cancels.
42
42
  * - **The sample vector** is Lagarde's dominant direction, `normalize(mix(r, n, α))` with r the
43
43
  * reflection of the view and α the roughness squared.
44
- * - **A radiance tap** a probe, along the sample vector after a one-step sphere parallax: the reflected ray
45
- * is met with a sphere about the probe whose radius is its mean depth along the vector. The depth is held
46
- * at the cage's diagonal (§8.2), past which no parallax is taken. One bilinear tap of the tile, through
47
- * its skirt and the depth's sampler.
44
+ * - **A radiance tap** a probe, along the sample vector: one bilinear tap of the tile, through its skirt and
45
+ * the depth's sampler. Every picked probe is tapped along the same direction, as if what it sees there were
46
+ * infinitely far.
47
+ * - **No parallax** is taken toward what a probe sees along the vector. The only distance a probe stores is its
48
+ * visibility depth, where a miss and a hit past `PROBE_DEPTH_LIMIT` both read the limit, so a sphere of
49
+ * that depth turns the taps of the sky and of everything distant, each probe's by its own angle
50
+ * (`chunk_probe_clipmap_parallax`, kept beside this chunk and not linked by it; §9.3, "Parallax
51
+ * correction"). A reflection of something nearer than the limit is therefore placed as if it were far.
48
52
  * - **The rough end** is the probes' SH, mixed by the same shares and resolved for the GGX lobe
49
53
  * (`sh3_color_get_radiance_with_GGX`, as Brick4 resolves its probes). The two are blended by
50
54
  * `roughness_to_mip_ratio`: SH alone from roughness 0.7.
@@ -97,23 +101,8 @@ fn probe_clipmap_lobe(slot: u32, share: f32, position: vec3<f32>, normal: vec3<f
97
101
  out.weight = share * probe_visibility_weight(toward, lobe, visibility) / probe_visibility_weight(toward, normal, visibility);
98
102
  out.sh = probe_record_sh_decode(record.sh);
99
103
 
100
- // the reflected ray met with a sphere about the probe, its radius the probe's mean depth along the lobe
101
- let radius = probe_clipmap_depth_moments(slot, lobe).x * spacing;
102
- let origin = position - probe;
103
- let b = dot(lobe, origin);
104
- let discriminant = b * b - (dot(origin, origin) - radius * radius);
105
-
106
- var direction = lobe;
107
-
108
- if (discriminant >= 0.0) {
109
- let t = sqrt(discriminant) - b;
110
-
111
- if (t > 0.0) {
112
- direction = normalize(origin + t * lobe);
113
- }
114
- }
115
-
116
- out.radiance = probe_clipmap_radiance(slot, direction).rgb;
104
+ // along the lobe itself: no parallax toward what the probe sees there (chunk_probe_clipmap_parallax, on misses)
105
+ out.radiance = probe_clipmap_radiance(slot, lobe).rgb;
117
106
 
118
107
  return out;
119
108
  }