@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,413 +0,0 @@
1
- # Contact shadows: what fails, and what a careful implementation fixes
2
-
3
- Status 2026-10-16: **prototype, not wired into the renderer.** The pass here is a WGSL port of Bend
4
- Studio's screen-space shadows; the playground `src/shade/playground/contact_shadows/` measures it, and the
5
- engine's older per-pixel march, against a ray-traced reference, one scene per failure mode. Nothing in the
6
- default frame changes until the forks at the end are answered.
7
-
8
- **In short.** Of the ten ways contact shadows are known to fail:
9
-
10
- - **Fixed**, measured:
11
- - noise: the pass is deterministic;
12
- - disocclusion trails: it keeps no history;
13
- - self-shadowing where the sun grazes a receiver: 0.1% false;
14
- - the far-field moiré where the view grazes the ground: 14,926 → 358 false px a frame with Bend's own
15
- `IgnoreEdgePixels`.
16
- - **A trade, no fix:**
17
- - the thickness window: no value serves both 2 cm poles and 40 cm boxes;
18
- - foliage: thinnest of all;
19
- - min against multiply: multiply is closer to the sun, min keeps the cascades' softness.
20
- - **Inherent to screen space:**
21
- - view dependence: 11–50% of the gaps closed frame to frame round one orbit;
22
- - off-screen casters, bounded by the 60-px reach;
23
- - normal-map detail;
24
- - shimmer of detail the cascades cannot resolve, under camera motion.
25
-
26
- With the cascades, the pass closes 77–79% of the gaps at caster bases for a handful of false pixels, at
27
- 38 µs at 1.27 Mpx on a 4090. With VSM there is a twelfth to a twentieth as much to close, and it adds about
28
- as much false shadow as it removes.
29
-
30
- **Later the same day, Alex chose a per-pixel march, favouring accuracy, on a generic linear trace any
31
- screen-space feature can use (§6).** At 64 steps it matches the wavefront pass's accuracy against the sun
32
- summed over the ten scenes, with less false shadow on fine detail, at 3.4× its cost.
33
-
34
- ## 0. What is here
35
-
36
- - `ContactShadowDispatchList.js`: Bend's `BuildDispatchList` (CPU). Up to 8 dispatches of 64-pixel
37
- wavefronts converging on the light's point on screen.
38
- - `chunk_contact_shadow_wavefront_extents.js`, `shader_contact_shadow_wavefront.js`: Bend's
39
- `ComputeWavefrontExtents` and `WriteScreenSpaceShadow`. A 64-thread workgroup is one 64-pixel run along a
40
- single ray to the light; each thread does 2 reads of 2 depth taps into a 128-word workgroup array and
41
- compares 60 of its neighbours' words. **Every thread's work is fixed: 4 texture reads, 60 shared-memory
42
- compares,** whatever the scene.
43
- - `graph_contact_shadow_wavefront.js`: one graph pass, one dispatch per list entry, writing an `r32float`
44
- visibility mask (1 lit). `r8unorm` storage needs `texture-formats-tier1`, which the engine takes when
45
- offered but does not require.
46
- - `ContactShadowDispatchList.spec.js`: the real WGSL extents function, under the emulator, against the CPU
47
- dispatch list: every pixel of a viewport gets a thread, for lights on screen, off each edge, in a corner,
48
- nearly perpendicular to the view, and behind the camera.
49
-
50
- ### Two holes in Bend's released layout, found by that spec and fixed
51
-
52
- 1. **The light's own pixel is written by no thread.** Every ring stops one pixel short of the light, so
53
- with the light on screen one pixel kept whatever the texture held. The innermost ring's threads now
54
- also write it (lit: a ray of no length).
55
- 2. **A light projecting millions of pixels away loses rows to f32 spacing.** Bend clamps w only once the
56
- light is ~1M px out; at 9e6 px the spec saw rows unwritten. The CPU now pulls the light's point in to
57
- 2^20 px from the viewport's centre (f32 spacing 1/8 px there), turning the rays by under 0.1° at
58
- 1600 px. An overhead sun with a level camera (w = 0, Bend's clamp) projects to 3.5e6 px and was
59
- already whole at 1600×900.
60
-
61
- ## 1. The failure modes, and why they happen
62
-
63
- From the primary sources. Bend is
64
- `bend_sss_gpu.h` / `bend_sss_cpu.h` (Sony, Apache 2.0) and the SIGGRAPH 2023 talk's slide text.
65
-
66
- | # | Failure mode | Cause | What shipping code does about it |
67
- |---|---|---|---|
68
- | 1 | **Heightfield thickness**: thin casters smear, thick ones leak | The depth buffer holds each caster's front and nothing behind it, so every method assumes a slab thickness | Bend: 0.5% of the sample's depth to the far plane (here: in front of the ray by up to 1% of its view depth). UE desktop: ≈ L/2, set by ray length and 8 steps. Filament ≈ 7.5 cm, three.js 1 cm, Bevy 10 cm, all world space. Nobody reconstructs back faces |
69
- | 2 | **Self-shadowing** where the sun or the view grazes a surface, and on normal-mapped surfaces | A ray leaving a surface at a grazing angle runs along it, so the surface's own neighbouring depths sit just in front of it; depth is quantised per pixel; the shading normal and the depth disagree | Bend: an edge-aware bilinear read across the ray's minor axis, pushing the casting depth back by the step across the pixel; a start bias "suppressed legitimate detail" (talk). UE: skip samples bit-equal to the start depth. Bevy: an open draft (#25355) bends the ray toward the normal. Normal maps are invisible to all of them; Days Gone wrote a ±8 cm material displacement into depth to get that detail |
70
- | 3 | **View dependence** | Only casters that are on screen and in front cast; the reach is counted in pixels (Bend, Godot, UE screen mode) or the screen reach shrinks with distance (world-space methods) | Bend: "they cannot replace shadow maps, only complement them" (talk). Nothing fixes it |
71
- | 4 | **Noise and TAA instability** | Jittered starts and few steps (UE 8 steps + IGN over 8 frames, Bevy, three.js, Filament) need TAA to converge; the jittered depth buffer changes what is in it | Bend is deterministic: 4 interleaved min-reductions averaged, 4 hard near samples, an 8-sample fade. Every other source leans on the scene's TAA |
72
- | 5 | **Disocclusion trails** | Temporal accumulation of a term that changes with the view | No source keeps contact-shadow history; trails are whatever TAA does |
73
- | 6 | **Screen edges** | Off-screen casters are not in the depth buffer | Bend reads off-screen as the far plane (clamp-to-border); UE treats an off-screen hit as a miss; Filament fades by the ray's end. A fade only hides the pop |
74
- | 7 | **Scale with distance** | A pixel reach means a world reach growing with depth; a world reach shrinks below a pixel | Bend 60 px fixed; UE screen mode L ∝ depth; world-space methods vanish far away |
75
- | 8 | **Alpha-tested foliage** | Cut-outs alias per texel, cards are millimetres thick, two-sided leaves are their own receivers | Bend's `IgnoreEdgePixels` "can also thin out otherwise valid shadows, especially on foliage edges". UE attenuates subsurface/foliage receivers by 1 − exp(−density·distance) |
76
- | 9 | **Double darkening** against the shadow map | Multiplying two partial visibilities (a PCF penumbra and a partial contact) is darker than either | UE desktop multiplies; UE mobile and Godot take the min; Filament and Bevy multiply but skip pixels the map already shadows fully |
77
- | 10 | **The light's point on screen** | Rays converge on it, so near it every ray is a few pixels long; Bend widens its window there | Bend: `min(sample_distance + direction, 1/thickness)` in the window scale |
78
-
79
- ## 2. Measured
80
-
81
- RTX 4090, headless Chrome, 1578×802, 2026-10-16. Every number is per frame, averaged over 150 frames at
82
- 1/60 s along the scene's own camera path (the same path from the same start for every arm), classified
83
- before TAA against a ray traced from each pixel's G-buffer position to the sun's centre ("Counters" in the
84
- playground README). "Gaps" are pixels the reference shadows and the cascades leave lit; "closed" is the
85
- share of those the combined term shadows; "added" is false shadow the contact term put where the reference
86
- and the cascades are both lit. The runs are deterministic: a second campaign reproduced every count.
87
-
88
- Arms: **Bend** is the port with Bend's starting values (surface thickness 0.005, edge threshold 0.02,
89
- contrast 4) multiplied into the cascades' term; the next column turns on Bend's own `IgnoreEdgePixels`.
90
- **March** is the engine's unwired per-pixel march
91
- (`deferred/chunk_ss_trace_contact_shadow_soft.js`) given the same 60 samples and the same thickness window.
92
-
93
- | Scene | Reference shadowed | Cascade gaps | Bend: closed / added | Bend + `IgnoreEdgePixels`: closed / added | March: closed / added |
94
- |---|---|---|---|---|---|
95
- | thickness | 32,686 | 2,141 | 17.1% / 155 | 17.1% / 153 | 11.2% / 186 |
96
- | grazing | 22,286 | 7,941 | 31.9% / 23 | 28.2% / 6 | 2.8% / 1 |
97
- | view | 22,953 | 2,523 | 28.6% / 36 | 28.1% / 26 | 20.9% / 19 |
98
- | noise (fine detail) | 72,090 | 66,943 | 67.7% / 6,992 | 65.0% / 5,525 | 27.1% / 2,387 |
99
- | disocclusion | 19,305 | 5,013 | 76.6% / 21 | 75.3% / 11 | 4.5% / 1 |
100
- | screen_edge | 118,831 | 3,071 | 14.2% / 83 | 14.1% / 79 | 13.0% / 125 |
101
- | distance | 12,296 | 3,383 | 10.2% / 49 | 10.2% / 45 | 2.7% / 5 |
102
- | foliage | 57,767 | 26,659 | 42.6% / 3,323 | 40.8% / 3,012 | 18.6% / 1,272 |
103
- | combine | 22,767 | 6,039 | 81.5% / 45 | 79.1% / 22 | 10.1% / 3 |
104
- | sun_in_view | 19,868 | 2,991 | 36.2% / 14,926 | 35.3% / 358 | 33.8% / 433 |
105
-
106
- Taking the min with the cascades instead of multiplying is item 9.
107
-
108
- ### Verdicts, failure by failure
109
-
110
- 1. **Heightfield thickness — inherent; the window is a trade with no safe value.** In `thickness`, Bend's
111
- window (in front of the ray by up to 1% of its depth) closes 17.1% and smears 155 px behind the thin
112
- poles and plank; ¼ of it closes 14.3% and adds 1 px; 4× closes 20.1% and adds 1,193 px. But the same ½
113
- window that cleans `foliage` (3,323 → 1,302 px added) drops the movers' closure in `disocclusion` from
114
- 76.6% to 21.6%: rays pass behind casters thicker than the window and read as lit. One depth layer cannot
115
- tell a 2 cm pole from a 40 cm box. Bend's value is kept as the default; it is the trade every caller
116
- would make differently.
117
- 2. **Self-shadowing.**
118
- - *The sun grazing a receiver* (8°, `grazing`) — **fixed by Bend's design**: 23 false px of 22,286
119
- shadowed (0.1%), 6 with `IgnoreEdgePixels`. The edge-aware read across the ray's minor axis and the
120
- window's one-sided offset (a sample at the ray's own depth stays lit) carry it; no start bias needed.
121
- - *The view grazing a surface* (far ground at the horizon, sun ahead, `sun_in_view`) — **fixed by
122
- `IgnoreEdgePixels`**: 14,926 → 358 false px a frame, all of it on ground 16–128 m away, and the
123
- contact term's frame-to-frame change 16,957 → 5,552 (the cascades' own: 6,046), for one point of
124
- closure. At 50 m one pixel row of ground spans ~1.7 m, past the 2% edge threshold, so the reads are
125
- point-sampled and the row half a step nearer falls inside the window: a moiré band. Bend's notes
126
- describe exactly this and offer the flag.
127
- - *Normal maps* — **inherent**: depth does not carry normal-map detail, so the contact pass neither
128
- shadows nor self-shadows from it (`grazing`'s normal-mapped slab). Days Gone wrote a ±8 cm material
129
- displacement into depth to get it; that is a G-buffer change, not a shadow-pass one.
130
- 3. **View dependence — inherent.** The share of `view`'s gaps closed swings from 12.7% to 42.1% frame to
131
- frame along the orbit; casters hidden by the post cast nothing while hidden.
132
- 4. **Noise and TAA instability — the noise is fixed; motion shimmer on sub-texel detail is inherent.**
133
- Bend has no random term (a second campaign reproduced every count). TAA on or off changes nothing
134
- before TAA (`noise`: 16,093 vs 15,616 flips), so the jitter is not the driver. But where the contact
135
- term carries detail the cascades cannot resolve (`noise`: 2 cm slats, the cascades miss 93% of the
136
- shadowed pixels), it changes frame to frame under camera motion far more than the cascades do: 15,616
137
- pixels cross ½ a frame against the cascades' 856; summed change 18,568 against 10,788. That is the
138
- depth buffer's own sampling of sub-pixel detail moving; only TAA can resolve it, and it costs nothing
139
- there to try.
140
- 5. **Disocclusion trails — fixed by construction.** The pass reads this frame's depth and nothing else;
141
- it has no history to trail. Around the movers in `disocclusion` it closes 76.6% of the gaps with 21
142
- false px. Any ghosting is TAA's, unchanged by the pass.
143
- 6. **Screen edges — inherent.** See the coverage run below.
144
- 7. **Scale with distance — mitigated.** The reach is 60 pixels, so its world length grows with depth, and
145
- the thickness window does too. That matches both shadow maps' error, which also grows with depth (see
146
- "The budget, derived" below). The far field's real failure was the grazing-view moiré, which
147
- `IgnoreEdgePixels` removes (item 2).
148
- 8. **Alpha-tested foliage — mitigated.** Contact shadows close 42.6% of the foliage gaps but add 3,323
149
- false px (5.8% of the shadowed pixels): cards a few millimetres thick get the window's 1%-of-depth
150
- thickness. `IgnoreEdgePixels` takes it to 3,012, a ½ window to 1,302 (closing 29.4%). It is item 1's
151
- trade on the thinnest casters there are.
152
- 9. **Double darkening — real, and against the sun it is the more accurate choice.** Multiplying leaves
153
- pixels darker than both terms by over 0.1 (`combine` 978, `noise` 19,873, `foliage` 9,278, with
154
- `IgnoreEdgePixels`); the min removes every one. But measured against the ray-traced sun, the multiply is
155
- closer in all ten scenes (mean |error| lower or tied: `disocclusion` 0.0047 against 0.0051, `noise`
156
- 0.0376 against 0.0393, `combine` 0.0041 against 0.0043), and the min gives up closure for it
157
- (`disocclusion` 75.3% → 55.5%, `screen_edge` 14.1% → 9.2%) while removing some false shadow (`combine`
158
- 22 → 14 px). The cascades' 5×5 PCF penumbra is wider than the sun's (0.37°, under a millimetre at a
159
- contact), so darkening it toward the contact is mostly darkening toward the truth. The min only wins if
160
- the shadow map's softness is the look to keep.
161
- 10. **The light's point on screen.** The widened window near the sun's point did not show as a failure of
162
- its own; the far-field moiré in `sun_in_view` (item 2) is what looking toward the sun exposed.
163
-
164
- ### Against VSM
165
-
166
- The same scenes with the virtual shadow map (1 cm first texel), Bend + `IgnoreEdgePixels` + min:
167
-
168
- | Scene | Cascade gaps → closed / added | VSM gaps → closed / added |
169
- |---|---|---|
170
- | thickness | 2,141 → 15.8% / 142 | 197 → 7.2% / 149 |
171
- | grazing | 7,941 → 28.0% / 5 | 3,307 → 62.1% / 12 |
172
- | view | 2,523 → 24.0% / 8 | 336 → 1.6% / 8 |
173
- | noise | 66,943 → 59.0% / 4,156 | 19,417 → 54.2% / 2,935 |
174
- | disocclusion | 5,013 → 55.5% / 6 | 251 → 13.1% / 5 |
175
- | screen_edge | 3,071 → 9.2% / 62 | 357 → 7.3% / 60 |
176
- | distance | 3,383 → 8.7% / 27 | 166 → 4.7% / 28 |
177
- | foliage | 26,659 → 36.1% / 2,647 | 9,557 → 16.8% / 2,201 |
178
- | combine | 6,039 → 77.4% / 14 | 380 → 5.6% / 14 |
179
- | sun_in_view | 2,991 → 33.2% / 224 | 284 → 23.6% / 303 |
180
-
181
- VSM leaves a twelfth to a twentieth of the cascades' gaps at caster bases (`combine`, `disocclusion`,
182
- `view`, `distance`, `screen_edge`, `thickness`), and there the contact term adds about as much false shadow
183
- as it closes, or more. It still earns its place in three cases: a sun grazing the receiver (`grazing`: 62%
184
- of VSM's 3,307 gaps closed for 12 false px), detail finer than the first page (`noise`'s 2 cm slats: 54%),
185
- and foliage, though there it adds 2,201 false px to close 1,605. Bend's defaults without `IgnoreEdgePixels`
186
- put the far-field moiré back under VSM too (`sun_in_view`: 14,942 false px).
187
-
188
- ### The coverage runs
189
-
190
- The 150-frame runs at 1/60 s cover only the first 2.5 s of each path. To traverse the pans, the orbit,
191
- the turn and the dolly, four scenes ran 300 frames at four times the speed:
192
-
193
- - **Screen edges — inherent, bounded by the reach.** Through the whole pan, the share of `screen_edge`'s
194
- gaps closed swings between 9% and 20% from frame to frame, the same swing as the orbit's. A caster that
195
- leaves the screen only takes the contact shadow within 60 px of the edge with it; off-screen reads
196
- return the far plane (an explicit bounds check: WebGPU has no clamp-to-border), so nothing false comes
197
- from beyond the edge.
198
- - **View dependence.** Round the full orbit of `view`, Bend closes 11–50% of the gaps by frame and its
199
- false shadow spikes to 2,986 px on one frame; with `IgnoreEdgePixels` (and the ½ window) the spike is
200
- 12 px.
201
- - **Sun in view.** Facing the sun Bend adds 12,662–25,247 false px a frame, facing away 78–345; with
202
- `IgnoreEdgePixels` (and the ½ window) at most 67 throughout.
203
-
204
- ### The budget, derived
205
-
206
- Each thread's reach is its sample count in pixels. Bend's 60 is what their read formula fits in two reads
207
- of a 64-wide wave (it over-counts: the two reads hold 64 words past each thread). What has to be reached is
208
- the shadow map's own blur at a caster's base: the cascades filter 5×5 texels (`SHADOWMAP_FILTER_SIZE`), so
209
- 2.5 texels either side of an edge. Measured in `combine`: cascade 0 covers the first 54 m at **4.7 cm a
210
- texel**, so 12 cm of blur; at 1578×802 and 55° a pixel spans 1.3 mm per metre of depth, so 60 pixels reach
211
- 12 cm at **1.5 m** and more beyond it (7.8 cm × depth in metres, for a light parallel to the image). Nearer
212
- than 1.5 m the cascades' blur is wider than the reach; further away the reach outgrows it in step with the
213
- cascades, whose texels also grow with distance (17 cm to 167 m, 42 cm to 400 m). For VSM's 1 cm first
214
- texel the same 60 px covers its 2.5 cm from 0.3 m. Doubling the reach would take a third read per thread
215
- (READ_COUNT 3) and buy the 0.75–1.5 m band for cascades only. 60 is kept.
216
-
217
- ### Defects found on the way, outside this pass
218
-
219
- - `shadow/ray/shader_ray_shadow_code.js`, the engine's ray-traced shadow prototype, binds five groups; a
220
- device offers four, so it cannot be dispatched. The playground's reference is the same query in three
221
- groups. Fixed the same day: it binds three, as the reference does.
222
- - It also starts its rays with `offset_ray`, which offsets in proportion to |position| (meant for a ray
223
- hit's position). On a position rebuilt from depth that leaves the far ground shadowing itself: 180,140
224
- shadowed pixels in `combine` against 25,166 with an offset of 3e-5 of the view distance, the onset of a
225
- plateau measured from 1e-6 to 1e-3. Fixed the same day: its rays (and the staged generator's) start at
226
- `offset_ray_from_depth` (`shader/chunk/geometry/ray/chunk_offset_ray_from_depth.js`), that offset.
227
- - `deferred/chunk_ss_trace_contact_shadow_soft.js`, the engine's unwired contact chunk, closes 2.7–27% of
228
- the gaps where the wavefront pass closes 10–82%, with the same samples and window.
229
-
230
- ## 3. Cost
231
-
232
- GPU time per pass, RTX 4090, 1578×802 (1.27 Mpx), the three methods swapped every 4 frames in ABC CBA
233
- order inside one profile capture, each block's first frame dropped, 90 frames per arm, camera still. Two
234
- runs per case; their medians agree to within one timer step (~1 µs). Deferred shading read 66.6–68.6 µs in
235
- every arm, so the clocks held.
236
-
237
- | | Sun off screen (`combine`) | Sun on screen (`sun_in_view`, facing it) |
238
- |---|---|---|
239
- | Wavefront pass (Bend) | **37.9 µs** | **32.8 µs** |
240
- | Per-pixel march (engine chunk) | 73.7 µs | 53.2 µs |
241
- | Playground composite (scaffolding) | 48.1 µs | 31.7 µs |
242
-
243
- About 30 µs per megapixel, so ~62 µs at 1080p and ~250 µs at 4K on this card; Bend report 0.19 ms at
244
- 1440p on PS5. The composite is the price of applying the mask without touching deferred shading: it
245
- re-evaluates the sun's BRDF and cascade lookup and writes the debug record. Reading the mask inside the
246
- sun's shadow term instead is one texture load per pixel in a pass already running; it is not measured here
247
- because it needs the deferred shader changed (fork 3).
248
-
249
- ## 4. Reuse map
250
-
251
- | Piece | Reuses | New |
252
- |---|---|---|
253
- | Depth, normals, camera | `ViewTextures`, `GBufferTextures` records; `CAMERA_UNIFORM_STRUCT`; the view's jittered `view_projection_matrix` for the light's screen point | — |
254
- | Wavefront pass | `ComputeShader`, `CodeChunk`, immediates (`setImmediate`), `graph_prepare_bindings`, the frame graph | the Bend port: dispatch list, extents chunk, kernel |
255
- | The mask in the sun's term (playground) | `chunk_read_gBuffer_material`, `chunk_shadowmap_get_light_visibility`, `chunk_get_directional_light_info_by_index`, `chunk_re_direct_physical`, the deferred pass's random seed — the deferred pass's own chunks | the subtractive composite (scaffolding) |
256
- | Reference | `chunk_ray_shaded_query_occluded` (path tracer), `RESOURCE_GROUP_RTX`, resident materials, `chunk_offset_ray` | three-group reference shader |
257
- | A/B arm | `chunk_ss_trace_pixel_occlusion` unchanged | an 8×8 dispatch of it |
258
- | Linear trace (§6) | `chunk_v3_matrix4_project`, `chunk_ndc_to_uv`, `chunk_uv_to_ndc`, `chunk_get_view_space_depth`, `chunk_get_bilinear_filter_texel`, `chunk_interpolate_bilinear_f32`, `chunk_interleaved_gradient_noise`, `chunk_project_position_from_depth`, `graph_compute_pass` | `chunk_screen_space_linear_ray` (generic, beside the Newton ray), the contact pass on it |
259
- | Measurement | `GPUProfileSession` (subclassed to keep spans by frame), the render-extension phases | counters shader |
260
-
261
- Nothing in the engine builds screen-space wavefronts toward a light, so the dispatch list and kernel are
262
- new. The unwired `deferred/chunk_ss_trace_contact_shadow_soft.js` is what the pass would supersede.
263
-
264
- ## 5. Forks
265
-
266
- What the measurements recommend; each is Alex's call.
267
-
268
- 1. **The sun only, or local lights too?** Sun only. Bend's layout takes a point or spot light as
269
- `(position, 1)` with a screen rectangle, but every light is another full pass over its rectangle (about
270
- 30 µs per megapixel here), the local lights' shadow maps had their contact gap closed on 2026-10-04
271
- (front faces, texel-scaled bias), and the ReSTIR DI path already traces their visibility. Not built or
272
- measured here.
273
- 2. **With the cascades, and with VSM.**
274
- - Cascades: on. The pass closes 77–79% of their gaps at caster bases (`combine`, `disocclusion`) for
275
- 12–22 false px a frame, and 41–65% of what they cannot resolve at all (foliage cards, 2 cm slats) for
276
- 3,000–5,500 false px, at 38 µs at 1.27 Mpx.
277
- - VSM: off. It leaves a twelfth to a twentieth of the cascades' gaps, and there the pass adds about as
278
- much false shadow as it closes. The exceptions are a sun grazing the receiver, detail finer than the
279
- first page, and foliage; whether those justify it is the question.
280
- - Multiply (closer to the sun in all ten scenes) rather than min (keeps the cascades' softness, loses up
281
- to 20 points of closure).
282
- 3. **Where the mask is read.**
283
- - (a) In the sun's shadow term (`chunk_shadowmap_sample_directional`, beside the CSM/VSM lookup): one
284
- texture load per pixel. But that chunk is also linked by volumetrics, water optics and the forward
285
- path, none of which has a screen pixel to read the mask at, so they need it without the read: a
286
- per-pipeline choice, which waits on the shader-switches design started 2026-10-16.
287
- - (b) A pass of its own after lighting, as the playground does: no change to deferred shading at all,
288
- 48 µs at 1.27 Mpx (it re-evaluates the sun's BRDF and cascade lookup), more than the contact pass
289
- itself.
290
- - Recommendation: (a) once shader switches exist.
291
- 4. **Default on or off.** On with the cascades, with Bend's thickness, `IgnoreEdgePixels` on, bilinear
292
- offset mode off (it closes more in `grazing`, 38.9% against 31.9%, but adds 150 false px against 23 and
293
- does nothing for the far-field moiré), multiplied in. Off with VSM. The thickness is the one setting no
294
- default serves (item 1): content with thin casters (foliage, grilles) wants it smaller, chunky casters
295
- want Bend's.
296
-
297
- ### Follow-ups, outside this prototype
298
-
299
- - `deferred/chunk_ss_trace_contact_shadow_soft.js` is unwired and measured worse than the wavefront pass
300
- at twice its cost; wiring the pass should delete it.
301
- - `shadow/ray/shader_ray_shadow_code.js` could not be dispatched (five bind groups) and self-shadowed the
302
- far ground (`offset_ray` on depth-rebuilt positions); both fixed 2026-10-16, along with its denoiser,
303
- which did not load. It is still unwired.
304
-
305
- ## 6. The linear trace, per pixel
306
-
307
- Alex's direction after reading §1–5: a per-pixel march, favouring accuracy, on a generic linear trace
308
- with a configurable step count that the rest of the engine can reuse.
309
-
310
- ### What it is
311
-
312
- `shader/chunk/screen_space/chunk_screen_space_linear_ray.js`, beside the water's Newton ray. It is a port of
313
- Tomasz Stachowiak's `raymarch.hlsl` (MIT/Apache; the march Bevy uses for contact shadows, SSR and SSGI),
314
- built on the engine's own projection, depth and bilinear chunks:
315
- - **Clipped first.** The segment is clipped to the view frustum in NDC, so every step lands on screen.
316
- - **Exact depth along the ray.** It marches linearly in NDC, where device depth is affine along a projected
317
- line.
318
- - **Bounded.** At most one step per pixel and at most 64 steps (`SCREEN_SPACE_LINEAR_RAY_STEP_LIMIT`), plus
319
- up to 8 bisection steps.
320
- - **Two depth reads per step.** It takes the point-sampled and the bilinear depth from one 4-texel fetch,
321
- and claims a hit only when the ray is behind both.
322
- - **World-unit thickness.** Depth is compared as view distance, so `depth_thickness` is in metres; with
323
- `march_behind_surfaces` the ray carries on past a surface it went too deep behind.
324
- - **Hit refinement** by bisection and secant, for a trace that samples colour at the hit.
325
-
326
- `shadow/contact/shader_contact_shadow_linear.js` is the contact pass on it. Each pixel marches from its own
327
- NDC toward the sun:
328
- - a world-space reach, in a configurable number of steps;
329
- - a first step either fixed or jittered by interleaved gradient noise;
330
- - a hit's visibility faded over the back half of the thickness, as Bevy does.
331
-
332
- Pixels facing away from the sun are skipped.
333
-
334
- **Pinned on the CPU** (`chunk_screen_space_linear_ray.spec.js`, emulator against analytic depth buffers):
335
- - A ray climbing 3°, 10° or 30° off a flat ground, from near and far pixels in four headings, never finds
336
- the ground in front of it. With point samples alone, the same rays do (the test that keeps the bilinear
337
- read).
338
- - A ray toward a wall stops within a pixel of the analytic crossing.
339
- - Bisection takes a 4-step march from over 2 px off the crossing to under 1.
340
- - A 2 m deep wall is passed behind when marching behind surfaces, and stops the ray when not.
341
- - The sky is a miss over the whole length; the step count caps at 64 and at one per pixel.
342
-
343
- **Found on the device only:** `filter` is a WGSL reserved word, which the CPU validator does not check; the
344
- pipeline was invalid until it was renamed.
345
-
346
- ### Settings, and where they come from
347
-
348
- - **Reach** is so many texels of the shadow map serving the near field (cascade 0 as last fitted, or VSM's
349
- first level). That way the reach follows what the shadow map cannot resolve. Cascade 0 measured 4.7 cm a
350
- texel in `combine`: 5 texels (the 5×5 filter) is 24 cm, 10 texels 48 cm.
351
- - **Thickness** is a multiple of reach ÷ steps. At 1 it is the least for which a march behind surfaces still
352
- sees every surface (Tomasz's rule). Tying it to the step count makes more steps close less, because each
353
- step's window narrows: at reach 5, 16 steps closed 58.8% in `combine`, 64 steps 39.5%.
354
-
355
- ### Measured, against Bend with `IgnoreEdgePixels`
356
-
357
- Same scenes, paths and counters as §2 (150 frames per arm, cascades, multiply). Gaps closed / false px added /
358
- mean |error| against the ray-traced sun:
359
-
360
- | Scene | Bend + `IgnoreEdgePixels` | Linear, 32 steps, reach 5, thickness ×1 | Linear, 64 steps, reach 10, thickness ×4 |
361
- |---|---|---|---|
362
- | thickness | 17.1% / 153 / 0.0042 | 6.2% / 0 / 0.0043 | 15.1% / 21 / 0.0042 |
363
- | grazing | 28.2% / 6 / **0.0075** | 12.2% / 0 / 0.0086 | 11.1% / 0 / 0.0084 |
364
- | view | 28.1% / 26 / 0.0060 | 14.3% / 0 / 0.0064 | 29.0% / 1 / **0.0058** |
365
- | noise (fine detail) | 65.0% / 5,513 / 0.0376 | 29.7% / 175 / 0.0454 | 60.8% / 3,132 / **0.0351** |
366
- | disocclusion | 75.3% / 12 / **0.0047** | 45.2% / 1 / 0.0052 | 57.1% / 36 / 0.0050 |
367
- | screen_edge | 14.1% / 79 / 0.0346 | 5.3% / 1 / 0.0347 | 18.5% / 71 / **0.0342** |
368
- | distance | 10.2% / 45 / 0.0039 | 5.6% / 0 / 0.0041 | 10.3% / 1 / 0.0039 |
369
- | foliage | 40.8% / 3,004 / 0.0234 | 18.7% / 569 / 0.0256 | 41.0% / 1,725 / **0.0221** |
370
- | combine | 79.1% / 22 / **0.0041** | 53.8% / 0 / 0.0052 | 41.6% / 13 / 0.0056 |
371
- | sun_in_view | 35.3% / 358 / 0.0104 | 26.1% / 27 / 0.0110 | 48.7% / 542 / **0.0097** |
372
- | **Σ mean \|error\|** | 0.1364 | 0.1505 | **0.1340** |
373
-
374
- - **At the derived defaults** (reach 5, thickness ×1) the trace is the most conservative arm measured. It
375
- adds almost no false shadow (0–1 px in seven scenes), but closes a third to three quarters of what Bend
376
- closes, so it is the least accurate overall.
377
- - **At 64 steps, reach 10, thickness ×4** (≈48 cm reach, 3 cm thickness) it has the lowest summed error.
378
- - Best in five scenes, tied in two.
379
- - Bend stays better at the bases of solid casters (`combine`, `disocclusion`) and on a grazing sun.
380
- - It adds less false shadow than Bend in most scenes (`noise` 3,132 against 5,513, `foliage` 1,725 against
381
- 3,004, `thickness` 21 against 153); `sun_in_view` is the exception (542 against 358).
382
- - **With VSM** (`combine`), 32 steps at reach 10 and thickness ×4 closes 5.1% of 380 gap px with none
383
- false. There is as little to do as in §2.
384
- - **Jitter with TAA** changed nothing before TAA. It closed 53.0% against 53.8% in `combine` and doubled
385
- the frame-to-frame change TAA is left to absorb (2,760 against 1,912). With at most one step per pixel
386
- there is nothing for it to fill in. It stays off.
387
-
388
- ### Cost
389
-
390
- RTX 4090, 1578×802, interleaved in one capture with Bend and the old march as in §3, two runs agreeing:
391
-
392
- | | Sun off screen | Sun on screen |
393
- |---|---|---|
394
- | Bend wavefront | 37.9 µs | 32.8 µs |
395
- | Linear, 32 steps | 80.9 µs | 47.1 µs |
396
- | Linear, 64 steps | 130.0 µs | 73.7 µs |
397
- | Old per-pixel march (60 steps) | 73.7 µs | 53.2 µs |
398
-
399
- Four depth reads a step, against Bend's four a pixel shared through workgroup memory. Fewer pixels march
400
- with the sun ahead, where more of the frame is sky and rays are shorter on screen.
401
-
402
- ### What this changes in §5
403
-
404
- - **The method is the linear trace**, at 64 steps, reach 10 texels and thickness ×4. That setting is at
405
- parity with Bend on accuracy against the sun and has less false shadow on fine detail, for 3.4× the cost:
406
- ~130 µs at 1.27 Mpx, ~210 µs at 1080p on this card.
407
- - **Forks 1, 2 and 4 stand as written.** VSM still leaves too little to close.
408
- - **Fork 3 gets easier.** A per-pixel trace can run inline in the sun's shadow term, as Bevy does, with no
409
- mask texture. It still needs the pixel's depth-buffer coordinate, which volumetrics and water do not
410
- have, so it waits on shader switches all the same.
411
- - **Reuse.** SSR and ReSTIR DI march the HZB (`ffx_sssr_hierarchical_raymarch`), and the water uses its
412
- Newton ray. Moving any of them onto this trace is a decision of its own, not made here; ReSTIR's chunk
413
- records why it chose the HZB over a linear march.
@@ -1,5 +0,0 @@
1
- Useful references:
2
-
3
- * https://github.com/roy-t/MiniRTS/blob/4e9d8b3999513ab11199f7666ae5976e18b192b8/src/MiniEngine.Graphics/Shadows/CascadedShadowMapSystem.cs#L94
4
- * https://github.com/roy-t/MiniRTS/blob/4e9d8b3999513ab11199f7666ae5976e18b192b8/src/MiniEngine.Graphics/Content/Effects/Includes/Shadows.hlsl#L92
5
- * https://github.com/SaschaWillems/Vulkan/blob/master/examples/shadowmappingcascade/shadowmappingcascade.cpp
@@ -1,31 +0,0 @@
1
- Things to try:
2
- * Variable rate shading, shade a few pixels and see if it makes sense to shade more
3
- * First do temporal reprojection, and only then do raycasts using reprojection data
4
- * If reprojection is a success and confidence is high - we can skip casting rays
5
- * Otherwise, we cast a ray with probability proportional to confidence
6
- * Eventually it should converge, but at a fraction of rays cast overall
7
-
8
- Occlusion queries should be single-sided, meaning we should not consider back of a triangle to be occluding.
9
- Considering back side of a triangle as an intersection will cause a lot of false-positives for shadows, TAA jitter will
10
- make those false-positives flicker creating a mess.
11
- So far there's no clear and robust solution to self-occlusion, this seems like the cleanest compromise
12
-
13
- # VRS
14
-
15
- 1. Split image into 16x16 tiles (256 values)
16
- 2. Classify tiles by shading rate (1, 4, 16, 64, 128, 256)
17
- 3. Generate rays for each tile
18
- 4. (optional) Sort rays
19
- 5. Trace rays and write result into texture
20
- 6. Fill gaps (flood fill)
21
- 7. Apply denoising per-tile
22
-
23
- References:
24
-
25
- * Call of Duty paper [TBA]
26
- * [Raytraced Shadows in Call of Duty: Modern Warfare](https://www.youtube.com/watch?v=VXp-HEAw-l4)
27
- * Ray Tracing Gems chapter on shadows [TBA]
28
- * https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/blob/main/docs/techniques/denoiser.md
29
- * [Denoising Raytraced Soft Shadows with FidelityFX (Presented by AMD)](https://www.youtube.com/watch?v=RTtVC-Zk5yI)
30
- * Calisto Protocol
31
- * [Ray-Traced Reflections in Battlefield V](https://www.youtube.com/watch?v=ncUNLDQZMzQ)
@@ -1,9 +0,0 @@
1
- References:
2
-
3
- * https://iquilezles.org/articles/distfunctions/
4
- * https://github.com/gkjohnson/three-mesh-bvh/blob/efce76d488a5875b5d8119c50b5d4c8e00f9d66c/example/utils/RayMarchSDFMaterial.js#L72
5
- * https://github.com/StarsX/SDFTracing/blob/11a1bb9911eae09cb68b4a66c2d25959fb51b460/SDFTracing/Content/Shaders/ConeTrace.hlsli#L24
6
- * https://kosmonautblog.wordpress.com/2017/05/01/signed-distance-field-rendering-journey-pt-1/
7
- * https://github.com/godotengine/godot/blob/a65954894670d3c1f23d7e09c13df9cd0cf534a8/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl#L311
8
- * "Dynamic Occlusion with Signed Distance Fields" by Daniel Wright, Epic Games 2015
9
- * [Radiance Caching for Real-Time Global Illumination](https://www.youtube.com/watch?v=2GYXuM10riw)
@@ -1,5 +0,0 @@
1
- References:
2
-
3
- * https://gpuopen.com/manuals/fidelityfx_sdk/fidelityfx_sdk-page_techniques_brixelizer/
4
- * https://gpuopen.com/fidelityfx-brixelizer/
5
- * https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/tree/main/sdk/include/FidelityFX/gpu/brixelizer
@@ -1,9 +0,0 @@
1
- see [Claybook_Simulation_Raytracing_GDC18](https://www.dropbox.com/scl/fi/5w6mwv24qis7pwco53oxn/Claybook_Simulation_Raytracing_GDC18.pptx?rlkey=11u09sotl5ahdhimmnc6o4rcv&e=1&dl=0)
2
-
3
- Raymarching to perfect intersection using geometric progression:
4
-
5
- ```c
6
- step = d / (1 - (d - d_prev))
7
- ```
8
-
9
- This should take us directly to the surface
@@ -1,12 +0,0 @@
1
- # Virtual Shadow Map
2
-
3
- ## Requirements
4
- * we *don't* want to draw coarse-level tiles for virtual shadow map, unless it will actually be used.
5
- * Drawing a coarse tile, will require us to rasterize larger amount of geometry, plus unused tile will be taking up a physical page
6
-
7
- ## References
8
-
9
- * "Fitted Virtual Shadow Maps" by "Markus Giegl" and "Michael Wimmer"
10
- * "Queried Virtual Shadow Maps" by "Markus Giegl" and "Michael Wimmer"
11
- * How to split frustum : https://stackoverflow.com/questions/28155749/opengl-matrix-setup-for-tiled-rendering
12
- * https://ktstephano.github.io/rendering/stratusgfx/svsm