@woosh/meep-engine 3.60.4 → 3.60.6

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 (419) hide show
  1. package/CHANGELOG.md +2621 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts +11 -0
  63. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  64. package/src/shade/renderer/Renderer.js +50 -6
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  67. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  68. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  69. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  70. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  71. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  72. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +28 -45
  74. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  75. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +111 -119
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +22 -3
  77. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  78. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +84 -3
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts +19 -0
  80. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts.map +1 -0
  81. package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.js +25 -0
  82. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  83. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  84. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  85. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +15 -0
  86. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +38 -0
  88. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  89. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  90. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  91. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  92. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  93. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +28 -59
  94. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -1
  95. package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +84 -789
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +7 -6
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +12 -11
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -2
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -2
  103. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  104. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  106. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  107. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  108. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  109. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  110. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  111. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  112. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  113. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  114. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  115. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  116. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  117. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  118. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  119. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  120. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  121. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  122. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  123. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  124. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  125. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  126. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  127. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  128. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  129. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  130. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  131. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  132. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  133. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  134. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  135. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  136. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  137. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  138. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  139. package/src/shade/renderer/material/GPUMaterialManager.d.ts +11 -1
  140. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  141. package/src/shade/renderer/material/GPUMaterialManager.js +16 -8
  142. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  143. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  144. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  145. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +7 -3
  146. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
  147. package/src/shade/renderer/postprocess/gtao/GTAO.js +26 -13
  148. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts +14 -0
  149. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
  150. package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +196 -68
  151. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  152. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +42 -28
  153. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
  154. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +429 -414
  155. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts +16 -0
  156. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts.map +1 -0
  157. package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.js +156 -0
  158. package/src/shade/renderer/scene/GPUSceneContext.d.ts +2 -2
  159. package/src/shade/renderer/scene/GPUSceneContext.js +5 -5
  160. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  161. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  162. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  163. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  164. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  165. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  166. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  168. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  169. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  170. package/src/shade/renderer/water/shader_water.js +22 -13
  171. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  172. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  173. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  174. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  175. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  176. package/editor/REWORK_PLAN_2026_08.md +0 -692
  177. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  178. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  179. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  180. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  181. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  182. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  183. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  184. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  185. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  186. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  187. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  188. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  189. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  190. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  191. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  192. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  193. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  194. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  195. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  196. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  197. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  198. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  199. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  200. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  201. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  202. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  203. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  204. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  205. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  206. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  207. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  208. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  209. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  210. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  211. package/src/REVIEW_2026_08_06/generation.md +0 -176
  212. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  213. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  214. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  215. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  216. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  217. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  218. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  219. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  220. package/src/REVIEW_2026_08_06/view.md +0 -667
  221. package/src/REVIEW_2026_08_06.md +0 -610
  222. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  223. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  224. package/src/core/bvh8/NOTES.md +0 -63
  225. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  226. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  227. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  228. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  229. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  230. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  231. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  232. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  233. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  234. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  235. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  236. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  237. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  238. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  239. package/src/engine/REVIEW_2026_07_03.md +0 -211
  240. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  241. package/src/engine/control/first-person/DESIGN.md +0 -658
  242. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  243. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  244. package/src/engine/control/first-person/TODO.md +0 -160
  245. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  246. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  247. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  248. package/src/engine/ecs/ik/PLAN.md +0 -179
  249. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  250. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  251. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  252. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  253. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  254. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  255. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  256. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  257. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  258. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  259. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  260. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  261. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  262. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  263. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  264. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  265. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  266. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  267. package/src/engine/physics/cloth/PLAN.md +0 -3056
  268. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  269. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  270. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  271. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  272. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  273. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  274. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  275. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  276. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  277. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  278. package/src/format/image/avif/DECISIONS.md +0 -545
  279. package/src/format/image/jpeg/NOTES.md +0 -3
  280. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  281. package/src/generation/COORDINATES.md +0 -54
  282. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  283. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  284. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  285. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  286. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  287. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  288. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  289. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  290. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  291. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  292. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  293. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  294. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  295. package/src/shade/RENDERER_CONTRACT.md +0 -697
  296. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  297. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  298. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  299. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  300. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  301. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  302. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  303. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  304. package/src/shade/renderer/NOTES.md +0 -78
  305. package/src/shade/renderer/PLAN.md +0 -8
  306. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  307. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  308. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  309. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  310. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  311. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  312. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  313. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  314. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  315. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  316. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  317. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  318. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  319. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  320. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  321. package/src/shade/renderer/camera/orbital/README.md +0 -81
  322. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  323. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  324. package/src/shade/renderer/camera/orbital/index.js +0 -9
  325. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  326. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  327. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  328. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  329. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  330. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  331. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  332. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  333. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  334. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  335. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  336. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  337. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  338. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  339. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  340. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  341. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  342. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  343. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +0 -47
  344. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +0 -1
  345. package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +0 -80
  346. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +0 -16
  347. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +0 -1
  348. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +0 -67
  349. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +0 -17
  350. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +0 -1
  351. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +0 -145
  352. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +0 -12
  353. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +0 -1
  354. package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +0 -105
  355. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  356. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  357. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  358. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  359. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  360. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  361. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  362. package/src/shade/renderer/hiz/NOTES.md +0 -3
  363. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  364. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  365. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  366. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  367. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  368. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  369. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  370. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  371. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  372. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  373. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  374. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  375. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  376. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  377. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  378. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  379. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  380. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  381. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  382. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  383. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  384. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  385. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  386. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  387. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  388. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  389. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  390. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  391. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  392. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  393. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  394. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  395. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  396. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  397. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  398. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  399. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  400. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  401. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  402. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  403. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  404. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  405. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  406. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  407. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  408. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  409. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  410. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  411. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  412. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  413. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  414. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  415. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  416. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  417. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  418. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  419. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,5 +1,10 @@
1
1
  import { DEPTH_STENCIL_FOREGROUND_ONLY } from "../../depth/DEPTH_STENCIL_FOREGROUND_ONLY.js";
2
+ import { chunk_decode_g_buffer_normal } from "../../shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.js";
3
+ import { chunk_encode_g_buffer_normal } from "../../shader/chunk/geometry/normal/chunk_encode_g_buffer_normal.js";
4
+ import { chunk_f16_round_stochastic } from "../../shader/chunk/math/chunk_f16_round_stochastic.js";
2
5
  import { chunk_get_std_dev } from "../../shader/chunk/math/statistics/chunk_get_std_dev.js";
6
+ import { chunk_hash_to_float01 } from "../../shader/chunk/random/chunk_hash_to_float01.js";
7
+ import { chunk_pcg3d } from "../../shader/chunk/random/pcg/chunk_pcg3d.js";
3
8
  import {
4
9
  chunk_texture_sample_catmullrom_hardware_5tap_uv
5
10
  } from "../../shader/chunk/texture/sample/chunk_texture_sample_catmullrom_hardware_5tap_uv.js";
@@ -8,107 +13,174 @@ import { ImageShader } from "../../shader/ImageShader.js";
8
13
  import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
9
14
  import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
10
15
  import { SAMPLER_LINEAR_UPSCALE } from "../../texture/SAMPLER_LINEAR_UPSCALE.js";
11
- import { f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
16
+ import { f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
12
17
  import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
13
18
  import { chunk_taa_velocity_confidence } from "../taa/shader_taa.js";
14
19
  import { chunk_taa_get_velocity } from "../velocity/chunk_taa_get_velocity.js";
15
20
 
16
21
  const AO_REPROJECT_SETTINGS_STRUCT = WebGPUStruct.from({
17
22
  /**
18
- * 1 to blend against the history, 0 to take this frame's moments alone: the first frame, a reset,
19
- * or a frame that does not follow the one the history was written on.
23
+ * 1 to blend against the history, 0 to take this frame's alone: the first frame, a reset, or a frame that
24
+ * does not follow the one the history was written on.
20
25
  */
21
26
  history_validity: f32,
27
+ /**
28
+ * Seeds the stochastic rounding of the history's store, fresh each frame.
29
+ */
30
+ frame_index: u32,
22
31
  });
23
32
 
24
33
  const resources = new ShaderResourceSetDescriptor();
25
34
 
26
- // per-pass, 4 bytes, read-only: immediate data rather than a uniform buffer.
35
+ // per-pass, 8 bytes, read-only: immediate data rather than a uniform buffer.
27
36
  resources.setImmediate("settings", AO_REPROJECT_SETTINGS_STRUCT);
28
37
  resources.createGroup()
29
38
  .addTexture("tInput")
30
39
  .addTexture("tVelocity")
31
40
  .addTexture("tOcclusion")
41
+ .addTexture("tNormal", "uint")
42
+ // last frame's G-buffer normal, at the size last frame was drawn at
43
+ .addTexture("tNormalPrevious", "uint")
32
44
  .addTexture("tHistory","float")
33
45
  .addSampler("sLinear", "filtering", SAMPLER_LINEAR_UPSCALE)
34
46
 
35
47
  const body = CodeChunk.from(
36
48
  //language=WGSL
37
49
  `
38
- fn compute_center_moments(
39
- input_center: vec2<f32>,
50
+ struct NeighbourhoodStatistics {
51
+ // visibility's first two moments
52
+ moments: vec2<f32>,
53
+ // the bend's mean, and the mean of its squared length
54
+ bend: vec3<f32>,
55
+ bend_square: f32,
56
+ }
57
+
58
+ fn compute_center_statistics(
59
+ input_center: vec4<f32>,
40
60
  input_coord: vec2<i32>,
41
61
  input_texture: texture_2d<f32>,
42
- ) -> vec2<f32>{
43
-
62
+ ) -> NeighbourhoodStatistics {
63
+
44
64
  const offsets = array< vec2<i32>, 8 >(
45
65
  vec2( -1, -1 ),
46
66
  vec2( 0, -1 ),
47
- vec2( 1, -1 ),
48
-
49
- vec2( -1, 0 ),
50
- vec2( 1, 0 ),
51
-
67
+ vec2( 1, -1 ),
68
+
69
+ vec2( -1, 0 ),
70
+ vec2( 1, 0 ),
71
+
52
72
  vec2( -1, 1 ),
53
- vec2( 0, 1 ),
54
- vec2( 1, 1 ),
73
+ vec2( 0, 1 ),
74
+ vec2( 1, 1 ),
55
75
  );
56
-
76
+
57
77
  const iteratorMax = 8;
58
78
  const rcp_divider = 1.f / 9.f;
59
79
 
60
80
  var moments = vec2(input_center.x, input_center.x * input_center.x);
61
-
81
+
82
+ var bend = input_center.yzw;
83
+ var bend_square = dot(input_center.yzw, input_center.yzw);
84
+
62
85
  for (var i = 0; i < iteratorMax; i++ ) {
63
86
  let new_st = input_coord + offsets[ i ];
64
87
 
65
- let texel = textureLoad(input_texture, new_st, 0 ).rg;
66
-
88
+ let texel = textureLoad(input_texture, new_st, 0 );
89
+
67
90
  moments += vec2(texel.x, texel.x * texel.x);
91
+ bend += texel.yzw;
92
+ bend_square += dot(texel.yzw, texel.yzw);
68
93
  }
69
-
70
- return moments * rcp_divider;
94
+
95
+ return NeighbourhoodStatistics(moments * rcp_divider, bend * rcp_divider, bend_square * rcp_divider);
96
+ }
97
+
98
+ // A face this far from another is another surface: half a right angle, as UE's Lumen takes it
99
+ // (r.Lumen.ScreenProbeGather.Temporal.NormalThreshold). A tessellated curve's faces sit well inside it, a
100
+ // crease's well outside.
101
+ const SAME_SURFACE_COS = 0.70710678;
102
+
103
+ // 1 where the history texel at tap was written on this texel's surface, by its face normal: last frame's
104
+ fn history_texel_on_surface(tap: vec2<i32>, size: vec2<i32>, face_normal: vec3<f32>) -> f32 {
105
+ let history_face_normal = decode_g_buffer_normal(textureLoad(tNormalPrevious, clamp(tap, vec2(0), size - 1), 0).zw);
106
+
107
+ return select(0.0, 1.0, dot(history_face_normal, face_normal) >= SAME_SURFACE_COS);
108
+ }
109
+
110
+ // The share of the history's bilinear footprint written on this texel's surface, read where the history is, in
111
+ // the previous normal's own grid.
112
+ fn history_surface_agreement(prev_uv: vec2<f32>, face_normal: vec3<f32>) -> f32 {
113
+ let size = vec2<i32>(textureDimensions(tNormalPrevious));
114
+
115
+ let st = prev_uv * vec2<f32>(size) - 0.5;
116
+ let origin = vec2<i32>(floor(st));
117
+ let f = st - floor(st);
118
+
119
+ let weights = vec4(
120
+ (1.0 - f.x) * (1.0 - f.y),
121
+ f.x * (1.0 - f.y),
122
+ (1.0 - f.x) * f.y,
123
+ f.x * f.y,
124
+ );
125
+
126
+ let on_surface = vec4(
127
+ history_texel_on_surface(origin, size, face_normal),
128
+ history_texel_on_surface(origin + vec2(1, 0), size, face_normal),
129
+ history_texel_on_surface(origin + vec2(0, 1), size, face_normal),
130
+ history_texel_on_surface(origin + vec2(1, 1), size, face_normal),
131
+ );
132
+
133
+ return dot(weights, on_surface);
134
+ }
135
+
136
+ struct Output {
137
+ // visibility and the bend, accumulated: next frame's history
138
+ @location(0) history: vec4<f32>,
139
+ // the bent normal, octahedral as the G-buffer's normals are
140
+ @location(1) bent_normal: vec2<u32>,
71
141
  }
72
142
 
73
143
  @fragment
74
144
  fn main(
75
145
  @builtin(position) coord: vec4<f32>,
76
146
  @location(0) uv: vec2<f32>,
77
- ) -> @location(0) vec2<f32> {
147
+ ) -> Output {
78
148
  let screenST = vec2<i32>( coord.xy );
79
-
149
+
80
150
  let resolution = textureDimensions(tInput);
81
-
151
+
82
152
  let occlusion_confidence = textureLoad(tOcclusion, screenST, 0).r;
83
- let current_moments = textureLoad(tInput, screenST, 0).rg;
84
-
153
+ let current = textureLoad(tInput, screenST, 0);
154
+ let encoded_normal = textureLoad(tNormal, screenST, 0);
155
+ let shading_normal = decode_g_buffer_normal(encoded_normal.xy);
156
+
85
157
  // get velocity
86
158
  let velocity = taa_get_velocity( tVelocity, screenST );
87
-
159
+
88
160
  let velocity_confidence = taa_velocity_confidence(velocity);
89
-
90
-
161
+
162
+
91
163
  // prev frame ST
92
164
  let prevFrameScreenST = coord.xy - velocity.xy;
93
-
165
+
94
166
  const MIN_VARIANCE = 0.5f; // under motion
95
167
  const MAX_VARIANCE = 1.2f; // no motion
96
168
 
97
169
  let variance_scale = mix( MIN_VARIANCE, MAX_VARIANCE, velocity_confidence * velocity_confidence ) ;
98
-
99
-
170
+
171
+
100
172
  let history_within_screen = all( prevFrameScreenST >= vec2(0.0) ) && all( prevFrameScreenST < vec2f(resolution )) ;
101
-
102
-
173
+
174
+
103
175
  let confidence = velocity_confidence * occlusion_confidence * select(0.0, 1.0,history_within_screen) * settings.history_validity;
104
176
 
105
-
106
- var output: vec2<f32>;
107
-
177
+
178
+ var resolved: vec4<f32>;
179
+
108
180
  if(
109
181
  confidence <= 0.001
110
182
  ) {
111
- output = current_moments;
183
+ resolved = current;
112
184
  }else{
113
185
 
114
186
  // a uv over this frame's size: the history keeps the size it was written at across a
@@ -116,51 +188,81 @@ fn main(
116
188
  let prev_uv = prevFrameScreenST / vec2<f32>(resolution);
117
189
 
118
190
  let history = texture_sample_catmullrom_hardware_5tap_uv(tHistory, sLinear, prev_uv);
119
- let history_moments = history.rg;
120
191
 
121
192
  // AABB sigma is calibrated against the spatially pre-filtered input.
122
193
  // The small spatial denoise upstream is what makes this clamp meaningful:
123
194
  // it stabilises the neighbourhood so the AABB is a tight, non-jittery
124
195
  // ghosting bound rather than chasing per-frame noise. (Standard
125
196
  // pre-blur-then-clamp pattern from SVGF-style and TAA literature.)
126
- let filtered_center_moments = compute_center_moments( current_moments, screenST, tInput);
197
+ let statistics = compute_center_statistics( current, screenST, tInput);
127
198
 
128
- let sigma = get_std_dev(filtered_center_moments.x, filtered_center_moments.y) * variance_scale;
199
+ let sigma = get_std_dev(statistics.moments.x, statistics.moments.y) * variance_scale;
129
200
 
130
201
  // clamp history mean to neighborhood AABB
131
- let input_min = filtered_center_moments.x - sigma ;
132
- let input_max = filtered_center_moments.x + sigma ;
202
+ let clamped_visibility = clamp(history.x, statistics.moments.x - sigma, statistics.moments.x + sigma);
203
+
204
+ // The bend is clamped to a ball about the neighbourhood's mean bend, its radius the same multiple of
205
+ // the bend's deviation as the visibility's box takes of its own. The bend is not a unit vector, so its
206
+ // variance has no cancellation to fight: a neighbourhood of one value has none, and clamps the history
207
+ // onto it.
208
+ let bend_variance = max(statistics.bend_square - dot(statistics.bend, statistics.bend), 0.0);
209
+ let bend_radius = sqrt(bend_variance) * variance_scale;
133
210
 
134
- let clamped_history_m1 = clamp(history_moments.x, input_min, input_max);
211
+ let bend_offset = history.yzw - statistics.bend;
212
+ let bend_offset_length = length(bend_offset);
135
213
 
136
- // Preserve history's variance under the mean clamp:
137
- // m2 = E[X²] = E[X]² + Var(X), so adjust m2 to track the clamped mean while
138
- // retaining the variance the temporal accumulator has built up.
139
- let history_variance = max(history_moments.y - history_moments.x * history_moments.x, 0.0);
140
- let clamped_history_m2 = clamped_history_m1 * clamped_history_m1 + history_variance;
214
+ // past the radius the offset's length is positive, so the division is safe where it is taken
215
+ let clamped_bend = select(
216
+ history.yzw,
217
+ statistics.bend + bend_offset * (bend_radius / bend_offset_length),
218
+ bend_offset_length > bend_radius
219
+ );
141
220
 
142
- // Note: deliberately do NOT gate history_weight on history_variance.
221
+ // Note: deliberately do NOT gate history_weight on the neighbourhood's variance.
143
222
  // Mixing a clamped history mean with a current mean injects cross-term
144
223
  // variance (w·(1-w)·(Δmean)²) that compounds through the EMA whenever
145
224
  // history hasn't converged. Letting that drive history_confidence down
146
- // collapses temporal accumulation. The AABB clamp already constrains
147
- // ghosting; rely on it instead and trust history at a fixed rate.
225
+ // collapses temporal accumulation. The clamps already constrain
226
+ // ghosting; rely on them instead and trust history at a fixed rate.
148
227
  const HISTORY_WEIGHT_MAX = 0.95;
149
228
 
150
229
  let history_weight = HISTORY_WEIGHT_MAX * occlusion_confidence;
151
230
 
152
- let resolved = mix(
153
- current_moments,
154
- vec2(clamped_history_m1, clamped_history_m2),
155
- history_weight
156
- );
231
+ // A bend means something only against the normal it was measured on. A texel on a crease lands on
232
+ // either side from frame to frame as the projection jitters, so its history holds the other surface's
233
+ // bend, which added to this surface's normal tilts the bent normal towards that surface: a line along
234
+ // every crease. The bend takes the history only for the share written on this texel's own surface.
235
+ // Visibility is not measured against the normal, and keeps all of it.
236
+ let surface_agreement = history_surface_agreement(prev_uv, decode_g_buffer_normal(encoded_normal.zw));
157
237
 
158
- output = resolved;
238
+ resolved = vec4(
239
+ mix(current.x, clamped_visibility, history_weight),
240
+ mix(current.yzw, clamped_bend, history_weight * surface_agreement),
241
+ );
159
242
 
160
243
  }
161
-
162
-
163
- return output;
244
+
245
+ // Halves round toward zero on the devices measured, so a blend stored as one stalls short of its target by
246
+ // up to a ULP over the history's 5% step. Rounded stochastically, it lands on its target in expectation.
247
+ let hash = pcg3d(vec3<u32>(vec2<u32>(screenST), settings.frame_index));
248
+ let noise = vec4<f32>(
249
+ hash_to_float01(hash.x),
250
+ hash_to_float01(hash.y),
251
+ hash_to_float01(hash.z),
252
+ hash_to_float01(pcg3d(hash).x),
253
+ );
254
+
255
+ // The bend rides on this frame's own shading normal, so the history adds nothing of the normal map's detail
256
+ // of the texels it was resampled from. An extreme bend can cancel the normal; the normal stands in then.
257
+ let bent = shading_normal + resolved.yzw;
258
+ let bent_length = length(bent);
259
+
260
+ var out: Output;
261
+
262
+ out.history = f16_round_stochastic(resolved, noise);
263
+ out.bent_normal = encode_g_buffer_normal(select(shading_normal, bent / bent_length, bent_length > 1e-4));
264
+
265
+ return out;
164
266
  }
165
267
  `,
166
268
  [
@@ -168,8 +270,28 @@ fn main(
168
270
  chunk_taa_velocity_confidence,
169
271
  chunk_texture_sample_catmullrom_hardware_5tap_uv,
170
272
  chunk_get_std_dev,
273
+ chunk_decode_g_buffer_normal,
274
+ chunk_encode_g_buffer_normal,
275
+ chunk_f16_round_stochastic,
276
+ chunk_pcg3d,
277
+ chunk_hash_to_float01,
171
278
  ]
172
279
  );
280
+
281
+ /**
282
+ * Accumulates GTAO over time: visibility, and the bend that makes the bent normal.
283
+ *
284
+ * The bend takes the history only where the history was written on this texel's surface, by the face normals of
285
+ * `tNormalPrevious` — last frame's G-buffer normal — against this frame's.
286
+ *
287
+ * `tInput`, `tHistory` and the first target are `rgba16float`: visibility in `x`, and in `yzw` the world-space
288
+ * bend — the bent normal minus the shading normal. Each is clamped to this frame's 3x3 neighbourhood before it
289
+ * blends, visibility to a box and the bend to a ball. The second target is the bent normal itself,
290
+ * `normalize(shading normal + bend)`, octahedral in `rg16uint` as the G-buffer normal is, which is what lighting
291
+ * reads.
292
+ *
293
+ * @type {ImageShader}
294
+ */
173
295
  export const ao_reproject_shader = new ImageShader({
174
296
  descriptor: ShaderDescriptor.from({
175
297
  label: "AO Reproject",
@@ -177,10 +299,16 @@ export const ao_reproject_shader = new ImageShader({
177
299
  resources,
178
300
  }),
179
301
  depthStencil: DEPTH_STENCIL_FOREGROUND_ONLY,
180
- targets: [{
181
- format: "rg16float",
182
- // Background is skipped, so it keeps the clear: moments of visibility 1 (not occluded), zero variance.
183
- // This is also next frame's history, whose filtered fetch reaches across silhouettes.
184
- clearValue: [1, 1],
185
- }]
186
- })
302
+ targets: [
303
+ {
304
+ format: "rgba16float",
305
+ // Background is skipped, so it keeps the clear: not occluded, not bent.
306
+ // This is also next frame's history, whose filtered fetch reaches across silhouettes.
307
+ clearValue: [1, 0, 0, 0],
308
+ },
309
+ {
310
+ label: "Bent Normals",
311
+ format: "rg16uint",
312
+ },
313
+ ]
314
+ })
@@ -1 +1 @@
1
- {"version":3,"file":"fragment_shader_gtao.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js"],"names":[],"mappings":"AA2VA,+CA6BG;4BAzWyB,6BAA6B"}
1
+ {"version":3,"file":"fragment_shader_gtao.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js"],"names":[],"mappings":"AA6WA,+CAyBG;4BAxXyB,6BAA6B"}
@@ -6,7 +6,6 @@ import { chunk_project_view_position_from_depth } from "../../shader/chunk/camer
6
6
  import { chunk_get_view_space_depth } from "../../shader/chunk/depth/chunk_get_view_space_depth.js";
7
7
  import { chunk_mat4_extract_position } from "../../shader/chunk/geometry/mat4/chunk_mat4_extract_position.js";
8
8
  import { chunk_decode_g_buffer_normal } from "../../shader/chunk/geometry/normal/chunk_decode_g_buffer_normal.js";
9
- import { chunk_encode_g_buffer_normal } from "../../shader/chunk/geometry/normal/chunk_encode_g_buffer_normal.js";
10
9
  import { chunk_v3_matrix4_rotate } from "../../shader/chunk/geometry/vec3/chunk_v3_matrix4_rotate.js";
11
10
  import { chunk_fast_acos } from "../../shader/chunk/math/fast/chunk_fast_acos.js";
12
11
  import { PI_DECLARATION } from "../../shader/chunk/math/PI_DECLARATION.js";
@@ -95,16 +94,11 @@ const SLICE_COUNT = ${QUALITY_SETTINGS.slices};
95
94
 
96
95
  const STEPS = ${QUALITY_SETTINGS.steps};
97
96
 
98
- struct Output{
99
- @location(0) visibility: vec2<f32>, // first 2 moment
100
- @location(1) bent_normal: vec2<u32>, // octahedral encoding
101
- }
102
-
103
97
  @fragment
104
98
  fn main(
105
99
  @builtin(position) coord: vec4<f32>,
106
100
  @location(0) uv: vec2<f32>,
107
- ) -> Output {
101
+ ) -> @location(0) vec4<f32> {
108
102
 
109
103
  // fadeout precompute optimisation
110
104
  const falloffRange = ${GTAO_EFFECT_FALLOFF_RANGE} * ${GTAO_EFFECT_RADIUS};
@@ -160,7 +154,22 @@ fn main(
160
154
 
161
155
  // this is the min distance to start sampling from to avoid sampling from the center pixel (no useful data obtained from sampling center pixel)
162
156
  let minS = pixelTooCloseThreshold / screenspaceRadius;
163
-
157
+
158
+ // The slices' angle is measured around the view ray, from view-space x made perpendicular to it: at the
159
+ // screen's centre that is the screen's own x, as the paper has it. The ray never runs along x inside a frustum.
160
+ let slice_basis_x = normalize(vec3(1.0, 0.0, 0.0) - view_direction_vs * view_direction_vs.x);
161
+ let slice_basis_y = cross(view_direction_vs, slice_basis_x);
162
+
163
+ // This texel through the projection, reading only the entries a projection fills, as
164
+ // project_view_position_from_depth reads its inverse: x from x and z, y from y and z, w from z. The TAA
165
+ // jitter is in the z column of a perspective, the translation column of an orthographic one.
166
+ let projection = camera.projection_matrix;
167
+ let center_clip_xy = vec2(
168
+ fma(position_vs.x, projection[0][0], fma(position_vs.z, projection[2][0], projection[3][0])),
169
+ fma(position_vs.y, projection[1][1], fma(position_vs.z, projection[2][1], projection[3][1])),
170
+ );
171
+ let center_clip_w = fma(position_vs.z, projection[2][3], projection[3][3]);
172
+
164
173
  const INV_SLICE_COUNT = 1.0 / f32(SLICE_COUNT);
165
174
 
166
175
  for (var slice = 0; slice < SLICE_COUNT; slice++) {
@@ -173,12 +182,24 @@ fn main(
173
182
  let cosPhi = cos(phi);
174
183
  let sinPhi = sin(phi);
175
184
 
176
- let omega = vec2(cosPhi, -sinPhi) * screenspaceRadius;
177
-
178
- // line 8 from the paper
179
- let sliceViewDir = vec3(cosPhi, sinPhi, 0.0);
185
+ // line 8 from the paper, with phi the slice's angle around this texel's own view ray: the integral below
186
+ // is written in that angle. The paper takes phi on screen, which is the same angle only at the screen's
187
+ // centre; off it, slices spread evenly on screen bunch around the view ray, the two of a frame stop
188
+ // cancelling, and an open plane's bent normal leans by degrees towards the screen's edges.
189
+ let sliceViewDir = cosPhi * slice_basis_x + sinPhi * slice_basis_y;
180
190
  let sliceWorldDir = v3_matrix4_rotate(sliceViewDir, camera.view_matrix_inverse);
181
191
 
192
+ // The slice's plane holds the view ray, so on screen it is a line through this texel, along the
193
+ // projection's derivative in the slice's direction: (d(clip.xy) * clip.w - clip.xy * d(clip.w)) / clip.w^2,
194
+ // its scale dropped, into uv and then pixels.
195
+ let slice_clip_xy = vec2(
196
+ fma(sliceViewDir.x, projection[0][0], sliceViewDir.z * projection[2][0]),
197
+ fma(sliceViewDir.y, projection[1][1], sliceViewDir.z * projection[2][1]),
198
+ );
199
+ let slice_clip_w = sliceViewDir.z * projection[2][3];
200
+ let slice_screen = (slice_clip_xy * center_clip_w - center_clip_xy * slice_clip_w) * vec2(0.5, -0.5) * vec2<f32>(ViewportSize);
201
+ let omega = normalize(slice_screen) * screenspaceRadius;
202
+
182
203
  // line 9 from the paper
183
204
  // NOTE: optimized with FMA, readability suffers
184
205
  let orthoWorldDir = fma( vec3( -dot(sliceWorldDir, view_direction_ws) ), view_direction_ws, sliceWorldDir );
@@ -230,7 +251,7 @@ fn main(
230
251
  // approx lines 21-22 from the paper, unrolled
231
252
  var sampleOffset = s * omega;
232
253
 
233
- // omega = vec2(cosPhi, -sinPhi) * screenspaceRadius has length screenspaceRadius
254
+ // omega is a unit screen direction times screenspaceRadius, so has length screenspaceRadius
234
255
  let sampleOffsetLength = s * screenspaceRadius;
235
256
  let mipLevel = gtao_compute_mip_level(sampleOffsetLength);
236
257
 
@@ -318,12 +339,10 @@ fn main(
318
339
  visibility = max(0.03, visibility);
319
340
 
320
341
  bent_normal = normalize(bent_normal);
321
-
322
- var out: Output;
323
- out.visibility = vec2(visibility, visibility * visibility);
324
- out.bent_normal = encode_g_buffer_normal( bent_normal );
325
-
326
- return out;
342
+
343
+ // The bend, not the bent normal: what the horizons add to the shading normal. Unoccluded it is exactly
344
+ // zero, so the filters downstream can average it without averaging away the normal map's detail.
345
+ return vec4(visibility, bent_normal - view_normal_ws);
327
346
  }
328
347
  `, [
329
348
  chunk_get_view_space_depth,
@@ -331,7 +350,6 @@ fn main(
331
350
  PI_HALF_DECLARATION,
332
351
 
333
352
  chunk_decode_g_buffer_normal,
334
- chunk_encode_g_buffer_normal,
335
353
  chunk_spatio_temporal_noise_r2_64,
336
354
 
337
355
  chunk_fast_acos,
@@ -357,9 +375,10 @@ export const fragment_shader_gtao = new ImageShader({
357
375
  targets: [
358
376
  {
359
377
  label: "Occlusion",
360
- // first 2 moments of visibility
361
- format: "rg16float",
362
- clearValue: [1, 1], // Stores visibility, so 1 == not occluded
378
+ // visibility, and the world-space bend: bent normal minus shading normal
379
+ format: "rgba16float",
380
+ // Background is skipped, so it keeps the clear: not occluded, not bent.
381
+ clearValue: [1, 0, 0, 0],
363
382
  blend: BlendState.from({
364
383
  color: {
365
384
  operation: "add",
@@ -368,10 +387,5 @@ export const fragment_shader_gtao = new ImageShader({
368
387
  }
369
388
  })
370
389
  },
371
- {
372
- label: "Bent Normals",
373
- // Direction is encoded with octahedral
374
- format: "rg16uint",
375
- },
376
390
  ]
377
391
  });
@@ -1 +1 @@
1
- {"version":3,"file":"fragment_shader_gtao_with_irradiance.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js"],"names":[],"mappings":"AA2XA,+DAkCG;4BA5YyB,6BAA6B"}
1
+ {"version":3,"file":"fragment_shader_gtao_with_irradiance.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js"],"names":[],"mappings":"AA0YA,+DAkCG;4BA5ZyB,6BAA6B"}