@woosh/meep-engine 3.60.3 → 3.60.5

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 (514) hide show
  1. package/CHANGELOG.md +2602 -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/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts +3 -0
  9. package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts.map +1 -1
  10. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +6 -0
  11. package/package.json +6 -2
  12. package/src/engine/EngineHarness.d.ts +3 -9
  13. package/src/engine/EngineHarness.d.ts.map +1 -1
  14. package/src/engine/EngineHarness.js +6 -8
  15. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  16. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  17. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  18. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  19. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  21. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  22. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  23. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  27. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  28. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  30. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometryFlags.js +1 -2
  31. package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.d.ts +14 -0
  32. package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.d.ts.map +1 -0
  33. package/src/engine/graphics/ecs/trail3d/TRAIL3D_FADE_LINEAR.js +22 -0
  34. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +19 -3
  35. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  36. package/src/engine/graphics/ecs/trail3d/Trail3D.js +31 -4
  37. package/src/engine/graphics/ecs/trail3d/advance_trail.js +1 -1
  38. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  39. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  40. package/src/engine/graphics/ecs/water/Water.js +8 -0
  41. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts +5 -5
  42. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts.map +1 -1
  43. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +6 -6
  44. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  45. package/src/engine/graphics3/WaterSystem.js +731 -734
  46. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  47. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  48. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  49. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  50. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  51. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  52. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  53. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  54. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  55. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  56. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  57. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  58. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  59. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  60. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  61. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  62. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  63. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  64. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  65. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  66. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  67. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts +10 -0
  68. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts.map +1 -1
  69. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +13 -1
  70. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  71. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  72. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  73. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  74. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  75. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  76. package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +2 -2
  77. package/src/engine/physics/cloth/ecs/cloth_geodesic.js +2 -2
  78. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  79. package/src/shade/playground/probe_clipmap/README.md +1 -0
  80. package/src/shade/playground/probe_clipmap/index.html +5 -0
  81. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  82. package/src/shade/playground/probe_clipmap/main.js +16 -2
  83. package/src/shade/playground/vgeo_scene/README.md +1 -1
  84. package/src/shade/playground/water_refraction/README.md +5 -6
  85. package/src/shade/playground/water_refraction/index.html +1 -1
  86. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  87. package/src/shade/renderer/Renderer.js +7 -5
  88. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +4 -6
  89. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -1
  90. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +34 -36
  91. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +1 -1
  92. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
  93. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +162 -163
  94. package/src/shade/renderer/atmosphere/compute_mie_absorption.d.ts +1 -1
  95. package/src/shade/renderer/atmosphere/compute_mie_absorption.js +1 -1
  96. package/src/shade/renderer/atmosphere/hillaire/ATMOSPHERE_EARTH.js +1 -1
  97. package/src/shade/renderer/atmosphere/hillaire/ATMOSPHERE_PARAMETERS_STRUCT.js +1 -1
  98. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +164 -164
  99. package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +1 -1
  100. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  101. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  102. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  103. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  104. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  105. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  106. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  107. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  108. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +4 -4
  109. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +4 -4
  110. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  111. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  112. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  113. package/src/shade/renderer/geometry/sdf/cards/mesh_cards_raster_pass_descriptor.js +2 -2
  114. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_histogram.d.ts +1 -1
  115. package/src/shade/renderer/geometry/sdf/cards/shader_mesh_cards_histogram.js +1 -1
  116. package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.d.ts +4 -5
  117. package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.d.ts.map +1 -1
  118. package/src/shade/renderer/geometry/sdf/chunk_blas_query_band_sdf.js +6 -7
  119. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  120. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  121. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  122. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  123. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  124. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  125. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  126. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  127. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +2 -8
  129. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  130. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  131. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  132. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +12 -0
  133. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  134. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +22 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +4 -4
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +50 -13
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +6 -0
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +7 -0
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts +13 -0
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.d.ts.map +1 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP_RESAMPLING.js +13 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +20 -0
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.d.ts +18 -0
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.d.ts.map +1 -0
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_resampled.js +42 -0
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +5 -4
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +4 -0
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +13 -2
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts +52 -0
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.d.ts.map +1 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_resample.js +250 -0
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  163. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  164. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  165. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  166. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  167. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  168. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  169. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  170. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  171. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  172. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  173. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  174. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  175. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  176. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  177. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  178. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  179. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  180. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  181. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  182. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  183. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  184. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  185. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  186. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  187. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  188. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  189. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  190. package/src/shade/renderer/light/environment/environment_level_1_blur_plan.d.ts +39 -0
  191. package/src/shade/renderer/light/environment/environment_level_1_blur_plan.d.ts.map +1 -0
  192. package/src/shade/renderer/light/environment/environment_level_1_blur_plan.js +119 -0
  193. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +15 -7
  194. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  195. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +66 -83
  196. package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts.map +1 -1
  197. package/src/shade/renderer/light/environment/graph_filter_environment_map.js +15 -6
  198. package/src/shade/renderer/light/environment/shader_blur_environment_map.d.ts +3 -0
  199. package/src/shade/renderer/light/environment/shader_blur_environment_map.d.ts.map +1 -0
  200. package/src/shade/renderer/light/environment/shader_blur_environment_map.js +111 -0
  201. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.d.ts +3 -0
  202. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.d.ts.map +1 -0
  203. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_blurred.js +128 -0
  204. package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
  205. package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +0 -1
  206. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  207. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  208. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  209. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  210. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  211. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  212. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  213. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -3
  214. package/src/shade/renderer/postprocess/nss/NSS.d.ts.map +1 -1
  215. package/src/shade/renderer/postprocess/nss/NSS.js +1 -3
  216. package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.d.ts +5 -6
  217. package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.d.ts.map +1 -1
  218. package/src/shade/renderer/postprocess/nss/NSS_NETWORK_SCHEMA.js +9 -10
  219. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.d.ts.map +1 -1
  220. package/src/shade/renderer/postprocess/nss/shader_nss_extract_feedback.js +48 -49
  221. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.d.ts.map +1 -1
  222. package/src/shade/renderer/postprocess/nss/shader_nss_postprocess.js +12 -16
  223. package/src/shade/renderer/postprocess/nss/shader_nss_preprocess.js +246 -246
  224. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts +1 -2
  225. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts.map +1 -1
  226. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.js +34 -35
  227. package/src/shade/renderer/shader/chunk/atmosphere/C_MIE_SCATTERING_DECLARATION.d.ts +2 -2
  228. package/src/shade/renderer/shader/chunk/atmosphere/C_MIE_SCATTERING_DECLARATION.js +2 -2
  229. package/src/shade/renderer/shader/chunk/atmosphere/chunk_compute_extinction.js +1 -1
  230. package/src/shade/renderer/shader/chunk/atmosphere/hillaire/DENSITY_PROFILE_LAYER_STRUCT.d.ts +1 -1
  231. package/src/shade/renderer/shader/chunk/atmosphere/hillaire/DENSITY_PROFILE_LAYER_STRUCT.js +1 -1
  232. package/src/shade/renderer/shader/chunk/brdf/fresnel/chunk_F_Schlick.d.ts +3 -3
  233. package/src/shade/renderer/shader/chunk/brdf/fresnel/chunk_F_Schlick.js +3 -3
  234. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts +9 -10
  235. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.d.ts.map +1 -1
  236. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_aces_ue_matrices.js +9 -10
  237. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.d.ts +4 -4
  238. package/src/shade/renderer/shader/chunk/color/tonemap/aces/chunk_tonemap_ue_filmic.js +5 -5
  239. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts +1 -2
  240. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.d.ts.map +1 -1
  241. package/src/shade/renderer/shader/chunk/math/chunk_f16_round_stochastic.js +1 -2
  242. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.d.ts +14 -1
  243. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.d.ts.map +1 -1
  244. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec2.js +19 -6
  245. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.d.ts +10 -1
  246. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.d.ts.map +1 -1
  247. package/src/shade/renderer/shader/chunk/noise/chunk_stbn_sample_vec3.js +14 -6
  248. package/src/shade/renderer/shader/chunk/random/murmur/chunk_murmur3_vec3u.d.ts +1 -1
  249. package/src/shade/renderer/shader/chunk/random/murmur/chunk_murmur3_vec3u.js +1 -1
  250. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  251. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  252. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.d.ts +2 -3
  253. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.d.ts.map +1 -1
  254. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_DYNAMIC_LOD_BIAS.js +7 -8
  255. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_LOAD_FACTOR.d.ts +1 -1
  256. package/src/shade/renderer/shadow/vsm/DEFAULT_VSM_MAX_LOAD_FACTOR.js +12 -12
  257. package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts +2 -2
  258. package/src/shade/renderer/shadow/vsm/VSMPageManager.d.ts.map +1 -1
  259. package/src/shade/renderer/shadow/vsm/VSMPageManager.js +3 -4
  260. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  261. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  262. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  263. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  264. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  265. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  266. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  267. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  268. package/src/shade/renderer/water/shader_water.js +22 -13
  269. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  270. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  271. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  272. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  273. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  274. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +0 -19
  275. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
  276. package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +2 -52
  277. package/editor/REWORK_PLAN_2026_08.md +0 -692
  278. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  279. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  280. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  281. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  282. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  283. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  284. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  285. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  286. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  287. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  288. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  289. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  290. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  291. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  292. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  293. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  294. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  295. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  296. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  297. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  298. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  299. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  300. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  301. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  302. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  303. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  304. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  305. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  306. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  307. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  308. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  309. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  310. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  311. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  312. package/src/REVIEW_2026_08_06/generation.md +0 -176
  313. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  314. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  315. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  316. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  317. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  318. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  319. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  320. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  321. package/src/REVIEW_2026_08_06/view.md +0 -667
  322. package/src/REVIEW_2026_08_06.md +0 -610
  323. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  324. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  325. package/src/core/bvh8/NOTES.md +0 -63
  326. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  327. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  328. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  329. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  330. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  331. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  332. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  333. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  334. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  335. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  336. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  337. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  338. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  339. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  340. package/src/engine/REVIEW_2026_07_03.md +0 -211
  341. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  342. package/src/engine/control/first-person/DESIGN.md +0 -658
  343. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  344. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  345. package/src/engine/control/first-person/TODO.md +0 -160
  346. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  347. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  348. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  349. package/src/engine/ecs/ik/PLAN.md +0 -179
  350. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  351. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  352. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  353. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  354. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  355. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  356. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  357. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  358. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  359. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  360. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  361. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  362. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  363. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  364. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  365. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  366. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  367. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  368. package/src/engine/physics/cloth/PLAN.md +0 -3056
  369. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  370. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  371. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  372. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  373. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  374. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  375. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  376. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  377. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  378. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  379. package/src/format/image/avif/DECISIONS.md +0 -545
  380. package/src/format/image/jpeg/NOTES.md +0 -3
  381. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  382. package/src/generation/COORDINATES.md +0 -54
  383. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  384. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  385. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  386. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  387. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  388. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  389. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  390. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  391. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  392. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  393. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  394. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  395. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  396. package/src/shade/RENDERER_CONTRACT.md +0 -697
  397. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  398. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  399. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  400. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  401. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  402. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  403. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  404. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  405. package/src/shade/renderer/NOTES.md +0 -78
  406. package/src/shade/renderer/PLAN.md +0 -8
  407. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  408. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  409. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  410. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  411. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  412. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  413. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  414. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  415. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  416. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  417. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  418. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  419. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  420. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  421. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  422. package/src/shade/renderer/camera/orbital/README.md +0 -81
  423. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  424. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  425. package/src/shade/renderer/camera/orbital/index.js +0 -9
  426. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  427. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  428. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  429. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  430. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  431. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  432. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  433. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  434. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  435. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -483
  436. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  437. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  438. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  439. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  440. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  441. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  442. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  443. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -536
  444. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  445. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4225
  446. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  447. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  448. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  449. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  450. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  451. package/src/shade/renderer/hiz/NOTES.md +0 -3
  452. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  453. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  454. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  455. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  456. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  457. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts +0 -13
  458. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.d.ts.map +0 -1
  459. package/src/shade/renderer/light/environment/shader_convolve_reflection_map_from_averages.js +0 -198
  460. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  461. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  462. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  463. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  464. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -283
  465. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  466. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  467. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  468. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  469. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  470. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -339
  471. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  472. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  473. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  474. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  475. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  476. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  477. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  478. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  479. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  480. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  481. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  482. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  483. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -394
  484. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -160
  485. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  486. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  487. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  488. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  489. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  490. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  491. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  492. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  493. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  494. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -932
  495. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  496. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  497. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  498. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  499. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  500. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  501. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  502. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  503. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  504. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  505. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -4
  506. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  507. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  508. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  509. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  510. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  511. package/src/shade/wgsl/NOTES.md +0 -4
  512. package/src/view/elements/progress/segmented/segment_frame_transform.d.ts +0 -15
  513. package/src/view/elements/progress/segmented/segment_frame_transform.d.ts.map +0 -1
  514. package/src/view/elements/progress/segmented/segment_frame_transform.js +0 -69
@@ -1,490 +0,0 @@
1
- # Path Tracer — Correctness Review 001 & Action Plan
2
-
3
- Scope: the CPU (JavaScript) unidirectional path tracer rooted at `PathTracer.js`, plus its
4
- scene / BVH / material / sampling support code in this directory and the core geom/math
5
- primitives it depends on.
6
-
7
- Goal of this document: catalogue the **major correctness** defects (wrong light transport,
8
- wrong pixels, crashes) and give a concrete, prioritised remediation plan. Style/perf/feature
9
- polish is out of scope except where it crosses into correctness.
10
-
11
- Method: a multi-agent review fanned out across seven dimensions (integrator math, sampling/PDF,
12
- geometry/intersection, BVH/traversal/transforms, materials/textures, numerical robustness, and a
13
- holistic end-to-end pass). Every candidate finding was then **independently re-read and
14
- adversarially verified** by a separate skeptic before being accepted here. 31 findings were
15
- confirmed; 10 were checked and dismissed (see [§7](#7-checked-and-dismissed-not-bugs)).
16
-
17
- The integrator's intended design is taken as a given (and is correct as a design): cosine-weighted
18
- hemisphere sampling for a Lambertian lobe + next-event estimation (NEE) for analytic
19
- directional/point lights; **no MIS, no specular/transmission, no emitter sampling**. The findings
20
- below are defects *relative to that design*, not requests to change the design — except where a gap
21
- in the design itself (emissive, environment GI) silently drops energy.
22
-
23
- ---
24
-
25
- ## 0. Status (applied 2026-06-19)
26
-
27
- **Applied:** F1 (RR compensation), F2 (NEE 1/π), F3 (environment on every miss), F4 (UV order),
28
- F5 (sRGB→linear for textures + tints — `StandardTexture.decode_sRGB` boolean, set from
29
- `texture.encoding` in `MaterialConverter` so the three.js dependency stays at that boundary), F6
30
- (transpose-adjugate **normal matrix** — new `core/geom/3d/mat4/m4_compute_normal_matrix3.js`, cached
31
- on `PathTracedMesh`, used for both shading and geometric normals), F8 (point-light shadow `tMax`),
32
- F9 (emissive `L_e` on hit; `tmp_0` widened to 9), F10 (coordinate-scaled self-occlusion offset),
33
- F13 (`occluded` → `false`), F14 (`getBiasedNormalSample` honors `out_offset`).
34
-
35
- Regression gate added: `PathTracer.spec.js` (normal-matrix correctness, white-furnace energy
36
- conservation, primary-miss background). All path-tracer + touched-core specs pass.
37
-
38
- **Dropped on review** (defensive guards against conditions that can only mean an upstream bug —
39
- masking them hides the real defect, so they were reverted; see [§7](#7-checked-and-dismissed-not-bugs)):
40
- - **F11** (`float_to_uint8` non-finite guard + driver sample rejection) — if the tracer emits
41
- NaN/Inf the tracer is buggy; surface it, don't average around it.
42
- - **F15** (`getCosineDirection` antipode guard) — unreachable for a unit normal and well-behaved RNG.
43
- - **F18** (orthonormal-basis zero guard) — unreachable for a non-zero input; and a non-unit input
44
- produces a broken basis regardless. Replaced with a JSDoc **unit-vector precondition** instead.
45
-
46
- **Deferred (with rationale):**
47
- - **F7** (tone mapping) — driver-only display feature; best done together with exposure re-tuning
48
- after the π-scale change settles.
49
- - **F12** (metallic-roughness BRDF) — a feature, not a bug; the Lambertian path is correct. Wants
50
- its own design pass (likely with MIS and a real `scattering_pdf`).
51
- - **F16** (`aabb3_intersects_ray_segment` `0·Inf`) — shared hot primitive backing physics BVH /
52
- determinism gates; broad blast radius, needs its own change + spec. Left untouched here.
53
- - **F17** (top-level scratch overflow) — proper fix is an explicit-stack traversal or a bounded
54
- shared query; a defensive `undefined` guard would be a bandaid. Deferred.
55
- - **F19** (shading-normal hemisphere guard) — minor approximation refinement, optional.
56
-
57
- Note: F2 darkens direct lighting by π and F5 darkens sRGB textures — scene light intensities tuned
58
- against the old renderer will need re-tuning (and F7 tone mapping helps here).
59
-
60
- ---
61
-
62
- ## 1. Severity summary
63
-
64
- | # | Severity | Area | Issue | Primary location |
65
- |---|----------|------|-------|------------------|
66
- | F1 | **High** | Integrator | Russian roulette never re-weights survivors by `1/p_survive` → all indirect GI biased dark | `PathTracer.js:66-75` |
67
- | F2 | **High** | Integrator | NEE direct lighting omits the Lambertian `1/π` BRDF factor → direct light ~π× too bright vs. indirect | `PathTracedScene.js:542-547,597-602` |
68
- | F3 | **High** | Integrator | Environment/background is broken: primary-miss does `multiply` against a zero accumulator, and mid-path misses add nothing → sky never contributes | `PathTracer.js:77-83,111-118` |
69
- | F4 | **High** | Materials | Normal map sampled at the *previous* hit's UV (stale module-static `texture_uv`) | `texture/sample_material.js:91` vs `:113` |
70
- | F5 | **High** | Materials | sRGB base-color textures & color tints used without sRGB→linear decode → over-bright, compounds per bounce | `material/StandardTexture.js:60-87`, `material/MaterialConverter.js` |
71
- | F6 | **High→Med** | Geometry | Normals transformed by `M` instead of `(M⁻¹)ᵀ` → wrong under non-uniform scale | `texture/sample_material.js:89`, `ray_hit_apply_transform.js:29` |
72
- | F7 | **High** *(driver)* | Output | No tone-mapping before the sRGB OETF → HDR clips harshly to white + per-channel hue shift | `prototypePathTracer.js:486-494` |
73
- | F8 | **Medium** | Lighting | Point-light shadow ray uses `tMax = radius` instead of `distance_to_light` → false shadows from geometry *behind* the light | `PathTracedScene.js:587` |
74
- | F9 | **Medium** | Integrator | Emissive materials are loaded but never emit (`L_e` term missing, not in NEE) → emitters render black | `PathTracer.js:85-108`, `material/MaterialConverter.js:84` |
75
- | F10 | **Medium** | Robustness | Fixed `0.00001` self-intersection offset is below Float32 ULP at large scene scale (and is applied along the scatter dir, not the normal) → shadow/contact acne | `PathTracer.js:95` |
76
- | F11 | **Medium** | Robustness | A single NaN/Inf sample poisons the whole pixel average → black (or white) speckle | `prototypePathTracer.js:478-488`, `core/binary/float_to_uint8.js` |
77
- | F12 | **Medium** | Materials | `metalness`/`roughness` loaded but ignored — every surface is Lambertian (no Fresnel/GGX) | `material/MaterialConverter.js:80-83`, `material/StandardMaterial.js` |
78
- | F13 | **Low** | BVH | `BufferedGeometryBVH.occluded` returns `-1` (truthy) for empty geometry → empty mesh reported as an occluder | `BufferedGeometryBVH.js:176` |
79
- | F14 | **Low** | Sampling | `getBiasedNormalSample` writes to a hardcoded offset `3`, ignoring its `out_offset` param (latent public-API bug) | `sampling/getBiasedNormalSample.js:43` |
80
- | F15 | **Low** | Sampling | `getCosineDirection` yields NaN when the sampled sphere point is the antipode of the normal | `sampling/getCosineDirection.js:33-41` |
81
- | F16 | **Low** | Core/BVH | `aabb3_intersects_ray_segment`: `0*Inf = NaN` for an axis-parallel ray whose origin lies on a slab plane → missed hit/occluder | `core/.../aabb3_intersects_ray_segment.js:41-62` |
82
- | F17 | **Low** | BVH | Top-level candidate scratch array (4096) has no overflow guard → silent corruption / undefined deref crash if a ray crosses >4096 mesh AABBs | `PathTracedScene.js:47,393-408,437-453` |
83
- | F18 | **Low** | Robustness | Zero-length normal → `1/length(0)` → NaN basis in `v3_orthonormal_matrix_from_normal` (narrow, mostly contained downstream) | `core/geom/vec3/v3_orthonormal_matrix_from_normal.js:26` |
84
- | F19 | **Low** | Shading | Perturbed (normal-mapped) shading normal has no geometric-normal hemisphere guard → grazing-angle light leak/darkening | `texture/sample_material.js:102-106` |
85
-
86
- Library vs. tooling note: per project convention, `prototypePathTracer.js` is an internal
87
- prototype/driver tool and `PathTracer.js`/`PathTracedScene.js`/etc. are public library surface.
88
- F7 and the driver half of F11 live in the prototype; everything else is library code. Unreferenced
89
- exports (e.g. `getCosineDirection`, `make_sky_*`, `raycast`) are still public surface — fix, don't
90
- delete.
91
-
92
- ---
93
-
94
- ## 2. The radiometric core (fix these first)
95
-
96
- These three are small, surgical edits in the integrator, but they define whether the renderer is
97
- energy-correct at all. They should be done together and locked with a regression test
98
- ([§6](#6-testing--validation)).
99
-
100
- ### F1 — Russian roulette has no survival compensation (bias / global GI darkening)
101
-
102
- `PathTracer.js:66-75`. For `i >= min_bounce` the path is killed with probability
103
- `RUSSIAN_ROULETTE_PROBABILITY = 0.5`, but on **survival** the throughput `color_mask` is never
104
- divided by the survival probability `(1 - 0.5)`. The only write to `color_mask` is the albedo
105
- multiply at `PathTracer.js:88`.
106
-
107
- Why it's wrong: RR is unbiased only if survivors are scaled by `1/p_survive` so that
108
- `E = p_survive·(value/p_survive) = value`. Without it, every contribution gathered at or after a
109
- surviving RR step is attenuated by `0.5` per step (bounce 2 → ×0.5, bounce 3 → ×0.25, …). With the
110
- driver's `min_bounce=1`, directly-visible surfaces' direct light (`i=0`) is correct, but **all
111
- multi-bounce indirect light converges to a too-dark answer** — a true bias, not noise.
112
-
113
- Fix: inside the `if (i >= min_bounce)` block, after the terminate test passes, multiply
114
- `color_mask` by `1 / (1 - RUSSIAN_ROULETTE_PROBABILITY)` (= 2 for the current constant). Placement
115
- matters — it must be inside the `i >= min_bounce` guard (only when RR actually ran), before the
116
- trace/accumulate for that iteration, so both the NEE term and onward throughput carry the factor.
117
-
118
- ```js
119
- if (i >= min_bounce) {
120
- if (random() < RUSSIAN_ROULETTE_PROBABILITY) {
121
- break; // terminate
122
- }
123
- const inv_survive = 1 / (1 - RUSSIAN_ROULETTE_PROBABILITY);
124
- color_mask[0] *= inv_survive;
125
- color_mask[1] *= inv_survive;
126
- color_mask[2] *= inv_survive;
127
- }
128
- ```
129
-
130
- Optional follow-up (variance, not correctness): make `p_survive` depend on `max(color_mask)`
131
- (throughput-based RR). Strictly better, but not required to remove the bias. Also note `max_bounce`
132
- hard-truncates surviving paths at the cap without RR there — a much smaller, separate residual bias.
133
-
134
- ### F2 — NEE omits the Lambertian `1/π` (direct vs. indirect imbalance of π)
135
-
136
- `PathTracedScene.js:542-547` (directional) and `:597-602` (point). The NEE contribution is
137
- `light_color · dotNL · intensity` (× attenuation for point), accumulated as
138
- `color_mask · tmp_0` at `PathTracer.js:104-106`. `color_mask` already carries the albedo, so the
139
- direct term is `albedo · L · cosθ` — but the physical Lambertian result is
140
- `(albedo/π) · L · cosθ`. The `1/π` is missing.
141
-
142
- Why it's wrong, and why it's specifically an *imbalance*: the **indirect** path is already
143
- self-consistent for `BRDF = albedo/π` — cosine sampling gives `pdf = cosθ/π`, so
144
- `BRDF·cosθ/pdf = albedo`, exactly what `color_mask *= albedo` (`PathTracer.js:88`) does. The
145
- indirect path implicitly carries the `1/π`; NEE does not. So direct lighting is π (~3.14×) too
146
- bright *relative to* bounced lighting that shares the same surface. The engine's own intended
147
- convention confirms this: `StandardMaterial.scattering_pdf` returns `cosθ · PI_RECIPROCAL` (it's
148
- just commented out at its call site, `PathTracedScene.js:365-369`).
149
-
150
- Fix: fold `PI_RECIPROCAL` (`core/math/PI_RECIPROCAL.js`) into `intensity` in both light branches:
151
-
152
- ```js
153
- const intensity = dotNL * light.intensity.getValue() * PI_RECIPROCAL; // directional
154
- const intensity = dotNL * light.intensity.getValue() * attenuation * PI_RECIPROCAL; // point
155
- ```
156
-
157
- Do **not** touch `PathTracer.js:88` — the indirect throughput already cancels the `1/π`. This will
158
- darken direct lighting by π, so any light intensities tuned against the buggy renderer will need
159
- rescaling. Validate with a constant-albedo white-furnace test ([§6](#6-testing--validation)).
160
-
161
- ### F3 — Environment/background contribution is broken (primary miss + mid-path miss)
162
-
163
- Two coupled defects, best fixed together:
164
-
165
- 1. **Primary miss multiplies against zero** — `PathTracer.js:111-118`. With `min_bounce=1`, the
166
- only way to exit the loop with `i === 0` is a primary-ray miss; at that point `irradiance` is
167
- still `[0,0,0]`. The branch then does `vec3.multiply(irradiance, irradiance, tmp_0)` =
168
- `0 · sky = 0`. The sky radiance sampled into `tmp_0` is discarded — a missed primary ray is
169
- always black, for **any** background. The correct op is an **assignment** (radiance along a
170
- missed primary ray *equals* the environment radiance).
171
- 2. **Mid-path misses drop the environment entirely** — `PathTracer.js:77-83`. When a bounce ray
172
- (`i > 0`) escapes, the loop just `break`s, never adding `color_mask · sky`. So the sky never acts
173
- as a light source; surfaces receive only the analytic lights, zero environment GI.
174
-
175
- Currently masked: the default `__background_sampler = make_vector3(0,0,0)` (`PathTracedScene.js:103`)
176
- is black and is never reassigned in shipped code, so `0·0` and `0+0` both look correct today. The
177
- defect becomes visible the moment a real sky (`make_sky_rtiw` / `make_sky_hosek` — which exist for
178
- exactly this) is wired into the public `__background_sampler`. It is unambiguously wrong logic and
179
- should be fixed even though it is currently dormant.
180
-
181
- Fix (unifies both): handle the miss inside the loop and delete the `i === 0` post-loop block:
182
-
183
- ```js
184
- const hit_distance = scene.trace(trace_result, _ray_0);
185
- if (hit_distance < 0) {
186
- // ray escaped — accumulate throughput-weighted environment radiance
187
- scene.sample_background(tmp_0, 0, _ray_0, 3);
188
- irradiance[0] += color_mask[0] * tmp_0[0];
189
- irradiance[1] += color_mask[1] * tmp_0[1];
190
- irradiance[2] += color_mask[2] * tmp_0[2];
191
- break;
192
- }
193
- ```
194
-
195
- At `i=0`, `color_mask` is still `[1,1,1]`, so this reduces to assigning the raw sky (fixing the
196
- multiply-vs-assign); at `i>0` it adds the throughput-weighted environment, restoring sky GI. The
197
- direction at `_ray_0[3..5]` is the correct escaping direction at the moment of the miss (the bounce
198
- overwrite at `:91`/`:101` hasn't run yet for this iteration).
199
-
200
- ---
201
-
202
- ## 3. Material & shading correctness
203
-
204
- ### F4 — Normal map sampled at stale UV (`high`)
205
-
206
- `texture/sample_material.js`. `material.normal.sample(normal, texture_uv[0], texture_uv[1])` runs
207
- at **line 91**, but `texture_uv` (a module-static `[0,0]`) is only filled with *this* triangle's
208
- interpolated UV at **lines 109-118**, which execute afterward. So the tangent-space normal is read
209
- at the *previous* invocation's UV (or `(0,0)` on the first call) — a spatially unrelated texel. The
210
- diffuse sample (`:129`) correctly uses the freshly-computed UV, so only normal-mapped materials are
211
- affected (the default flat normal `[127,127,255]` is skipped by the `:93` distance test, so plain
212
- materials are unaffected). The corrupted shading normal feeds both the NEE cosine term and the
213
- cosine-lobe bounce, and varies with traversal order.
214
-
215
- Fix: move the UV-computation block (current `:109-118`) **above** the normal-map sampling block
216
- (`:91-107`). No other call site depends on the current ordering.
217
-
218
- ### F5 — sRGB albedo not linearized (`high`)
219
-
220
- The live shading path calls `material.diffuse.sample(...)` → `StandardTexture.sample`
221
- (`material/StandardTexture.js:60-87`), which converts uint8→float but performs **no** sRGB→linear
222
- decode and has no `encoding` field at all. `MaterialConverter.#ensure_texture`
223
- (`material/MaterialConverter.js:43-57`) drops `texture.encoding` at conversion time. (The free
224
- function `texture/sample_texture.js` *does* branch on encoding, but its sRGB call is commented out
225
- at `:53` and it is dead code — referenced nowhere.) glTF/three base-color maps are sRGB-authored;
226
- feeding gamma-encoded texels into a linear integrator over-brightens midtones (`0.5` sRGB ≈ `0.214`
227
- linear) and the error **compounds multiplicatively per bounce** via `color_mask` (`PathTracer.js:88`).
228
- Flat `material.color` tints (`MaterialConverter.js:92-100`) are likewise not linearized.
229
-
230
- Fix (must be **selective** — only sRGB-authored channels):
231
- - Add an `encoding` field to `StandardTexture` (default `LinearEncoding`); set it in
232
- `MaterialConverter.#ensure_texture` from `texture.encoding`.
233
- - In `StandardTexture.sample`, apply `sRGB_to_linear` (`core/color/sRGB/sRGB_to_linear.js`) only
234
- when `encoding === sRGBEncoding`, after the uint8→float step. **Do not** linearize
235
- normal/metalness/roughness — those are data textures and would be corrupted.
236
- - Linearize `material.color` before `sampler2d_multiply_vector` in the tint path.
237
-
238
- ### F6 — Normals use `M`, not the inverse-transpose (`high` for shading normal under non-uniform scale)
239
-
240
- `texture/sample_material.js:89` rotates the **shading** normal by the forward model matrix
241
- `mesh.transform`; `ray_hit_apply_transform.js:29` does the same for the **geometric** normal. Both
242
- funnel into `v3_matrix4_rotate` (applies the upper-left 3×3 of `M`, then renormalizes). A normal is
243
- a covector and must transform as `(M⁻¹)ᵀ·n`. For rotation + uniform scale + translation these agree
244
- up to a positive scalar (killed by the renormalize), so the **common case is correct** — but under
245
- **any non-uniform scale/shear** `M·n` is no longer perpendicular to the transformed surface, and
246
- renormalization fixes only length, not direction. The skewed shading normal mis-aims both the
247
- cosine sampling lobe and the NEE `dotNL`; at strong non-uniform scale the skewed *geometric* normal
248
- can even flip the back-face sign test (`PathTracedScene.js:355-363`), flipping shading to the wrong
249
- hemisphere (black/wrong shading).
250
-
251
- Reachability: `createMesh` accepts an arbitrary `mat4`, and `Transform` supports per-axis scale, so
252
- non-uniform scale enters through the public API. The shipped prototype scenes happen to use uniform
253
- scale, so it's latent there but live for library callers.
254
-
255
- Fix: cache a normal matrix = transpose of the upper-left 3×3 of `#transform_inverse` (already
256
- computed via `mat4.invert` in the transform setter, `PathTracedMesh.js:86`) and use it for both
257
- normal rotations. Add a `v3_array_matrix4_rotate_transpose`-style helper (mind gl-matrix
258
- column-major indexing). The position transform in `ray_hit_apply_transform` must keep using the
259
- forward matrix; only the normal line changes. The geometric-normal site (`ray_hit_apply_transform.js`)
260
- is lower impact (sign test only) but worth fixing for consistency.
261
-
262
- ### F12 — `metalness`/`roughness` ignored; always Lambertian (`medium`)
263
-
264
- `MaterialConverter.js:80-83` assigns these samplers and `StandardMaterial` holds them, but nothing
265
- in shading reads them — the only BRDF is the cosine diffuse lobe. Metals render as colored diffuse;
266
- all gloss/specular/Fresnel is absent; energy is mis-distributed for any PBR asset. Note: the
267
- existing Lambertian path is itself *correct* — this is an unimplemented-feature gap, not a math
268
- error. The loaded data is currently dead.
269
-
270
- Fix (larger): implement a metallic-roughness BRDF (Lambert diffuse scaled by `1-metalness` + GGX/
271
- Cook-Torrance specular with Fresnel-Schlick, `F0 = mix(0.04, albedo, metalness)`), read
272
- metalness/roughness in `sample_material`, importance-sample the chosen lobe, and re-enable a real
273
- `scattering_pdf` division in the integrator. If out of scope now, **document** that only Lambertian
274
- diffuse is supported so the dead metalness/roughness inputs aren't mistaken for active. See also the
275
- emitter/MIS gap (F9) — a proper specular path usually wants MIS.
276
-
277
- ### F19 — Perturbed shading normal lacks a geometric-normal guard (`low`)
278
-
279
- `texture/sample_material.js:102-106`. The normal-mapped shading normal becomes the sole normal for
280
- both sampling and NEE, with no check that it stays in the geometric upper hemisphere. Strong normal
281
- maps at grazing angles can send bounce/NEE directions below the true surface → localized leak/
282
- darkening. Standard minor approximation; only matters with real normal maps. Optional: retain the
283
- geometric normal (`hit[3..5]`) and clamp/guard directions against it.
284
-
285
- ---
286
-
287
- ## 4. Lighting, geometry & robustness
288
-
289
- ### F8 — Point-light shadow ray `tMax = radius` (`medium`; production-relevant)
290
-
291
- `PathTracedScene.js:587`. The occlusion ray for a point light is bounded by the light's influence
292
- `radius`, but the surface-to-light distance is `distance_to_light` (`:556`), and the cull at `:560`
293
- guarantees `radius >= distance_to_light`. So the visibility test searches **past** the light:
294
- geometry between `distance_to_light` and `radius` (i.e. *behind* the light) is counted as an
295
- occluder, producing spurious shadows / over-darkening. Point lights are used in the production ECS
296
- path (`populate_path_traced_scene_from_ecd.js`), so this is not prototype-only.
297
-
298
- Fix: `_ray_1.tMax = distance_to_light;` (optionally `- eps`). Keep `radius` strictly for the
299
- attenuation cutoff. The directional branch (`tMax = Infinity`, `:533`) is already correct.
300
-
301
- ### F9 — Emissive surfaces never emit (`medium`)
302
-
303
- The bounce loop accumulates only NEE + (broken) background; there is no `L_e` term on hits, and NEE
304
- doesn't sample emitters. Emissive maps are parsed and cached (`MaterialConverter.js:84`,
305
- `StandardMaterial.js:19`) but read by nothing. Any mesh whose light output is its emissive map
306
- renders black — common in glTF assets.
307
-
308
- Fix: sample `material.emissive` in `sample_material` into **separate** output slots (not the albedo
309
- slots), plumb it through the `PathTracedScene.sample_material` wrapper, and in `path_trace` add
310
- `irradiance += color_mask · emissive` **before** `color_mask` is multiplied by this surface's albedo
311
- (`:88`) — otherwise the emitter's glow gets tinted by its own albedo. Because there's no MIS and no
312
- emitter NEE, a plain `L_e`-on-hit term is the correct, non-double-counting choice. Note: `tmp_0` is
313
- `Float32Array(6)` (`PathTracer.js:24`) and must be widened (e.g. to 9) or a separate scratch used.
314
-
315
- ### F10 — Self-intersection epsilon too small at scale (`medium`)
316
-
317
- `PathTracer.js:95` nudges the new origin by a fixed `0.00001` along the **new ray direction**, on a
318
- Float32 ray (`Ray3` extends `Float32Array`). Float32 ULP at coordinate magnitude `C` is
319
- ≈ `C·1.2e-7`; at `|C|≈1000` that's ≈ `1.2e-4` > `1e-5`, so the nudge rounds away and the secondary/
320
- shadow ray re-spawns on the surface → acne/leaks. There is no `tMin` backstop anywhere (leaf tests
321
- use bare `t > 0`). The offset is also applied along the scatter direction (near-tangent for grazing
322
- cosine samples), shrinking the effective normal-escape further. Large scenes (`prepare_scene_lucy`:
323
- ground `y=-800`, camera `z=-2300`) hit this; the currently-active `prepare_sponza` (~5 units) does
324
- not.
325
-
326
- Fix (preferred): carry a real `tMin` in the ray and reject `t <= tMin` in the leaf tests
327
- (`BufferedGeometryBVH.js:260,408`) and the AABB lower bound, with `tMin` scaled to coordinate
328
- magnitude. This also fixes the NEE shadow ray without depending on origin precision. Alternatively,
329
- offset along the **geometric normal** by a magnitude-relative amount
330
- (`max(1e-4, 1e-5·max(|x|,|y|,|z|))`). The offset must be applied in world space (before the
331
- transform-to-local).
332
-
333
- ### F11 — One NaN/Inf sample poisons the whole pixel (`medium`)
334
-
335
- `prototypePathTracer.js:478-488` accumulates into plain JS arrays with no finiteness guard; one bad
336
- sample makes the 16-sample average NaN/Inf. `core/binary/float_to_uint8.js` returns `NaN` for `NaN`
337
- (both range comparisons are false), which coerces to `0` in the `Uint8ClampedArray` → a pure-black
338
- pixel (`+Inf` → white). NaN is reachable via degenerate normals (F18) and the AABB `0*Inf` case
339
- (F16); Inf via unbounded radiance.
340
-
341
- Fix (two layers): (1) **library** — harden `float_to_uint8` so non-finite input maps to `0`
342
- explicitly (protects all callers). (2) **driver** — in the sample loop, skip non-finite
343
- `pixel_color` samples and divide by the count of valid samples (skipping keeps the estimate
344
- unbiased; clamping-to-zero would bias dark). Deeper root cause is preventing NaN generation (F18).
345
-
346
- ### F13 — `occluded` returns `-1` for empty geometry (`low`)
347
-
348
- `BufferedGeometryBVH.js:176` returns `-1` (truthy) when the BVH root is `NULL_NODE`, despite the
349
- documented boolean contract. `PathTracedScene.occluded` (`:408`) treats it as occluded, so an
350
- empty-geometry mesh among the shadow-ray candidates wrongly shadows the point (silent darkening).
351
- Reachable (no polycount guard in `addMesh`) but practically rare (the empty mesh's degenerate AABB
352
- usually fails the top-level slab test first). Fix: `return false;`. (Distinct from `raycast2`/
353
- `raycast`, which use `-1` as a numeric no-hit sentinel — those are fine.)
354
-
355
- ### F16 — `aabb3_intersects_ray_segment`: `0*Inf = NaN` on slab-coplanar axis-parallel rays (`low`)
356
-
357
- `core/geom/3d/aabb/aabb3_intersects_ray_segment.js:41-62`. Callers pass `1/direction`; a zero axis
358
- gives `±Inf`, and if the origin is exactly on that box face, `(box-origin)*inv = 0*Inf = NaN`.
359
- `max2` propagates NaN, so the segment test returns a false miss → skipped subtree → missed hit/
360
- occluder (speckle / missing shadow caster). Shared by all BVH traversal (`bvh_query_*`), so
361
- engine-wide, but requires two exact-`0.0` coincidences, hence rare and low.
362
-
363
- Fix: handle the parallel axis explicitly — branch on `direction_axis === 0` and do a containment
364
- test (`origin` within `[lo,hi]` → unconstrained interval, else miss), or clamp exactly-zero
365
- direction components away from zero before reciprocating. **Note:** a plain "NaN-ignoring min/max"
366
- swap is *insufficient* for the origin-exactly-on-face sub-case (verified) — the surviving non-NaN
367
- bound is itself degenerate. Add spec cases for origin-on-face × axis-aligned direction (all four
368
- face/sign combos).
369
-
370
- ### F17 — Top-level candidate scratch (4096) overflow (`low`)
371
-
372
- `PathTracedScene.js:47` + `trace()`/`occluded()`. `bvh_query_user_data_ray_segment` writes
373
- candidates with no capacity check; a TypedArray write past length is silently dropped while the
374
- returned count keeps incrementing. If a ray crosses >4096 mesh AABBs, the consuming loop reads stale
375
- slots and `meshes.get(...)` → `undefined` → crash on `mesh.hit/occluded`. (The **bottom-level**
376
- active path — `raycast2`/`occluded` — uses an explicit stack and is already overflow-free; the
377
- unused `raycast()` is latent for external callers.)
378
-
379
- Fix: bound the write in `bvh_query_user_data_ray_segment` (protects all callers), or — preferred —
380
- convert the top-level `trace`/`occluded` to the explicit-stack nearest/any traversal used by
381
- `raycast2`/`occluded` (neither needs to materialize all candidates).
382
-
383
- ### F14 / F15 / F18 — small latent sampler/robustness bugs (`low`)
384
-
385
- - **F14** `sampling/getBiasedNormalSample.js:43` writes to a literal offset `3` instead of
386
- `out_offset`. Harmless today (the only caller passes `3`) but wrong for any other caller of this
387
- public function. Fix: `v3_matrix3_rotate(out, out_offset, k0, k1, r_y, mat3)`.
388
- - **F15** `sampling/getCosineDirection.js:37` divides by the summed-vector length with no zero guard;
389
- the antipode (and near-antipode) case yields NaN/garbage. Dead in the integrator but public. Fix:
390
- if length `< 1e-6`, fall back to the normal. (Also rename the misleading `len2` → `inv_len`.)
391
- - **F18** `core/geom/vec3/v3_orthonormal_matrix_from_normal.js:26` does `1/v3_length(o1)` with no
392
- zero guard; a `(0,0,0)` input → NaN basis. Largely contained downstream (`v3_matrix4_rotate`
393
- zeroes degenerate normals, `v3_matrix3_rotate` has a length guard that yields a zero direction),
394
- so worst realistic outcome is a rare prematurely-terminated sample, not NaN pixels. Fix: substitute
395
- a fixed fallback axis when `o1` length ≈ 0.
396
-
397
- ---
398
-
399
- ## 5. Output / display (driver — `prototypePathTracer.js`)
400
-
401
- ### F7 — No tone mapping before the sRGB OETF (`high`, driver-scope)
402
-
403
- `prototypePathTracer.js:486-494`. After averaging, the pipeline is `linear_to_sRGB` →
404
- `float_to_uint8` with **no** tone-mapping operator. `linear_to_sRGB` is the display transfer
405
- function (OETF), not a dynamic-range compressor; for input `> 1` it returns `> 1` and
406
- `float_to_uint8` hard-clamps to 255. Path-traced radiance is unbounded HDR (sponza sun intensity 3,
407
- plus — until F2 lands — unnormalized diffuse direct light), so bright regions collapse to flat white
408
- and per-channel clipping skews hue.
409
-
410
- Fix: insert a tone map between averaging and the OETF — luminance-based Reinhard or a fitted ACES
411
- curve, optionally with an exposure control. Driver-only; does not touch the integrator. (Note F2
412
- will change the lighting scale by π, so add the tone map *after* the radiometric fixes and re-tune
413
- exposure together.)
414
-
415
- ---
416
-
417
- ## 6. Testing & validation
418
-
419
- Per project conventions: run Jest from the repo root `H:/git/moh` using the root `jest.conf.json`;
420
- write **black-box** tests (assert observable radiance, never call counts/private paths); use **real**
421
- objects, not mocks; and follow **correctness-first** (no loosened tolerances to make a test pass).
422
- `assert.*` is stripped in prod, so don't write rejection tests against asserts.
423
-
424
- Recommended new gate (`PathTracer.spec.js` or similar), added as part of Phase 1 so the radiometric
425
- fixes are locked:
426
-
427
- 1. **White-furnace / energy-conservation test.** Constant albedo `a`, uniform environment radiance
428
- `L` (set `__background_sampler` to a constant), no analytic lights, many samples/bounces with RR
429
- on. Expected converged radiance for a Lambertian closed/uniform field is `a·L/(1-a)`-style energy
430
- balance; at minimum, **`a=1` must not lose energy** (converges to `L`, not a darkening series).
431
- This single test catches F1 (RR bias) and F3 (environment GI) regressions.
432
- 2. **Direct-vs-indirect ratio test.** A lit Lambertian plane: compare the NEE direct term against a
433
- path-traced indirect estimate of the same configuration; they must be consistent (catches F2's
434
- π imbalance). A furnace test with a single light also surfaces the missing `1/π`.
435
- 3. **Primary-miss background test.** Non-black `__background_sampler`; a ray that misses must return
436
- the background color (catches F3's multiply-vs-assign).
437
- 4. **Point-light occlusion test.** Occluder placed *behind* the light within `radius`: the shaded
438
- point must remain lit (catches F8).
439
- 5. **AABB slab edge test** (extend `aabb3_intersects_ray_segment.spec.js`): origin exactly on a face
440
- plane with an axis-aligned direction transiting the box — must hit (catches F16).
441
- 6. **Non-finite hardening test** for `float_to_uint8(NaN/±Inf)` → defined finite bytes (F11).
442
-
443
- Reference-image / scene-level checks (`prepare_scene_rtiw`, `gi_box_01`, sponza) are useful for F4–
444
- F7 but are harder to assert numerically; treat them as manual visual confirmation after the unit
445
- gates pass.
446
-
447
- ---
448
-
449
- ## 7. Checked and dismissed (NOT bugs)
450
-
451
- These were raised during review and **verified to be correct** — recorded so they aren't re-flagged:
452
-
453
- - **Non-uniform-scale ray distance handling is correct.** `ray3_interval_array_apply_matrix4`
454
- normalizes the local direction and rescales `tMax`; `PathTracedMesh.hit` recomputes the world
455
- distance via `v3_distance`. Cross-mesh nearest-hit ordering stays consistent under scale.
456
- - **Interpolated/geometric normals *are* renormalized.** `sample_triangle_attribute` and
457
- `construct_ray_hit_from_geometry` produce non-unit normals, but `v3_array_matrix4_rotate`
458
- (→`v3_matrix4_rotate`) renormalizes before any consumer reads them (and zeroes degenerate ones).
459
- The "missing renormalize" concern is unfounded.
460
- - **The Lambertian sampling path is radiometrically correct.** Cosine pdf `cosθ/π` cancels the
461
- `albedo/π` BRDF, leaving `color_mask *= albedo`. `getBiasedNormalSample` (cos^power lobe) and
462
- `random_in_hemisphere` (uniform hemisphere) are both correct.
463
- - **The `_ray_0[3..5]` overload is load-bearing, not dead.** The normal is copied into the direction
464
- slot specifically so NEE's `dotNL` can read it; `getBiasedNormalSample` only overwrites it
465
- *after* NEE. Deleting the copy would break direct lighting.
466
- - **Black default background is an acceptable default**, not a bug (the visible symptom is F3's
467
- multiply logic, not the default value).
468
- - **Point-light windowed inverse-square attenuation is correct** — `radius` is the cutoff/window by
469
- design (matches the production forward+ renderer's `pointLight.distance`).
470
- - **No firefly clamp is by design.** Adding a per-sample radiance clamp would *bias* the estimator;
471
- the attenuation denominator is floored (`max(d², 0.01)`), so NEE cannot produce Inf/NaN.
472
- - **`sample_material` does not read uninitialized albedo** — the `PathTracedScene.sample_material`
473
- wrapper sets `out[0..2] = 1` before calling it.
474
-
475
- ---
476
-
477
- ## 8. Suggested implementation phasing
478
-
479
- 1. **Phase 1 — radiometric core + regression gate.** F1, F2, F3 together, plus the white-furnace /
480
- direct-vs-indirect / primary-miss tests (§6.1–6.3). Small surgical edits; biggest correctness
481
- win. Expect a global brightness change (re-tune any scene light intensities afterward).
482
- 2. **Phase 2 — material/shading correctness.** F4 (stale UV), F5 (sRGB linearization), F6 (normal
483
- inverse-transpose). Visible quality, scene-dependent.
484
- 3. **Phase 3 — lighting & robustness.** F8 (point-light shadow tMax) + test, F9 (emissive), F10
485
- (self-intersection epsilon / tMin), F11 (NaN/Inf hardening).
486
- 4. **Phase 4 — latent / core-primitive hardening.** F13, F14, F15, F16 (+ spec), F17, F18, F19.
487
- Low individual impact; cheap and prevent rare crashes/speckle.
488
- 5. **Phase 5 — bigger features (optional / separate).** F12 (metallic-roughness BRDF, likely with
489
- MIS and a real `scattering_pdf` path), F7 (tone mapping in the driver). Larger design work; do
490
- after the integrator is energy-correct.