@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
@@ -0,0 +1,61 @@
1
+ /**
2
+ * A fragment program drawn over the screen tiles that hold a decal, rather than over the whole
3
+ * screen — what an `ImageShader` is to a full-screen pass, for the decal passes that only need to
4
+ * touch the surfaces a decal could be on.
5
+ *
6
+ * The tiles come from `graph_gather_decal_tiles`, and so does the draw: the instance count is the
7
+ * live tile count, read on the device through an indirect command, so the work follows how much of
8
+ * the screen the decals cover and never the size of the screen.
9
+ *
10
+ * The fragment program is `descriptor`, an ordinary one — it is what the emulator runs and what
11
+ * specs read. The vertex program is {@link chunk_decal_tile_vertex}, compiled against the same
12
+ * resources, so both stages share one layout and the descriptor must declare `decal_tiles` and an
13
+ * immediate `settings` with a `screen_resolution`.
14
+ */
15
+ export class DecalTileShader {
16
+ /**
17
+ * @param {object} options
18
+ * @param {ShaderDescriptor} options.descriptor the fragment program
19
+ * @param {GPUColorTargetState[]} options.targets
20
+ */
21
+ constructor({ descriptor, targets }: {
22
+ descriptor: ShaderDescriptor;
23
+ targets: GPUColorTargetState[];
24
+ });
25
+ /**
26
+ * @returns {ShaderDescriptor}
27
+ */
28
+ get descriptor(): ShaderDescriptor;
29
+ /**
30
+ * @returns {RenderPipelineDescriptor}
31
+ */
32
+ get pipeline(): RenderPipelineDescriptor;
33
+ /**
34
+ * See `ImageShader#pipeline_for`.
35
+ *
36
+ * @param {GPUTextureFormat[]} color_formats
37
+ * @returns {RenderPipelineDescriptor}
38
+ */
39
+ pipeline_for(color_formats: GPUTextureFormat[]): RenderPipelineDescriptor;
40
+ /**
41
+ * Draw over every listed tile.
42
+ *
43
+ * @param {object} options
44
+ * @param {ShadeGPUCommandContext} options.encoder
45
+ * @param {Object} options.bindings
46
+ * @param {GPURenderPassColorAttachment[]} options.colorAttachments
47
+ * @param {GPUTextureFormat[]} options.color_formats
48
+ * @param {GPUBuffer} options.command the tiles' draw command: 6 vertices, one instance per tile
49
+ */
50
+ draw({ encoder, bindings, colorAttachments, color_formats, command }: {
51
+ encoder: ShadeGPUCommandContext;
52
+ bindings: any;
53
+ colorAttachments: GPURenderPassColorAttachment[];
54
+ color_formats: GPUTextureFormat[];
55
+ command: GPUBuffer;
56
+ }): void;
57
+ #private;
58
+ }
59
+ import { ShaderDescriptor } from "../../../shade/renderer/shader/ShaderDescriptor.js";
60
+ import { RenderPipelineDescriptor } from "../../../shade/descriptor/pipeline/render/RenderPipelineDescriptor.js";
61
+ //# sourceMappingURL=DecalTileShader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecalTileShader.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/decal/DecalTileShader.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH;IAkBI;;;;OAIG;IACH;QAHqC,UAAU,EAApC,gBAAgB;QACe,OAAO,EAAtC,qBAAqB;OA8B/B;IAED;;OAEG;IACH,mCAEC;IAED;;OAEG;IACH,yCAEC;IAED;;;;;OAKG;IACH,4BAHW,kBAAkB,GAChB,wBAAwB,CAIpC;IAED;;;;;;;;;OASG;IACH;QAN2C,OAAO;QACvB,QAAQ;QACgB,gBAAgB,EAAxD,8BAA8B;QACF,aAAa,EAAzC,kBAAkB;QACC,OAAO;aA6BpC;;CACJ;iCApIgC,oDAAoD;yCAJ5C,uEAAuE"}
@@ -0,0 +1,138 @@
1
+ import { assert } from "../../../core/assert.js";
2
+ import { RenderPipelineDescriptor } from "../../../shade/descriptor/pipeline/render/RenderPipelineDescriptor.js";
3
+ import {
4
+ rp_validate_and_rewrite_for_color_attachments
5
+ } from "../../../shade/device/pipeline/rp_validate_and_rewrite_for_color_attachments.js";
6
+ import { ShaderDescriptor } from "../../../shade/renderer/shader/ShaderDescriptor.js";
7
+ import { chunk_decal_tile_vertex } from "./chunk_decal_tile_vertex.js";
8
+
9
+ /**
10
+ * A fragment program drawn over the screen tiles that hold a decal, rather than over the whole
11
+ * screen — what an `ImageShader` is to a full-screen pass, for the decal passes that only need to
12
+ * touch the surfaces a decal could be on.
13
+ *
14
+ * The tiles come from `graph_gather_decal_tiles`, and so does the draw: the instance count is the
15
+ * live tile count, read on the device through an indirect command, so the work follows how much of
16
+ * the screen the decals cover and never the size of the screen.
17
+ *
18
+ * The fragment program is `descriptor`, an ordinary one — it is what the emulator runs and what
19
+ * specs read. The vertex program is {@link chunk_decal_tile_vertex}, compiled against the same
20
+ * resources, so both stages share one layout and the descriptor must declare `decal_tiles` and an
21
+ * immediate `settings` with a `screen_resolution`.
22
+ */
23
+ export class DecalTileShader {
24
+ /**
25
+ * @type {ShaderDescriptor}
26
+ */
27
+ #descriptor;
28
+
29
+ /**
30
+ * @type {RenderPipelineDescriptor}
31
+ */
32
+ #pipeline;
33
+
34
+ /**
35
+ * See `ImageShader`'s field of the same name: one device check per device, not one per draw.
36
+ *
37
+ * @type {GPUDevice|null}
38
+ */
39
+ #validated_device = null;
40
+
41
+ /**
42
+ * @param {object} options
43
+ * @param {ShaderDescriptor} options.descriptor the fragment program
44
+ * @param {GPUColorTargetState[]} options.targets
45
+ */
46
+ constructor({ descriptor, targets }) {
47
+ assert.defined(descriptor, 'descriptor');
48
+ assert.isArray(targets, 'targets');
49
+
50
+ this.#descriptor = descriptor;
51
+
52
+ const vertex = ShaderDescriptor.from({
53
+ label: `${descriptor.label} / tiles`,
54
+ resources: descriptor.resources,
55
+ body: chunk_decal_tile_vertex
56
+ });
57
+
58
+ this.#pipeline = RenderPipelineDescriptor.from({
59
+ label: descriptor.label,
60
+ layout: descriptor.resources.generatePipelineLayout(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
61
+ vertex: {
62
+ module: { code: vertex.source },
63
+ entryPoint: 'main',
64
+ },
65
+ fragment: {
66
+ module: { code: descriptor.source },
67
+ targets,
68
+ },
69
+ primitive: {
70
+ topology: 'triangle-list',
71
+ cullMode: 'none',
72
+ },
73
+ });
74
+ }
75
+
76
+ /**
77
+ * @returns {ShaderDescriptor}
78
+ */
79
+ get descriptor() {
80
+ return this.#descriptor;
81
+ }
82
+
83
+ /**
84
+ * @returns {RenderPipelineDescriptor}
85
+ */
86
+ get pipeline() {
87
+ return this.#pipeline;
88
+ }
89
+
90
+ /**
91
+ * See `ImageShader#pipeline_for`.
92
+ *
93
+ * @param {GPUTextureFormat[]} color_formats
94
+ * @returns {RenderPipelineDescriptor}
95
+ */
96
+ pipeline_for(color_formats) {
97
+ return rp_validate_and_rewrite_for_color_attachments(this.#pipeline, color_formats);
98
+ }
99
+
100
+ /**
101
+ * Draw over every listed tile.
102
+ *
103
+ * @param {object} options
104
+ * @param {ShadeGPUCommandContext} options.encoder
105
+ * @param {Object} options.bindings
106
+ * @param {GPURenderPassColorAttachment[]} options.colorAttachments
107
+ * @param {GPUTextureFormat[]} options.color_formats
108
+ * @param {GPUBuffer} options.command the tiles' draw command: 6 vertices, one instance per tile
109
+ */
110
+ draw({ encoder, bindings, colorAttachments, color_formats, command }) {
111
+ assert.defined(encoder, 'encoder');
112
+ assert.defined(command, 'command');
113
+
114
+ const descriptor = this.#descriptor;
115
+ const resources = descriptor.resources;
116
+
117
+ if (encoder.device !== this.#validated_device) {
118
+ descriptor.validate_against_device(encoder.device);
119
+
120
+ this.#validated_device = encoder.device;
121
+ }
122
+
123
+ encoder.pushDebugGroup(descriptor.label);
124
+
125
+ const pass = encoder.constructRenderPass({
126
+ pipeline: this.pipeline_for(color_formats),
127
+ bindings: resources.generateBindings(bindings, encoder),
128
+ colorAttachments,
129
+ immediate: encoder.writeImmediate(resources, bindings),
130
+ });
131
+
132
+ pass.drawIndirect(command, 0);
133
+
134
+ pass.end();
135
+
136
+ encoder.popDebugGroup();
137
+ }
138
+ }
@@ -1,10 +1,16 @@
1
1
  /**
2
2
  * Draws decals into the G-buffer.
3
3
  *
4
- * Four passes, in order: the atlases and this frame's records are uploaded, the decals are culled
5
- * against the camera, they are binned into their own froxels, and the composite reads the G-buffer
6
- * and writes a new one. The last of those is what {@link GBufferTextures} being publishable at
7
- * {@link FramePhase.AfterGBuffer} is for — see D23.
4
+ * Six passes, in order: the atlases and this frame's records are uploaded, the decals are culled
5
+ * against the camera, they are binned into their own froxels, the screen tiles whose froxels hold a
6
+ * decal are listed, the G-buffer under those tiles is copied, and the composite paints the decals
7
+ * into the G-buffer in place over the same tiles, reading the copy. The last of those is what
8
+ * {@link GBufferTextures} being publishable at {@link FramePhase.AfterGBuffer} is for — see D23.
9
+ *
10
+ * **Only the covered part of the screen costs anything.** The composite used to read the whole
11
+ * G-buffer and write a whole new one whenever any decal was on screen; on a 2-CU iGPU at 720p that
12
+ * copy alone was ~385 µs of a 544 µs pass for two small markers (2026-10-31). Now both tile passes
13
+ * are drawn indirectly over the gathered tiles, so their cost follows the area the decals cover.
8
14
  */
9
15
  export class GPUDecalRenderer {
10
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"GPUDecalRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/decal/GPUDecalRenderer.js"],"names":[],"mappings":"AA4CA;;;;;;;GAOG;AACH;IA6BI;;;;;;;;;;;OAWG;IACH;QAP8B,KAAK;QACL,OAAO,EAA1B,YAAY;QACC,YAAY,EAAzB,MAAM;QACU,YAAY;QACZ,YAAY;QACZ,SAAS;aAuBnC;IAkPD,gBAoBC;;CACJ"}
1
+ {"version":3,"file":"GPUDecalRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/decal/GPUDecalRenderer.js"],"names":[],"mappings":"AA6EA;;;;;;;;;;;;;GAaG;AACH;IA6BI;;;;;;;;;;;OAWG;IACH;QAP8B,KAAK;QACL,OAAO,EAA1B,YAAY;QACC,YAAY,EAAzB,MAAM;QACU,YAAY;QACZ,YAAY;QACZ,SAAS;aA+BnC;IA4SD,gBAoBC;;CACJ"}
@@ -11,6 +11,8 @@ import { SAMPLER_ANISOTROPIC_CLAMP } from "../../../shade/renderer/texture/SAMPL
11
11
  import { graph_build_decal_clusters } from "./graph_build_decal_clusters.js";
12
12
  import { DECAL_RECORD_WORD_COUNT } from "./DECAL_GPU_RECORD.js";
13
13
  import { shader_decal_composite } from "./shader_decal_composite.js";
14
+ import { shader_decal_tile_copy } from "./shader_decal_tile_copy.js";
15
+ import { graph_gather_decal_tiles } from "./graph_gather_decal_tiles.js";
14
16
  import { build_light_cluster_parameters } from "../../../shade/renderer/light/cluster/build_light_cluster_parameters.js";
15
17
  import { DECAL_CLUSTER_RESOLUTION_Z } from "./DECAL_CLUSTER.js";
16
18
 
@@ -22,6 +24,37 @@ import { DECAL_CLUSTER_RESOLUTION_Z } from "./DECAL_CLUSTER.js";
22
24
  */
23
25
  const GROWTH_FACTOR = 1.5;
24
26
 
27
+ /**
28
+ * The G-buffer's four targets, in the order both tile passes write them.
29
+ *
30
+ * @type {GPUTextureFormat[]}
31
+ */
32
+ const G_BUFFER_FORMATS = ["rg8unorm", "rgba16uint", G_BUFFER_ALBEDO_FORMAT, "r32uint"];
33
+
34
+ /**
35
+ * @type {TextureViewDescriptor}
36
+ */
37
+ const MIP_0 = TextureViewDescriptor.from({
38
+ mipLevelCount: 1,
39
+ baseMipLevel: 0
40
+ });
41
+
42
+ /**
43
+ * Mip 0 of a target, kept — a tile pass draws over part of the screen, so whatever lies outside the
44
+ * tiles has to survive it.
45
+ *
46
+ * @param {FramePassResources} resources
47
+ * @param {number} handle
48
+ * @returns {GPURenderPassColorAttachment}
49
+ */
50
+ function attachment(resources, handle) {
51
+ return {
52
+ loadOp: "load",
53
+ storeOp: "store",
54
+ view: resources.get(handle).obtainView(MIP_0)
55
+ };
56
+ }
57
+
25
58
  /**
26
59
  * One atlas as the GPU holds it, with the mip chain its borders exist to make usable.
27
60
  */
@@ -45,10 +78,16 @@ class AtlasResidency {
45
78
  /**
46
79
  * Draws decals into the G-buffer.
47
80
  *
48
- * Four passes, in order: the atlases and this frame's records are uploaded, the decals are culled
49
- * against the camera, they are binned into their own froxels, and the composite reads the G-buffer
50
- * and writes a new one. The last of those is what {@link GBufferTextures} being publishable at
51
- * {@link FramePhase.AfterGBuffer} is for — see D23.
81
+ * Six passes, in order: the atlases and this frame's records are uploaded, the decals are culled
82
+ * against the camera, they are binned into their own froxels, the screen tiles whose froxels hold a
83
+ * decal are listed, the G-buffer under those tiles is copied, and the composite paints the decals
84
+ * into the G-buffer in place over the same tiles, reading the copy. The last of those is what
85
+ * {@link GBufferTextures} being publishable at {@link FramePhase.AfterGBuffer} is for — see D23.
86
+ *
87
+ * **Only the covered part of the screen costs anything.** The composite used to read the whole
88
+ * G-buffer and write a whole new one whenever any decal was on screen; on a 2-CU iGPU at 720p that
89
+ * copy alone was ~385 µs of a 544 µs pass for two small markers (2026-10-31). Now both tile passes
90
+ * are drawn indirectly over the gathered tiles, so their cost follows the area the decals cover.
52
91
  */
53
92
  export class GPUDecalRenderer {
54
93
  /**
@@ -111,15 +150,94 @@ export class GPUDecalRenderer {
111
150
  resolution: frame.resolution
112
151
  });
113
152
 
114
- this.#graph_composite({ frame, clusters });
153
+ const tiles = graph_gather_decal_tiles({
154
+ graph,
155
+ cluster_lookup: clusters.lookup,
156
+ resolution: frame.resolution
157
+ });
158
+
159
+ const copy = this.#graph_copy({ frame, tiles });
160
+
161
+ this.#graph_composite({ frame, clusters, tiles, copy });
162
+ }
163
+
164
+ /**
165
+ * Copy the G-buffer under the listed tiles, for the composite to read while it writes them.
166
+ *
167
+ * The copy's textures are screen-sized, so a tile's texels sit where they are on screen and need
168
+ * no address of their own — only the listed tiles are ever written or read, and the rest of each
169
+ * texture is whatever it last held.
170
+ *
171
+ * @param {object} args
172
+ * @param {FrameContext} args.frame
173
+ * @param {{tiles: number, command: number}} args.tiles
174
+ * @returns {{pbr: number, normal: number, albedo: number, emissive: number}}
175
+ */
176
+ #graph_copy({ frame, tiles }) {
177
+ const graph = frame.graph;
178
+ const resolution = frame.resolution;
179
+
180
+ const gbuffer = frame.get(GBufferTextures);
181
+
182
+ const data = {};
183
+
184
+ const pass = graph.add('decals / copy covered tiles', data, (data, resources, context) => {
185
+ shader_decal_tile_copy.draw({
186
+ encoder: context.encoder,
187
+ bindings: {
188
+ settings: { screen_resolution: resolution },
189
+ decal_tiles: resources.get(data.tiles),
190
+ gBufferPBR: resources.get(data.in_pbr).obtainView(),
191
+ gBufferNormal: resources.get(data.in_normal).obtainView(),
192
+ gBufferAlbedo: resources.get(data.in_albedo).obtainView(),
193
+ gBufferEmissive: resources.get(data.in_emissive).obtainView(),
194
+ },
195
+ colorAttachments: [
196
+ attachment(resources, data.pbr),
197
+ attachment(resources, data.normal),
198
+ attachment(resources, data.albedo),
199
+ attachment(resources, data.emissive),
200
+ ],
201
+ color_formats: G_BUFFER_FORMATS,
202
+ command: resources.get(data.command),
203
+ });
204
+ });
205
+
206
+ data.tiles = pass.read(tiles.tiles);
207
+ data.command = pass.read(tiles.command);
208
+
209
+ data.in_pbr = pass.read(gbuffer.pbr);
210
+ data.in_normal = pass.read(gbuffer.normal);
211
+ data.in_albedo = pass.read(gbuffer.albedo);
212
+ data.in_emissive = pass.read(gbuffer.emissive);
213
+
214
+ /**
215
+ * @param {string} name
216
+ * @param {GPUTextureFormat} format
217
+ * @returns {number}
218
+ */
219
+ const target = (name, format) => pass.create(name, TextureResourceDescriptor.from({
220
+ format,
221
+ resolution,
222
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
223
+ }));
224
+
225
+ data.pbr = target("decals / covered PBR", G_BUFFER_FORMATS[0]);
226
+ data.normal = target("decals / covered normal", G_BUFFER_FORMATS[1]);
227
+ data.albedo = target("decals / covered albedo", G_BUFFER_FORMATS[2]);
228
+ data.emissive = target("decals / covered emissive", G_BUFFER_FORMATS[3]);
229
+
230
+ return { pbr: data.pbr, normal: data.normal, albedo: data.albedo, emissive: data.emissive };
115
231
  }
116
232
 
117
233
  /**
118
234
  * @param {object} args
119
235
  * @param {FrameContext} args.frame
120
236
  * @param {{lookup: number, data: number}} args.clusters
237
+ * @param {{tiles: number, command: number}} args.tiles
238
+ * @param {{pbr: number, normal: number, albedo: number, emissive: number}} args.copy
121
239
  */
122
- #graph_composite({ frame, clusters }) {
240
+ #graph_composite({ frame, clusters, tiles, copy }) {
123
241
  const graph = frame.graph;
124
242
  const resolution = frame.resolution;
125
243
 
@@ -143,35 +261,29 @@ export class GPUDecalRenderer {
143
261
 
144
262
  data.depth = pass.read(frame.get(ViewTextures).depth);
145
263
 
146
- data.in_pbr = pass.read(gbuffer.pbr);
147
- data.in_normal = pass.read(gbuffer.normal);
148
- data.in_albedo = pass.read(gbuffer.albedo);
149
- data.in_emissive = pass.read(gbuffer.emissive);
264
+ data.in_pbr = pass.read(copy.pbr);
265
+ data.in_normal = pass.read(copy.normal);
266
+ data.in_albedo = pass.read(copy.albedo);
267
+ data.in_emissive = pass.read(copy.emissive);
150
268
 
151
269
  data.cluster_lookup = pass.read(clusters.lookup);
152
270
  data.cluster_data = pass.read(clusters.data);
153
271
 
154
- /**
155
- * @param {string} name
156
- * @param {GPUTextureFormat} format
157
- * @returns {number}
158
- */
159
- const target = (name, format) => pass.create(name, TextureResourceDescriptor.from({
160
- format,
161
- resolution,
162
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
163
- }));
164
-
165
- data.out_pbr = target("g-buffer / PBR + decals", "rg8unorm");
166
- data.out_normal = target("g-buffer / Normal + decals", "rgba16uint");
167
- data.out_albedo = target("g-buffer / Albedo + decals", G_BUFFER_ALBEDO_FORMAT);
168
- data.out_emissive = target("g-buffer / Emissive + decals", "r32uint");
272
+ data.tiles = pass.read(tiles.tiles);
273
+ data.command = pass.read(tiles.command);
169
274
 
170
275
  /*
171
- The whole reason this pass can composite exactly. Everything downstream — ambient occlusion,
172
- reflections, shading — now reads what the decals wrote, and the graph knows it does, so the
173
- ordering is a real edge rather than an accident of declaration order.
276
+ In place, and still a real edge: a written handle is a new version of the same texture, its
277
+ producer this pass, and it is what the record hands on. Everything downstream — ambient
278
+ occlusion, reflections, shading — reads the version the decals wrote and the graph knows it
279
+ does. Pixels outside the listed tiles are never drawn, so they keep what the G-buffer pass
280
+ left there, which is exactly what they should hold.
174
281
  */
282
+ data.out_pbr = pass.write(gbuffer.pbr);
283
+ data.out_normal = pass.write(gbuffer.normal);
284
+ data.out_albedo = pass.write(gbuffer.albedo);
285
+ data.out_emissive = pass.write(gbuffer.emissive);
286
+
175
287
  gbuffer.pbr = data.out_pbr;
176
288
  gbuffer.normal = data.out_normal;
177
289
  gbuffer.albedo = data.out_albedo;
@@ -186,7 +298,7 @@ export class GPUDecalRenderer {
186
298
  * @param {number[]} cluster_params
187
299
  * @param {number[]} resolution
188
300
  */
189
- #execute(data, resources, context, view_context, cluster_params, resolution) {
301
+ #execute(data, resources, context, view_context, cluster_params, resolution) {
190
302
  const camera = view_context.camera;
191
303
  const encoder = context.encoder;
192
304
  const graphics = context.graphics;
@@ -206,19 +318,10 @@ export class GPUDecalRenderer {
206
318
  */
207
319
  const view = handle => resources.get(handle).obtainView();
208
320
 
209
- const attachment = handle => ({
210
- loadOp: "clear",
211
- storeOp: "store",
212
- view: resources.get(handle).obtainView(TextureViewDescriptor.from({
213
- mipLevelCount: 1,
214
- baseMipLevel: 0
215
- }))
216
- });
217
-
218
321
  shader_decal_composite.draw({
219
322
  encoder,
220
323
  bindings: {
221
- camera: camera.buffer,
324
+ camera: camera.buffer,
222
325
  view: view_context.uniform_buffer.buffer,
223
326
  settings,
224
327
  gBufferPBR: view(data.in_pbr),
@@ -235,14 +338,16 @@ export class GPUDecalRenderer {
235
338
  atlas_normal_sampler: sampler,
236
339
  atlas_orm: this.#orm.texture.obtainView(),
237
340
  atlas_orm_sampler: sampler,
341
+ decal_tiles: resources.get(data.tiles),
238
342
  },
239
343
  colorAttachments: [
240
- attachment(data.out_pbr),
241
- attachment(data.out_normal),
242
- attachment(data.out_albedo),
243
- attachment(data.out_emissive),
344
+ attachment(resources, data.out_pbr),
345
+ attachment(resources, data.out_normal),
346
+ attachment(resources, data.out_albedo),
347
+ attachment(resources, data.out_emissive),
244
348
  ],
245
- color_formats: ["rg8unorm", "rgba16uint", G_BUFFER_ALBEDO_FORMAT, "r32uint"]
349
+ color_formats: G_BUFFER_FORMATS,
350
+ command: resources.get(data.command),
246
351
  });
247
352
  }
248
353
 
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Where corner `vertex_index` of a listed screen tile lands in clip space.
3
+ *
4
+ * A tile is one column of the decal froxel grid, packed `x | y << 16`. Six vertices make two
5
+ * triangles covering it exactly, so a pixel is shaded by a tile draw if and only if its froxel column
6
+ * is that tile — the same column the composite then looks its decals up in.
7
+ *
8
+ * The froxel grid is built over a flipped y, counting rows up from the bottom edge
9
+ * (`cluster_from_fragment_coord`), which is the direction NDC y already runs. So no flip appears here:
10
+ * it is the grid's convention and clip space's agreeing, not an omission.
11
+ *
12
+ * @type {CodeChunk}
13
+ */
14
+ export const chunk_decal_tile_corner: CodeChunk;
15
+ /**
16
+ * The vertex stage of a pass drawn over the screen tiles that hold a decal: instance `i` is the tile
17
+ * at `decal_tiles[1 + i]`, the word before them being their count.
18
+ *
19
+ * Reads `decal_tiles` and `settings.screen_resolution`, which every pass using it declares.
20
+ *
21
+ * @type {CodeChunk}
22
+ */
23
+ export const chunk_decal_tile_vertex: CodeChunk;
24
+ import { CodeChunk } from "../../../shade/renderer/shader/compiler/CodeChunk.js";
25
+ //# sourceMappingURL=chunk_decal_tile_vertex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_decal_tile_vertex.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/decal/chunk_decal_tile_vertex.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,sCAFU,SAAS,CAgBjB;AAEF;;;;;;;GAOG;AACH,sCAFU,SAAS,CAgBjB;0BAtDwB,sDAAsD"}
@@ -0,0 +1,55 @@
1
+ import { CodeChunk } from "../../../shade/renderer/shader/compiler/CodeChunk.js";
2
+ import { DECAL_CLUSTER_TILE_RESOLUTION } from "./DECAL_CLUSTER.js";
3
+
4
+ /**
5
+ * Where corner `vertex_index` of a listed screen tile lands in clip space.
6
+ *
7
+ * A tile is one column of the decal froxel grid, packed `x | y << 16`. Six vertices make two
8
+ * triangles covering it exactly, so a pixel is shaded by a tile draw if and only if its froxel column
9
+ * is that tile — the same column the composite then looks its decals up in.
10
+ *
11
+ * The froxel grid is built over a flipped y, counting rows up from the bottom edge
12
+ * (`cluster_from_fragment_coord`), which is the direction NDC y already runs. So no flip appears here:
13
+ * it is the grid's convention and clip space's agreeing, not an omission.
14
+ *
15
+ * @type {CodeChunk}
16
+ */
17
+ export const chunk_decal_tile_corner = CodeChunk.from(
18
+ //language=WGSL
19
+ `
20
+ fn decal_tile_corner(tile: u32, vertex_index: u32, screen_resolution: vec2<u32>) -> vec2<f32> {
21
+ let cell = vec2<u32>(tile & 0xFFFFu, tile >> 16u);
22
+
23
+ // corners (0,0) (1,0) (0,1) (0,1) (1,0) (1,1), one bit per vertex
24
+ let corner = vec2<u32>((0x32u >> vertex_index) & 1u, (0x2Cu >> vertex_index) & 1u);
25
+
26
+ let pixel = (cell + corner) * ${DECAL_CLUSTER_TILE_RESOLUTION}u;
27
+
28
+ return vec2<f32>(pixel) / vec2<f32>(screen_resolution) * 2.0 - 1.0;
29
+ }
30
+ `
31
+ );
32
+
33
+ /**
34
+ * The vertex stage of a pass drawn over the screen tiles that hold a decal: instance `i` is the tile
35
+ * at `decal_tiles[1 + i]`, the word before them being their count.
36
+ *
37
+ * Reads `decal_tiles` and `settings.screen_resolution`, which every pass using it declares.
38
+ *
39
+ * @type {CodeChunk}
40
+ */
41
+ export const chunk_decal_tile_vertex = CodeChunk.from(
42
+ //language=WGSL
43
+ `
44
+ @vertex
45
+ fn main(
46
+ @builtin(vertex_index) vertex_index : u32,
47
+ @builtin(instance_index) instance_index : u32,
48
+ ) -> @builtin(position) vec4<f32> {
49
+ let ndc = decal_tile_corner(decal_tiles[1u + instance_index], vertex_index, settings.screen_resolution);
50
+
51
+ return vec4<f32>(ndc, 0.0, 1.0);
52
+ }
53
+ `,
54
+ [chunk_decal_tile_corner]
55
+ );
@@ -0,0 +1,22 @@
1
+ /**
2
+ * List the screen tiles that hold a decal, and the draw command a `DecalTileShader` draws them with.
3
+ *
4
+ * The list holds every tile of the screen at worst, so it never drops one; what it costs to draw
5
+ * follows the count the gather wrote, through the command. The command has a buffer of its own, as
6
+ * an indirect argument may not be bound writable in the scope it is used in.
7
+ *
8
+ * @param {object} args
9
+ * @param {FrameGraph} args.graph
10
+ * @param {number} args.cluster_lookup handle of the decal froxels' lookup
11
+ * @param {number[]} args.resolution
12
+ * @returns {{tiles: number, command: number}}
13
+ */
14
+ export function graph_gather_decal_tiles({ graph, cluster_lookup, resolution }: {
15
+ graph: FrameGraph;
16
+ cluster_lookup: number;
17
+ resolution: number[];
18
+ }): {
19
+ tiles: number;
20
+ command: number;
21
+ };
22
+ //# sourceMappingURL=graph_gather_decal_tiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph_gather_decal_tiles.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/decal/graph_gather_decal_tiles.js"],"names":[],"mappings":"AAeA;;;;;;;;;;;;GAYG;AACH;IAL4B,KAAK;IACT,cAAc,EAA3B,MAAM;IACS,UAAU,EAAzB,MAAM,EAAE;IACN;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CA2C5C"}