@woosh/meep-engine 3.47.0 → 3.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (619) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/editor/particles/effect/ParticleReferenceSimulation.d.ts +1 -2
  3. package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
  4. package/editor/particles/effect/ParticleReferenceSimulation.js +2 -4
  5. package/editor/view/particles/effect/ParticleGraphEditorView.js +1 -1
  6. package/package.json +1 -1
  7. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +27 -11
  8. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  9. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +11 -0
  10. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +2 -2
  11. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -1
  12. package/src/engine/graphics/ecs/particles/ParticleEffect.js +7 -7
  13. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts +8 -0
  14. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.d.ts.map +1 -1
  15. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationAdapter.js +11 -3
  16. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts +26 -0
  17. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.d.ts.map +1 -0
  18. package/src/engine/graphics/ecs/particles/ParticleEffectSerializationUpgrader_1_2.js +91 -0
  19. package/src/engine/graphics3/GPUParticleEmitterSystem.js +2 -2
  20. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  21. package/src/engine/graphics3/GraphicsEngine.js +8 -1
  22. package/src/engine/graphics3/ParticipatingMedia.d.ts +84 -1
  23. package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -1
  24. package/src/engine/graphics3/ParticipatingMedia.js +139 -5
  25. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +6 -2
  26. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -1
  27. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +29 -4
  28. package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts +10 -0
  29. package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.d.ts.map +1 -0
  30. package/src/engine/graphics3/ParticipatingMediaSerializationUpgrader_0_1.js +38 -0
  31. package/src/engine/graphics3/ParticipatingMediaSystem.d.ts.map +1 -1
  32. package/src/engine/graphics3/ParticipatingMediaSystem.js +46 -3
  33. package/src/engine/network/NetworkSession.d.ts +16 -5
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +104 -7
  36. package/src/engine/network/README.md +27 -1
  37. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts +40 -18
  38. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +180 -190
  40. package/src/engine/network/replication/Replicator.d.ts +15 -4
  41. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  42. package/src/engine/network/replication/Replicator.js +50 -16
  43. package/src/engine/network/state/RecordArrivalRing.d.ts +57 -0
  44. package/src/engine/network/state/RecordArrivalRing.d.ts.map +1 -0
  45. package/src/engine/network/state/RecordArrivalRing.js +144 -0
  46. package/src/engine/physics/cloth/MEASUREMENTS.md +354 -0
  47. package/src/engine/physics/cloth/PLAN.md +85 -5
  48. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +0 -12
  49. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  50. package/src/engine/physics/cloth/ecs/ClothInstance.js +0 -13
  51. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +2 -1
  52. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  53. package/src/engine/physics/cloth/ecs/ClothSystem.js +7 -1
  54. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
  55. package/src/engine/physics/cloth/ecs/ClothWorld.js +4 -15
  56. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +2 -1
  57. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
  58. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +6 -1
  59. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  60. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +20 -10
  61. package/src/engine/physics/cloth/playground/collide.html +5 -3
  62. package/src/engine/physics/cloth/playground/collide_main.js +14 -13
  63. package/src/engine/physics/cloth/solver/ClothState.d.ts +30 -2
  64. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  65. package/src/engine/physics/cloth/solver/ClothState.js +62 -4
  66. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +11 -3
  67. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
  68. package/src/engine/physics/cloth/solver/cloth_self_find.js +52 -11
  69. package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts +42 -0
  70. package/src/engine/physics/cloth/solver/cloth_self_radius.d.ts.map +1 -0
  71. package/src/engine/physics/cloth/solver/cloth_self_radius.js +64 -0
  72. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +99 -24
  73. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  74. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +102 -25
  75. package/src/engine/physics/cloth/solver/cloth_step.d.ts +5 -1
  76. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  77. package/src/engine/physics/cloth/solver/cloth_step.js +13 -3
  78. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +0 -1
  79. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
  80. package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -14
  81. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +23 -4
  82. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
  83. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +36 -8
  84. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
  85. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +4 -2
  86. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  87. package/src/shade/device/mock/SoftwareGPUDevice.d.ts +15 -0
  88. package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
  89. package/src/shade/device/mock/SoftwareGPUDevice.js +21 -0
  90. package/src/shade/device/pipeline/ComputePipelineManager.d.ts +20 -0
  91. package/src/shade/device/pipeline/ComputePipelineManager.d.ts.map +1 -1
  92. package/src/shade/device/pipeline/ComputePipelineManager.js +80 -6
  93. package/src/shade/device/pipeline/PipelineEnquiry.d.ts +52 -0
  94. package/src/shade/device/pipeline/PipelineEnquiry.d.ts.map +1 -0
  95. package/src/shade/device/pipeline/PipelineEnquiry.js +63 -0
  96. package/src/shade/device/pipeline/RenderPipelineManager.d.ts +21 -0
  97. package/src/shade/device/pipeline/RenderPipelineManager.d.ts.map +1 -1
  98. package/src/shade/device/pipeline/RenderPipelineManager.js +84 -4
  99. package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts +137 -0
  100. package/src/shade/playground/contact_shadows/ContactShadowLab.d.ts.map +1 -0
  101. package/src/shade/playground/contact_shadows/ContactShadowLab.js +654 -0
  102. package/src/shade/playground/contact_shadows/README.md +126 -0
  103. package/src/shade/playground/contact_shadows/index.html +191 -0
  104. package/src/shade/playground/contact_shadows/main.d.ts +2 -0
  105. package/src/shade/playground/contact_shadows/main.d.ts.map +1 -0
  106. package/src/shade/playground/contact_shadows/main.js +888 -0
  107. package/src/shade/playground/contact_shadows/scenes.d.ts +48 -0
  108. package/src/shade/playground/contact_shadows/scenes.d.ts.map +1 -0
  109. package/src/shade/playground/contact_shadows/scenes.js +620 -0
  110. package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts +36 -0
  111. package/src/shade/playground/contact_shadows/shader_contact_lab_composite.d.ts.map +1 -0
  112. package/src/shade/playground/contact_shadows/shader_contact_lab_composite.js +245 -0
  113. package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts +15 -0
  114. package/src/shade/playground/contact_shadows/shader_contact_lab_reference.d.ts.map +1 -0
  115. package/src/shade/playground/contact_shadows/shader_contact_lab_reference.js +120 -0
  116. package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts +55 -0
  117. package/src/shade/playground/contact_shadows/shader_contact_lab_stats.d.ts.map +1 -0
  118. package/src/shade/playground/contact_shadows/shader_contact_lab_stats.js +216 -0
  119. package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts +20 -0
  120. package/src/shade/playground/contact_shadows/shader_contact_lab_view.d.ts.map +1 -0
  121. package/src/shade/playground/contact_shadows/shader_contact_lab_view.js +114 -0
  122. package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts +11 -0
  123. package/src/shade/playground/contact_shadows/shader_contact_shadow_march.d.ts.map +1 -0
  124. package/src/shade/playground/contact_shadows/shader_contact_shadow_march.js +90 -0
  125. package/src/shade/playground/contact_shadows/textures.d.ts +16 -0
  126. package/src/shade/playground/contact_shadows/textures.d.ts.map +1 -0
  127. package/src/shade/playground/contact_shadows/textures.js +123 -0
  128. package/src/shade/playground/particle_ecs/README.md +1 -1
  129. package/src/shade/playground/particle_ecs/effects/flame.json +1932 -1881
  130. package/src/shade/playground/particle_ecs/effects/smoke.json +99 -1
  131. package/src/shade/playground/particle_ecs/effects/soot.json +152 -145
  132. package/src/shade/playground/tonemap_sdr/README.md +90 -0
  133. package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts +105 -0
  134. package/src/shade/playground/tonemap_sdr/ToneMapCompare.d.ts.map +1 -0
  135. package/src/shade/playground/tonemap_sdr/ToneMapCompare.js +380 -0
  136. package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts +32 -0
  137. package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.d.ts.map +1 -0
  138. package/src/shade/playground/tonemap_sdr/chunk_tonemap_gt7_sdr_reference.js +104 -0
  139. package/src/shade/playground/tonemap_sdr/index.html +90 -0
  140. package/src/shade/playground/tonemap_sdr/main.d.ts +2 -0
  141. package/src/shade/playground/tonemap_sdr/main.d.ts.map +1 -0
  142. package/src/shade/playground/tonemap_sdr/main.js +306 -0
  143. package/src/shade/playground/tonemap_sdr/scenes.d.ts +26 -0
  144. package/src/shade/playground/tonemap_sdr/scenes.d.ts.map +1 -0
  145. package/src/shade/playground/tonemap_sdr/scenes.js +404 -0
  146. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
  147. package/src/shade/playground/volumetrics_froxel/main.js +85 -4
  148. package/src/shade/playground/water_refraction/README.md +26 -18
  149. package/src/shade/playground/water_refraction/index.html +1 -1
  150. package/src/shade/renderer/Renderer.d.ts +35 -3
  151. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  152. package/src/shade/renderer/Renderer.js +208 -12
  153. package/src/shade/renderer/ShadeToneMappingMode.d.ts +14 -0
  154. package/src/shade/renderer/ShadeToneMappingMode.d.ts.map +1 -0
  155. package/src/shade/renderer/ShadeToneMappingMode.js +30 -0
  156. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +9 -0
  157. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  158. package/src/shade/renderer/animation/GPUAnimationManager.js +14 -0
  159. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.d.ts.map +1 -1
  160. package/src/shade/renderer/animation/skinning/shader_meshlet_apply_skinning.js +5 -3
  161. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts +7 -0
  162. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  163. package/src/shade/renderer/buffer/table/GPUDatabase.js +12 -0
  164. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts +8 -0
  165. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  166. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +12 -0
  167. package/src/shade/renderer/camera/GPUCameraContext.d.ts.map +1 -1
  168. package/src/shade/renderer/camera/GPUCameraContext.js +19 -8
  169. package/src/shade/renderer/deferred/chunk_read_gBuffer_material.d.ts.map +1 -1
  170. package/src/shade/renderer/deferred/chunk_read_gBuffer_material.js +4 -0
  171. package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.d.ts.map +1 -1
  172. package/src/shade/renderer/deferred/chunk_shade_standard_material_direct.js +4 -0
  173. package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.d.ts.map +1 -1
  174. package/src/shade/renderer/deferred/chunk_shade_standard_material_direct_restir.js +4 -0
  175. package/src/shade/renderer/deferred/shader_deferred_main.d.ts.map +1 -1
  176. package/src/shade/renderer/deferred/shader_deferred_main.js +3 -0
  177. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts +6 -0
  178. package/src/shade/renderer/deferred/shader_tonemap_HDR.d.ts.map +1 -1
  179. package/src/shade/renderer/deferred/shader_tonemap_HDR.js +13 -3
  180. package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts +9 -0
  181. package/src/shade/renderer/deferred/shader_tonemap_HDR_none.d.ts.map +1 -0
  182. package/src/shade/renderer/deferred/shader_tonemap_HDR_none.js +63 -0
  183. package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts +10 -0
  184. package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.d.ts.map +1 -0
  185. package/src/shade/renderer/deferred/shader_tonemap_HDR_pbr_neutral.js +87 -0
  186. package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts +6 -0
  187. package/src/shade/renderer/deferred/shader_tonemap_LDR.d.ts.map +1 -1
  188. package/src/shade/renderer/deferred/shader_tonemap_LDR.js +23 -5
  189. package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts +9 -0
  190. package/src/shade/renderer/deferred/shader_tonemap_LDR_none.d.ts.map +1 -0
  191. package/src/shade/renderer/deferred/shader_tonemap_LDR_none.js +68 -0
  192. package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts +10 -0
  193. package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.d.ts.map +1 -0
  194. package/src/shade/renderer/deferred/shader_tonemap_LDR_pbr_neutral.js +73 -0
  195. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
  196. package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +58 -9
  197. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +35 -25
  198. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  199. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +97 -196
  200. package/src/shade/renderer/geometry/sdf/shader_build_sdf.d.ts.map +1 -1
  201. package/src/shade/renderer/geometry/sdf/shader_build_sdf.js +121 -129
  202. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.d.ts.map +1 -1
  203. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.js +3 -0
  204. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.d.ts.map +1 -1
  205. package/src/shade/renderer/global_illumination/brick4/gpu/bake/shader_brick4_bake_probes.js +4 -0
  206. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.d.ts.map +1 -1
  207. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_indirect_lighting.js +4 -0
  208. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
  209. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.js +3 -0
  210. package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.d.ts.map +1 -1
  211. package/src/shade/renderer/global_illumination/lpv/deprecated/probe_trace_compute_shader_code.js +4 -0
  212. package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.d.ts.map +1 -1
  213. package/src/shade/renderer/global_illumination/probe/octahedral/graph_sample_light_probes.js +4 -0
  214. package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.d.ts.map +1 -1
  215. package/src/shade/renderer/global_illumination/shader_resolve_indirect_lighting.js +4 -0
  216. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +131 -1
  217. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts +7 -0
  218. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.d.ts.map +1 -1
  219. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_delta.js +45 -38
  220. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts +2 -0
  221. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.d.ts.map +1 -1
  222. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_determine_range.js +81 -79
  223. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts +2 -0
  224. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.d.ts.map +1 -1
  225. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_find_split.js +5 -3
  226. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts +21 -0
  227. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.d.ts.map +1 -0
  228. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_internal_children.js +42 -0
  229. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts +19 -0
  230. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.d.ts.map +1 -0
  231. package/src/shade/renderer/gpu_primitive/bvh/chunk_bvh_morton_code.js +44 -0
  232. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts +23 -5
  233. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts.map +1 -1
  234. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +139 -23
  235. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts +25 -0
  236. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.d.ts.map +1 -0
  237. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_build_single_workgroup.js +179 -0
  238. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts +2 -2
  239. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.d.ts.map +1 -1
  240. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_emit_hierarchy.js +7 -16
  241. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts +3 -4
  242. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.d.ts.map +1 -1
  243. package/src/shade/renderer/gpu_primitive/bvh/shader_bvh_morton.js +6 -23
  244. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts +11 -0
  245. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.d.ts.map +1 -1
  246. package/src/shade/renderer/gpu_primitive/indirect/IndirectComputeCommandBuildPass.js +14 -3
  247. package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts +10 -0
  248. package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.d.ts.map +1 -1
  249. package/src/shade/renderer/gpu_primitive/indirect/build_indirect_draw_command.js +13 -3
  250. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +10 -0
  251. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  252. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +14 -0
  253. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts +26 -0
  254. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.d.ts.map +1 -0
  255. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_comparator.js +52 -0
  256. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts +32 -0
  257. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.d.ts.map +1 -0
  258. package/src/shade/renderer/gpu_primitive/sort/chunk_sort_bitonic_workgroup.js +89 -0
  259. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +10 -0
  260. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  261. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +20 -1
  262. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +10 -0
  263. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  264. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +294 -281
  265. package/src/shade/renderer/light/GPULightCollection.d.ts +8 -0
  266. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  267. package/src/shade/renderer/light/GPULightCollection.js +18 -1
  268. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts +8 -0
  269. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
  270. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +234 -218
  271. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts +7 -0
  272. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
  273. package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +13 -0
  274. package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts +7 -0
  275. package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts.map +1 -1
  276. package/src/shade/renderer/light/cluster/graph_build_light_clusters.js +16 -2
  277. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts +10 -0
  278. package/src/shade/renderer/light/environment/execute_filter_environment_map.d.ts.map +1 -1
  279. package/src/shade/renderer/light/environment/execute_filter_environment_map.js +13 -0
  280. package/src/shade/renderer/lightmap/GPULightMap.d.ts.map +1 -1
  281. package/src/shade/renderer/lightmap/GPULightMap.js +3 -0
  282. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.d.ts.map +1 -1
  283. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_irradiance_flat.js +4 -0
  284. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.d.ts.map +1 -1
  285. package/src/shade/renderer/lightmap/bake/shader_lightmap_viz_to_sh.js +4 -0
  286. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  287. package/src/shade/renderer/material/GPUMaterialManager.d.ts +16 -4
  288. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  289. package/src/shade/renderer/material/GPUMaterialManager.js +38 -8
  290. package/src/shade/renderer/particles/DESIGN.md +49 -7
  291. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +453 -0
  292. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +5 -1
  293. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  294. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +13 -5
  295. package/src/shade/renderer/particles/data/particle_emitter_record.js +2 -2
  296. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.d.ts.map +1 -1
  297. package/src/shade/renderer/particles/graph/groups/particle_builtin_groups.js +12 -0
  298. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts +60 -0
  299. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.d.ts.map +1 -1
  300. package/src/shade/renderer/particles/graph/groups/particle_groups_geometry.js +156 -0
  301. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +2 -2
  302. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  303. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +8 -8
  304. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
  305. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +6 -4
  306. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +7 -6
  307. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
  308. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +91 -58
  309. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  310. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +10 -0
  311. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.d.ts.map +1 -1
  312. package/src/shade/renderer/path_tracer/accumulating/shader_accumulating_path_tracer.js +5 -1
  313. package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts.map +1 -1
  314. package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +6 -0
  315. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts +7 -0
  316. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts.map +1 -1
  317. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +18 -0
  318. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
  319. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.js +1 -0
  320. package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.d.ts.map +1 -1
  321. package/src/shade/renderer/postprocess/denoise/shader_temporal_reprojection_luma.js +6 -4
  322. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +11 -0
  323. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  324. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +16 -0
  325. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +10 -0
  326. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
  327. package/src/shade/renderer/postprocess/gtao/GTAO.js +16 -0
  328. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
  329. package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +32 -10
  330. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  331. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
  332. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +3 -0
  333. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts.map +1 -1
  334. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.js +6 -3
  335. package/src/shade/renderer/postprocess/taa/TAA.d.ts +12 -0
  336. package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
  337. package/src/shade/renderer/postprocess/taa/TAA.js +15 -0
  338. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts +7 -0
  339. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  340. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +13 -0
  341. package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts +31 -3
  342. package/src/shade/renderer/rasterize/TemplatePassDescriptor.d.ts.map +1 -1
  343. package/src/shade/renderer/rasterize/TemplatePassDescriptor.js +79 -4
  344. package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts +17 -0
  345. package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.d.ts.map +1 -1
  346. package/src/shade/renderer/rasterize/bucket/graph_meshlets_rasterize_by_bucket.js +35 -4
  347. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts +7 -0
  348. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
  349. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +182 -169
  350. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts +10 -0
  351. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts.map +1 -1
  352. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.js +20 -1
  353. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts +10 -0
  354. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.d.ts.map +1 -1
  355. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_extract_meshlets_from_bucket.js +18 -1
  356. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts +10 -0
  357. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
  358. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +20 -1
  359. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts +7 -0
  360. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
  361. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +187 -170
  362. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts +10 -0
  363. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
  364. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +19 -1
  365. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts +13 -0
  366. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
  367. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +25 -1
  368. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts +10 -0
  369. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  370. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +20 -0
  371. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  372. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -0
  373. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  374. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -0
  375. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
  376. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  377. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
  378. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +7 -2
  379. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  380. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +12 -4
  381. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.d.ts.map +1 -1
  382. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_brick4.js +4 -3
  383. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.d.ts.map +1 -1
  384. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_draw_ibl.js +4 -3
  385. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts +2 -1
  386. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  387. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +11 -3
  388. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.d.ts.map +1 -1
  389. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments.js +4 -3
  390. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.d.ts.map +1 -1
  391. package/src/shade/renderer/rasterize/native/oit/shader_oit_resolve_moments_ibl.js +4 -3
  392. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts +15 -0
  393. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  394. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +35 -2
  395. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts +14 -0
  396. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  397. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +32 -4
  398. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts +17 -0
  399. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
  400. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +34 -4
  401. package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts +5 -3
  402. package/src/shade/renderer/restir/di/chunk_restir_resolve.d.ts.map +1 -1
  403. package/src/shade/renderer/restir/di/chunk_restir_resolve.js +8 -3
  404. package/src/shade/renderer/restir/di/graph_restir_di.d.ts.map +1 -1
  405. package/src/shade/renderer/restir/di/graph_restir_di.js +1 -0
  406. package/src/shade/renderer/restir/di/shader_restir_di_resolve.d.ts.map +1 -1
  407. package/src/shade/renderer/restir/di/shader_restir_di_resolve.js +5 -1
  408. package/src/shade/renderer/restir/reservoir/shader.d.ts.map +1 -1
  409. package/src/shade/renderer/restir/reservoir/shader.js +7 -4
  410. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +7 -0
  411. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  412. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +13 -1
  413. package/src/shade/renderer/scene/GPUSceneContext.d.ts +10 -0
  414. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  415. package/src/shade/renderer/scene/GPUSceneContext.js +19 -0
  416. package/src/shade/renderer/scene/SceneManager.d.ts +9 -0
  417. package/src/shade/renderer/scene/SceneManager.d.ts.map +1 -1
  418. package/src/shade/renderer/scene/SceneManager.js +11 -0
  419. package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts +11 -0
  420. package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.d.ts.map +1 -1
  421. package/src/shade/renderer/scene/hierarchy/graph_nodes_update_transform_hierarchy.js +17 -0
  422. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts +11 -0
  423. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.d.ts.map +1 -1
  424. package/src/shade/renderer/scene/hierarchy/graph_scene_update_transform_hierarchy.js +18 -1
  425. package/src/shade/renderer/shader/ComputeShader.d.ts +12 -0
  426. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  427. package/src/shade/renderer/shader/ComputeShader.js +53 -0
  428. package/src/shade/renderer/shader/ImageShader.d.ts +27 -8
  429. package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
  430. package/src/shade/renderer/shader/ImageShader.js +70 -1
  431. package/src/shade/renderer/shader/ShaderDescriptor.d.ts +21 -0
  432. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  433. package/src/shade/renderer/shader/ShaderDescriptor.js +71 -1
  434. package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts +17 -0
  435. package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.d.ts.map +1 -0
  436. package/src/shade/renderer/shader/chunk/camera/chunk_project_view_position_from_depth.js +45 -0
  437. package/src/shade/renderer/shader/chunk/camera/chunk_screen_coordinate_to_view.js +3 -3
  438. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.d.ts +1 -1
  439. package/src/shade/renderer/shader/chunk/color/iCtCp/chunk_eotf_st2084.js +62 -62
  440. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +318 -0
  441. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +237 -0
  442. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts +17 -0
  443. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.d.ts.map +1 -0
  444. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_PAPER_WHITE_NITS.js +22 -0
  445. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts +14 -1
  446. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.d.ts.map +1 -1
  447. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_khronos_pbr.js +28 -15
  448. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts +12 -0
  449. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.d.ts.map +1 -1
  450. package/src/shade/renderer/shader/chunk/color/tonemap/gt7/chunk_tonemap_gt7.js +128 -110
  451. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts +20 -0
  452. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.d.ts.map +1 -0
  453. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_offset_ray_from_depth.js +33 -0
  454. package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts +4 -0
  455. package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.d.ts.map +1 -1
  456. package/src/shade/renderer/shader/chunk/light/chunk_compute_multiscattering_specular.js +12 -1
  457. package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.d.ts.map +1 -1
  458. package/src/shade/renderer/shader/chunk/material/MATERIAL_SHADING_INFO_STRUCT.js +7 -0
  459. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +108 -0
  460. package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.d.ts.map +1 -1
  461. package/src/shade/renderer/shader/chunk/material/chunk_compute_indirect_specular.js +23 -4
  462. package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts +18 -0
  463. package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.d.ts.map +1 -0
  464. package/src/shade/renderer/shader/chunk/material/chunk_re_direct_multiscatter.js +56 -0
  465. package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.d.ts.map +1 -1
  466. package/src/shade/renderer/shader/chunk/material/chunk_re_indirect_specular_physical.js +2 -0
  467. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts +43 -0
  468. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.d.ts.map +1 -0
  469. package/src/shade/renderer/shader/chunk/screen_space/chunk_screen_space_linear_ray.js +319 -0
  470. package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +33 -0
  471. package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
  472. package/src/shade/renderer/shader/compiler/CodeChunk.js +140 -0
  473. package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts +74 -0
  474. package/src/shade/renderer/shader/compiler/CodeChunkChoice.d.ts.map +1 -0
  475. package/src/shade/renderer/shader/compiler/CodeChunkChoice.js +166 -0
  476. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +680 -0
  477. package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts +86 -0
  478. package/src/shade/renderer/shader/compiler/ShaderSwitch.d.ts.map +1 -0
  479. package/src/shade/renderer/shader/compiler/ShaderSwitch.js +178 -0
  480. package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts +67 -0
  481. package/src/shade/renderer/shader/compiler/ShaderSwitchSet.d.ts.map +1 -0
  482. package/src/shade/renderer/shader/compiler/ShaderSwitchSet.js +205 -0
  483. package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts +14 -0
  484. package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.d.ts.map +1 -0
  485. package/src/shade/renderer/shadow/contact/CONTACT_SHADOW_WAVE_SIZE.js +13 -0
  486. package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts +65 -0
  487. package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.d.ts.map +1 -0
  488. package/src/shade/renderer/shadow/contact/ContactShadowDispatchList.js +252 -0
  489. package/src/shade/renderer/shadow/contact/FINDINGS.md +413 -0
  490. package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts +29 -0
  491. package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.d.ts.map +1 -0
  492. package/src/shade/renderer/shadow/contact/chunk_contact_shadow_wavefront_extents.js +105 -0
  493. package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts +29 -0
  494. package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.d.ts.map +1 -0
  495. package/src/shade/renderer/shadow/contact/graph_contact_shadow_linear.js +39 -0
  496. package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts +29 -0
  497. package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.d.ts.map +1 -0
  498. package/src/shade/renderer/shadow/contact/graph_contact_shadow_wavefront.js +92 -0
  499. package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts +29 -0
  500. package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.d.ts.map +1 -0
  501. package/src/shade/renderer/shadow/contact/shader_contact_shadow_linear.js +128 -0
  502. package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts +52 -0
  503. package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.d.ts.map +1 -0
  504. package/src/shade/renderer/shadow/contact/shader_contact_shadow_wavefront.js +358 -0
  505. package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts +10 -0
  506. package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.d.ts.map +1 -0
  507. package/src/shade/renderer/shadow/map/ShadowDirectionalTechnique.js +12 -0
  508. package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts +13 -0
  509. package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.d.ts.map +1 -0
  510. package/src/shade/renderer/shadow/map/shader/SHADOW_DIRECTIONAL_TECHNIQUE.js +14 -0
  511. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts +14 -8
  512. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.d.ts.map +1 -1
  513. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional.js +20 -86
  514. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts +14 -0
  515. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.d.ts.map +1 -0
  516. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_directional_cascades.js +79 -0
  517. package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.d.ts.map +1 -1
  518. package/src/shade/renderer/shadow/ray/shader_ray_shadow_code.js +12 -12
  519. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.d.ts.map +1 -1
  520. package/src/shade/renderer/shadow/ray/staged/gen/shader_generate_rays.js +153 -151
  521. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts +13 -0
  522. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.d.ts.map +1 -0
  523. package/src/shade/renderer/shadow/vsm/shader/chunk_shadowmap_sample_directional_virtual.js +48 -0
  524. package/src/shade/renderer/texture/GPUTextureContext.d.ts +10 -0
  525. package/src/shade/renderer/texture/GPUTextureContext.d.ts.map +1 -1
  526. package/src/shade/renderer/texture/GPUTextureContext.js +24 -0
  527. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts +219 -0
  528. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts.map +1 -0
  529. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.js +671 -0
  530. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts +26 -2
  531. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts.map +1 -1
  532. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +108 -4
  533. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +5 -1
  534. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  535. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +6 -0
  536. package/src/shade/renderer/volumetrics/NOTES.md +50 -0
  537. package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.d.ts.map +1 -1
  538. package/src/shade/renderer/volumetrics/PARTICIPATING_MEDIA_VOLUME_STRUCT.js +30 -1
  539. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +51 -13
  540. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
  541. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +98 -13
  542. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +9 -0
  543. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
  544. package/src/shade/renderer/volumetrics/SceneVolumetrics.js +78 -68
  545. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +326 -0
  546. package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts +7 -4
  547. package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.d.ts.map +1 -1
  548. package/src/shade/renderer/volumetrics/chunk_participating_media_volume_sample.js +21 -9
  549. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts +19 -0
  550. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.d.ts.map +1 -0
  551. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_uvw_from_clip.js +53 -0
  552. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +12 -3
  553. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -1
  554. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +85 -48
  555. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +4 -1
  556. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -1
  557. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +4 -1
  558. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +4 -1
  559. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  560. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +21 -1
  561. package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts +98 -0
  562. package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.d.ts.map +1 -0
  563. package/src/shade/renderer/volumetrics/noise/PARTICIPATING_MEDIA_NOISE.js +115 -0
  564. package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts +9 -0
  565. package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.d.ts.map +1 -0
  566. package/src/shade/renderer/volumetrics/noise/VOLUMETRICS_NOISE_TILE_BAKE_SETTINGS_STRUCT.js +24 -0
  567. package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts +27 -0
  568. package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.d.ts.map +1 -0
  569. package/src/shade/renderer/volumetrics/noise/bake_volumetrics_noise_tile.js +91 -0
  570. package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts +35 -0
  571. package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.d.ts.map +1 -0
  572. package/src/shade/renderer/volumetrics/noise/chunk_participating_media_noise.js +92 -0
  573. package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts +10 -0
  574. package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.d.ts.map +1 -0
  575. package/src/shade/renderer/volumetrics/noise/shader_volumetrics_noise_tile_bake.js +121 -0
  576. package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
  577. package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +38 -3
  578. package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -1
  579. package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +311 -290
  580. package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.d.ts.map +1 -1
  581. package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.js +28 -49
  582. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +3 -1
  583. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  584. package/src/shade/renderer/water/GPUWaterRenderer.js +24 -18
  585. package/src/shade/renderer/water/chunk_water_transport.d.ts +0 -1
  586. package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
  587. package/src/shade/renderer/water/chunk_water_transport.js +0 -17
  588. package/src/shade/renderer/water/shader_water.d.ts +4 -2
  589. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  590. package/src/shade/renderer/water/shader_water.js +27 -16
  591. package/src/shade/renderer/water/shader_water_avboit.d.ts +0 -4
  592. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  593. package/src/shade/renderer/water/shader_water_avboit.js +0 -63
  594. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  595. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +43 -9
  596. package/src/engine/network/transport/Channel.d.ts +0 -85
  597. package/src/engine/network/transport/Channel.d.ts.map +0 -1
  598. package/src/engine/network/transport/ReliableCommandPipeline.d.ts +0 -155
  599. package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +0 -1
  600. package/src/engine/network/transport/fragments/FragmentAssembler.d.ts +0 -105
  601. package/src/engine/network/transport/fragments/FragmentAssembler.d.ts.map +0 -1
  602. package/src/engine/network/transport/fragments/FragmentRetention.d.ts +0 -103
  603. package/src/engine/network/transport/fragments/FragmentRetention.d.ts.map +0 -1
  604. package/src/engine/network/transport/fragments/fragment_send.d.ts +0 -61
  605. package/src/engine/network/transport/fragments/fragment_send.d.ts.map +0 -1
  606. package/src/engine/network/transport/fragments/packet_size.d.ts +0 -99
  607. package/src/engine/network/transport/fragments/packet_size.d.ts.map +0 -1
  608. package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts +0 -6
  609. package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.d.ts.map +0 -1
  610. package/src/shade/renderer/shader/chunk/color/sRGB/chunk_RRTAndODTFit.js +0 -16
  611. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts +0 -7
  612. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.d.ts.map +0 -1
  613. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_aces.js +0 -46
  614. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts +0 -10
  615. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.d.ts.map +0 -1
  616. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_agx.js +0 -127
  617. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts +0 -7
  618. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.d.ts.map +0 -1
  619. package/src/shade/renderer/shader/chunk/color/tonemap/chunk_tonemap_pbr_neutral.js +0 -39
@@ -0,0 +1,888 @@
1
+ import Vector3 from "../../../core/geom/Vector3.js";
2
+ import { GPUProfileLevel } from "../../device/timing/profile/GPUProfileLevel.js";
3
+ import { GPUProfileSession } from "../../device/timing/profile/GPUProfileSession.js";
4
+ import { OrbitalCameraController } from "../../renderer/camera/OrbitalCameraController.js";
5
+ import { PerspectiveCamera } from "../../renderer/camera/PerspectiveCamera.js";
6
+ import { create_frame_loop } from "../../renderer/create_frame_loop.js";
7
+ import { Renderer } from "../../renderer/Renderer.js";
8
+ import { ShadeIndirectLightingMode } from "../../renderer/ShadeIndirectLightingMode.js";
9
+ import { ContactShadowFlags } from "../../renderer/shadow/contact/shader_contact_shadow_wavefront.js";
10
+ import { FrameRateMeter } from "../frame_rate_meter.js";
11
+ import { install_profile_hotkey } from "../profile_hotkey.js";
12
+ import { ContactMethod, ContactShadowLab } from "./ContactShadowLab.js";
13
+ import { create_contact_scene } from "./scenes.js";
14
+ import { ContactCombine } from "./shader_contact_lab_composite.js";
15
+ import {
16
+ CONTACT_STAT_BAND_BASE,
17
+ CONTACT_STAT_BAND_COUNT,
18
+ CONTACT_STAT_BAND_STRIDE,
19
+ CONTACT_STAT_COUNT,
20
+ ContactStat
21
+ } from "./shader_contact_lab_stats.js";
22
+
23
+ const element = id => document.getElementById(id);
24
+
25
+ const RUNNING = 'Running. Drag to orbit, right-drag to pan, wheel to zoom. T records a GPU profile.';
26
+
27
+ /** Seconds of scene time per frame when a measurement drives the frames. */
28
+ const FIXED_DT = 1 / 60;
29
+
30
+ /**
31
+ * @param {string} text
32
+ * @param {boolean} [error]
33
+ */
34
+ function report(text, error = false) {
35
+ const status = element('status');
36
+
37
+ status.textContent = text;
38
+ status.className = error ? 'fail' : '';
39
+ }
40
+
41
+ /**
42
+ * The counters of one or more frames as readable rates.
43
+ *
44
+ * @param {Float64Array|Uint32Array} s summed counters
45
+ * @param {number} frames how many frames they sum
46
+ */
47
+ function summarise(s, frames) {
48
+ const per_frame = v => v / frames;
49
+ const percent = (a, b) => b > 0 ? 100 * a / b : 0;
50
+
51
+ return {
52
+ frames,
53
+ pixels: per_frame(s[ContactStat.Pixels]),
54
+ reference_shadowed: per_frame(s[ContactStat.ReferenceShadowed]),
55
+ shadow_map_missed: per_frame(s[ContactStat.ShadowMapMissed]),
56
+ gap_closed_percent: percent(s[ContactStat.Fixed], s[ContactStat.ShadowMapMissed]),
57
+ missed: per_frame(s[ContactStat.Missed]),
58
+ shadow_map_false: per_frame(s[ContactStat.ShadowMapFalse]),
59
+ false_shadow: per_frame(s[ContactStat.False]),
60
+ added_false: per_frame(s[ContactStat.AddedFalse]),
61
+ contact_shadowed: per_frame(s[ContactStat.ContactShadowed]),
62
+ darker_than_both: per_frame(s[ContactStat.DarkerThanBoth]),
63
+ mean_error_combined: s[ContactStat.CombinedError] / 255 / Math.max(1, s[ContactStat.Pixels]),
64
+ mean_error_shadow_map: s[ContactStat.ShadowMapError] / 255 / Math.max(1, s[ContactStat.Pixels]),
65
+ spurious_flips: per_frame(s[ContactStat.SpuriousFlips]),
66
+ shadow_map_spurious_flips: per_frame(s[ContactStat.ShadowMapSpuriousFlips]),
67
+ reference_flips: per_frame(s[ContactStat.ReferenceFlips]),
68
+ change: per_frame(s[ContactStat.CombinedChange]) / 255,
69
+ shadow_map_change: per_frame(s[ContactStat.ShadowMapChange]) / 255,
70
+ bands: summarise_bands(s, frames),
71
+ };
72
+ }
73
+
74
+ /**
75
+ * The depth-band counters: per band of view depth ([0, 2) m, [2, 4) m, … doubling), per frame.
76
+ *
77
+ * @param {Float64Array|Uint32Array} s
78
+ * @param {number} frames
79
+ */
80
+ function summarise_bands(s, frames) {
81
+ const bands = [];
82
+
83
+ for (let band = 0; band < CONTACT_STAT_BAND_COUNT; band++) {
84
+ const base = CONTACT_STAT_BAND_BASE + band * CONTACT_STAT_BAND_STRIDE;
85
+ const reference_shadowed = s[base] / frames;
86
+
87
+ if (reference_shadowed === 0 && s[base + 3] === 0) {
88
+ continue;
89
+ }
90
+
91
+ bands.push({
92
+ metres: band === 0 ? '0-2' : `${2 ** band}-${band === CONTACT_STAT_BAND_COUNT - 1 ? 'inf' : 2 ** (band + 1)}`,
93
+ reference_shadowed,
94
+ shadow_map_missed: s[base + 1] / frames,
95
+ fixed: s[base + 2] / frames,
96
+ added_false: s[base + 3] / frames,
97
+ });
98
+ }
99
+
100
+ return bands;
101
+ }
102
+
103
+ /**
104
+ * @param {ReturnType<typeof summarise>} r
105
+ * @returns {string[]}
106
+ */
107
+ function describe_summary(r) {
108
+ return [
109
+ `reference shadowed ${r.reference_shadowed.toFixed(0)} px`,
110
+ `map missed (gaps) ${r.shadow_map_missed.toFixed(0)} px`,
111
+ ` closed by contact ${r.gap_closed_percent.toFixed(1)} %`,
112
+ `still missed ${r.missed.toFixed(0)} px`,
113
+ `false, total ${r.false_shadow.toFixed(0)} px`,
114
+ ` added by contact ${r.added_false.toFixed(0)} px`,
115
+ `darker than both ${r.darker_than_both.toFixed(0)} px`,
116
+ `mean |error| ${r.mean_error_combined.toFixed(4)} (map ${r.mean_error_shadow_map.toFixed(4)})`,
117
+ ];
118
+ }
119
+
120
+ /**
121
+ * A profile session that also keeps every span's duration by frame, for an in-page A/B.
122
+ */
123
+ class SpanCollector extends GPUProfileSession {
124
+ /** @type {Map<number, Map<string, number>>} frame index → label → nanoseconds */
125
+ spans = new Map();
126
+
127
+ /** @type {Map<number, number>} frame index → whole frame's GPU span, nanoseconds */
128
+ frames = new Map();
129
+
130
+ record_frame(frame) {
131
+ const by_label = new Map();
132
+
133
+ let begin = Infinity;
134
+ let end = -Infinity;
135
+
136
+ for (const span of frame.spans) {
137
+ by_label.set(span.label, (by_label.get(span.label) ?? 0) + span.duration_ns);
138
+
139
+ begin = Math.min(begin, span.t_begin_ns);
140
+ end = Math.max(end, span.t_begin_ns + span.duration_ns);
141
+ }
142
+
143
+ this.spans.set(frame.frame_index, by_label);
144
+ this.frames.set(frame.frame_index, end - begin);
145
+
146
+ super.record_frame(frame);
147
+ }
148
+ }
149
+
150
+ /**
151
+ * @param {number[]} values
152
+ */
153
+ function median(values) {
154
+ const sorted = values.slice().sort((a, b) => a - b);
155
+
156
+ return sorted.length === 0 ? NaN : sorted[sorted.length >> 1];
157
+ }
158
+
159
+ export async function start() {
160
+ const canvas = element('view');
161
+
162
+ const camera = new PerspectiveCamera();
163
+
164
+ camera.near = 0.1;
165
+ camera.far = 400;
166
+ camera.fov = 55 * Math.PI / 180;
167
+
168
+ const controller = new OrbitalCameraController(camera, canvas);
169
+
170
+ const renderer = new Renderer();
171
+
172
+ report('Acquiring GPU…');
173
+
174
+ await renderer.initialize({ context: canvas.getContext('webgpu'), pixelRatio: 1 });
175
+
176
+ renderer.indirect_lighting_mode = ShadeIndirectLightingMode.IBL;
177
+ renderer.feature_shadows_enabled = true;
178
+ renderer.feature_automatic_exposure_enabled = false;
179
+ renderer.exposure_compensation = 0.5;
180
+ // AO darkens the same contacts and would hide what the sun's term does; it is not under test
181
+ renderer.feature_ssao_enabled = false;
182
+ renderer.feature_bloom_enabled = false;
183
+
184
+ const lab = new ContactShadowLab(renderer);
185
+
186
+ renderer.add_extension(lab.lighting);
187
+ renderer.add_extension(lab.overlay);
188
+
189
+ /** @type {Map<string, import("./scenes.js").ContactScene>} */
190
+ const worlds = new Map();
191
+
192
+ /** @type {import("./scenes.js").ContactScene} */
193
+ let world;
194
+
195
+ /** Seconds along the camera path and the movers' clock. */
196
+ let time = 0;
197
+
198
+ /** Measurements driving the frames (they nest); the frame loop stands aside while any does. */
199
+ let driving = 0;
200
+
201
+ let stopped = false;
202
+
203
+ const meter = new FrameRateMeter();
204
+
205
+ const path_from = [0, 0, 0];
206
+ const path_to = [0, 0, 0];
207
+ const look_from = new Vector3();
208
+ const look_to = new Vector3();
209
+
210
+ /**
211
+ * @param {number[]} from
212
+ * @param {number[]} to
213
+ */
214
+ function look(from, to) {
215
+ look_from.set(from[0], from[1], from[2]);
216
+ look_to.set(to[0], to[1], to[2]);
217
+
218
+ controller.look(look_from, look_to);
219
+ }
220
+
221
+ function frame_preset(name = 'default') {
222
+ const presets = world.presets;
223
+ const preset = presets[name] ?? presets[Object.keys(presets)[0]];
224
+
225
+ look(preset[0], preset[1]);
226
+ }
227
+
228
+ async function select_world() {
229
+ const name = element('scene').value;
230
+
231
+ if (!worlds.has(name)) {
232
+ report(`Building ${name}…`);
233
+
234
+ worlds.set(name, await create_contact_scene(renderer, name));
235
+ }
236
+
237
+ world = worlds.get(name);
238
+
239
+ lab.to_light = world.to_light;
240
+ lab.reset_history();
241
+
242
+ if (world.defaults.taa !== undefined) {
243
+ element('taa').checked = world.defaults.taa;
244
+ }
245
+
246
+ element('failure').textContent = world.failure;
247
+
248
+ time = 0;
249
+
250
+ frame_preset();
251
+ apply_settings();
252
+
253
+ renderer.indicate_view_change();
254
+
255
+ report(RUNNING);
256
+ }
257
+
258
+ function apply_settings() {
259
+ const thickness = 0.005 * 2 ** Number(element('thickness').value);
260
+ const threshold = 0.02 * 2 ** Number(element('threshold').value);
261
+ const contrast = Number(element('contrast').value);
262
+
263
+ lab.method = Number(element('method').value);
264
+ lab.combine = Number(element('combine').value);
265
+ lab.view = Number(element('show').value);
266
+ lab.reference = element('reference').checked || lab.view >= 4;
267
+
268
+ lab.settings.surface_thickness = thickness;
269
+ lab.settings.bilinear_threshold = threshold;
270
+ lab.settings.shadow_contrast = contrast;
271
+ lab.settings.debug_mode = Number(element('debug').value);
272
+ lab.settings.flags = (element('ignore-edges').checked ? ContactShadowFlags.IgnoreEdgePixels : 0)
273
+ | (element('offset-mode').checked ? ContactShadowFlags.BilinearOffsetMode : 0)
274
+ | (element('precision-offset').checked ? ContactShadowFlags.PrecisionOffset : 0);
275
+
276
+ renderer.feature_virtual_shadow_maps = element('technique').value === 'vsm';
277
+ renderer.feature_taa_enabled = element('taa').checked;
278
+
279
+ lab.linear_settings.steps = Number(element('linear-steps').value);
280
+ lab.linear_jitter = element('linear-jitter').checked;
281
+
282
+ element('thickness-value').textContent = thickness.toFixed(5);
283
+ element('threshold-value').textContent = threshold.toFixed(4);
284
+ element('contrast-value').textContent = String(contrast);
285
+ element('speed-value').textContent = Number(element('speed').value).toFixed(2);
286
+ }
287
+
288
+ for (const id of ['method', 'combine', 'show', 'reference', 'thickness', 'threshold', 'contrast', 'debug',
289
+ 'ignore-edges', 'offset-mode', 'precision-offset', 'technique', 'taa', 'speed',
290
+ 'linear-steps', 'linear-reach', 'linear-thickness', 'linear-jitter']) {
291
+ element(id).addEventListener('input', apply_settings);
292
+ }
293
+
294
+ element('scene').addEventListener('change', () => select_world().catch(error => report(String(error), true)));
295
+ element('preset').addEventListener('click', () => frame_preset());
296
+ element('step').addEventListener('click', () => {
297
+ element('pause').checked = true;
298
+ advance(FIXED_DT);
299
+ render_frame(FIXED_DT);
300
+ });
301
+
302
+ function resize() {
303
+ const width = window.innerWidth;
304
+ const height = window.innerHeight;
305
+
306
+ camera.aspect = width / height;
307
+ renderer.resize(width, height);
308
+ }
309
+
310
+ /**
311
+ * Move the scene's clock, its movers and, on the path, the camera.
312
+ *
313
+ * @param {number} dt seconds
314
+ */
315
+ function advance(dt) {
316
+ time += dt * Number(element('speed').value);
317
+
318
+ world.update(time);
319
+ }
320
+
321
+ /**
322
+ * The world size of a texel of the shadow map serving the camera's near field: the cascades' first
323
+ * cascade as last fitted, or VSM's first level.
324
+ */
325
+ function shadow_texel() {
326
+ const map = renderer.scenes.obtain(world.scene).lights.shadow_context.get_map(world.sun);
327
+
328
+ if (map === undefined) {
329
+ return renderer.shadow_virtual_first_texel_size;
330
+ }
331
+
332
+ if (map.isVirtualShadowMap === true) {
333
+ return renderer.shadow_virtual_first_texel_size;
334
+ }
335
+
336
+ const camera = map.views[0]?.camera;
337
+ const slot = map.layout[0];
338
+
339
+ if (camera === undefined || slot === undefined) {
340
+ return renderer.shadow_virtual_first_texel_size;
341
+ }
342
+
343
+ return Math.max((camera.right - camera.left) / slot.width, (camera.top - camera.bottom) / slot.height);
344
+ }
345
+
346
+ /**
347
+ * The linear trace's reach and thickness, from the shadow map it complements: a reach of so many of its
348
+ * texels (the 5×5 filter blurs 5), and a thickness of reach / steps times a factor — at 1, the least that
349
+ * lets a march behind surfaces still see every surface.
350
+ */
351
+ function derive_linear_settings() {
352
+ const settings = lab.linear_settings;
353
+
354
+ settings.length = shadow_texel() * Number(element('linear-reach').value);
355
+ settings.thickness = settings.length / settings.steps * Number(element('linear-thickness').value);
356
+
357
+ element('linear-reach-value').textContent = `${(settings.length * 100).toFixed(1)} cm`;
358
+ }
359
+
360
+ /**
361
+ * @param {number} dt seconds, for the renderer's own clocks
362
+ */
363
+ function render_frame(dt) {
364
+ if (element('path').checked) {
365
+ world.path(time, path_from, path_to);
366
+ look(path_from, path_to);
367
+ }
368
+
369
+ resize();
370
+ controller.update();
371
+
372
+ derive_linear_settings();
373
+
374
+ renderer.render(camera, world.scene, dt);
375
+ }
376
+
377
+ /** Counters for the panel, read every few frames. */
378
+ let live_reading = false;
379
+ let live_counter = 0;
380
+ let live_lines = [];
381
+
382
+ async function read_live() {
383
+ live_reading = true;
384
+
385
+ try {
386
+ const s = await lab.read_stats();
387
+
388
+ live_lines = describe_summary(summarise(s, 1));
389
+ } finally {
390
+ live_reading = false;
391
+ }
392
+ }
393
+
394
+ function frame(dt, raf_dt) {
395
+ if (stopped || driving > 0 || world === undefined) {
396
+ return;
397
+ }
398
+
399
+ meter.add(raf_dt);
400
+
401
+ if (!element('pause').checked) {
402
+ advance(dt);
403
+ }
404
+
405
+ const live = element('live').checked && !live_reading && ++live_counter % 10 === 0;
406
+
407
+ if (live) {
408
+ // one frame on its own, so flips mean nothing here
409
+ lab.reset_history();
410
+ lab.clear_stats();
411
+ lab.measuring = true;
412
+ }
413
+
414
+ render_frame(dt);
415
+
416
+ lab.measuring = false;
417
+
418
+ if (live) {
419
+ read_live().catch(error => console.error(error));
420
+ }
421
+
422
+ update_readouts();
423
+ }
424
+
425
+ let last_readout = 0;
426
+
427
+ function update_readouts() {
428
+ const now = performance.now();
429
+
430
+ if (now - last_readout < 250) {
431
+ return;
432
+ }
433
+
434
+ last_readout = now;
435
+
436
+ const lines = [
437
+ `${meter.fps.toFixed(1)} fps, ${meter.mean_ms.toFixed(2)} ms mean`,
438
+ `${world.title}`,
439
+ `t = ${time.toFixed(2)} s`,
440
+ ];
441
+
442
+ if (element('live').checked) {
443
+ lines.push('', ...live_lines);
444
+ }
445
+
446
+ element('stats').textContent = lines.join('\n');
447
+ }
448
+
449
+ apply_settings();
450
+
451
+ await select_world();
452
+
453
+ let stop_loop = create_frame_loop((dt, raf_dt) => {
454
+ try {
455
+ frame(Math.min(dt, 0.1), raf_dt);
456
+ } catch (error) {
457
+ stopped = true;
458
+ stop_loop?.();
459
+ report(String(error?.stack ?? error), true);
460
+ console.error(error);
461
+ }
462
+ });
463
+
464
+ window.addEventListener('pagehide', () => {
465
+ stopped = true;
466
+ stop_loop?.();
467
+ lab.destroy();
468
+ renderer.destroy();
469
+ });
470
+
471
+ window.addEventListener('pageshow', event => {
472
+ if (event.persisted) {
473
+ location.reload();
474
+ }
475
+ });
476
+
477
+ install_profile_hotkey({
478
+ renderer,
479
+ name: 'contact_shadows',
480
+ status: element('status'),
481
+ settings: () => [
482
+ `scene=${element('scene').value}`,
483
+ `method=${element('method').value}`,
484
+ `combine=${element('combine').value}`,
485
+ `technique=${element('technique').value}`,
486
+ `taa=${element('taa').checked}`,
487
+ ],
488
+ });
489
+
490
+ /**
491
+ * Set controls by element id, as a person would.
492
+ *
493
+ * @param {Object<string, *>} settings
494
+ */
495
+ async function configure(settings) {
496
+ for (const [id, value] of Object.entries(settings)) {
497
+ const control = element(id);
498
+
499
+ if (control === null) {
500
+ throw new Error(`no control '${id}'`);
501
+ }
502
+
503
+ if (control.type === 'checkbox') {
504
+ control.checked = Boolean(value);
505
+ } else {
506
+ control.value = String(value);
507
+ }
508
+ }
509
+
510
+ if ('scene' in settings) {
511
+ await select_world();
512
+ }
513
+
514
+ apply_settings();
515
+ }
516
+
517
+ /**
518
+ * Take the frames from the loop for the length of `body`, and give them back.
519
+ *
520
+ * @template T
521
+ * @param {function(): Promise<T>} body
522
+ * @returns {Promise<T>}
523
+ */
524
+ async function drive(body) {
525
+ driving++;
526
+
527
+ const pause = element('pause').checked;
528
+
529
+ try {
530
+ return await body();
531
+ } finally {
532
+ lab.measuring = false;
533
+ lab.capture = false;
534
+ element('pause').checked = pause;
535
+ driving--;
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Render frames at a fixed step and wait for each to finish on the GPU.
541
+ *
542
+ * @param {number} count
543
+ * @param {boolean} move whether scene time (path and movers) advances
544
+ */
545
+ async function run_frames(count, move) {
546
+ for (let i = 0; i < count; i++) {
547
+ if (move) {
548
+ advance(FIXED_DT);
549
+ }
550
+
551
+ render_frame(FIXED_DT);
552
+
553
+ await renderer.device.queue.onSubmittedWorkDone();
554
+ }
555
+ }
556
+
557
+ /**
558
+ * Count one scene's failure against the reference for each arm, along the scene's own camera path:
559
+ * every arm runs the same path from the same start, with the same movers.
560
+ *
561
+ * @param {Object} [options]
562
+ * @param {string} [options.scene] defaults to the one on screen
563
+ * @param {number} [options.frames] measured per arm
564
+ * @param {number} [options.warmup] frames before counting, for the shadow map (and VSM pages) to settle
565
+ * @param {boolean} [options.moving] follow the path; still otherwise
566
+ * @param {Object<string, Object>} [options.arms] name → control settings for {@link configure}
567
+ */
568
+ async function measure_scene({
569
+ scene = element('scene').value,
570
+ frames = 240,
571
+ warmup = 30,
572
+ moving = true,
573
+ arms = {
574
+ off: { method: ContactMethod.Off },
575
+ wavefront: { method: ContactMethod.Wavefront },
576
+ march: { method: ContactMethod.March },
577
+ },
578
+ } = {}) {
579
+ return drive(async () => {
580
+ const path = element('path').checked;
581
+
582
+ await configure({ scene, path: moving });
583
+
584
+ const results = {};
585
+
586
+ for (const [name, arm] of Object.entries(arms)) {
587
+ await configure(arm);
588
+
589
+ time = 0;
590
+ world.update(0);
591
+
592
+ await run_frames(warmup, false);
593
+
594
+ lab.reset_history();
595
+
596
+ const sum = new Float64Array(CONTACT_STAT_COUNT);
597
+
598
+ /** per frame: the fraction of the shadow map's gaps closed, and false shadow added */
599
+ const closed = [];
600
+ const added = [];
601
+
602
+ for (let i = 0; i < frames; i++) {
603
+ if (moving) {
604
+ advance(FIXED_DT);
605
+ }
606
+
607
+ lab.clear_stats();
608
+ lab.measuring = true;
609
+
610
+ render_frame(FIXED_DT);
611
+
612
+ lab.measuring = false;
613
+
614
+ const s = await lab.read_stats();
615
+
616
+ for (let k = 0; k < s.length; k++) {
617
+ sum[k] += s[k];
618
+ }
619
+
620
+ closed.push(s[ContactStat.ShadowMapMissed] > 0 ? s[ContactStat.Fixed] / s[ContactStat.ShadowMapMissed] : NaN);
621
+ added.push(s[ContactStat.AddedFalse]);
622
+ }
623
+
624
+ const finite = closed.filter(Number.isFinite);
625
+
626
+ results[name] = {
627
+ ...summarise(sum, frames),
628
+ per_frame: {
629
+ gap_closed_min_percent: 100 * Math.min(...finite),
630
+ gap_closed_max_percent: 100 * Math.max(...finite),
631
+ added_false_max: Math.max(...added),
632
+ gap_closed: closed.map(v => Math.round(v * 1000) / 10),
633
+ added_false: added,
634
+ },
635
+ };
636
+ }
637
+
638
+ element('path').checked = path;
639
+
640
+ return { scene, moving, frames, results };
641
+ });
642
+ }
643
+
644
+ /**
645
+ * GPU time of the contact pass, A/B in one process: the arms swap every `block` frames in ABCD DCBA
646
+ * order, each block's first frame dropped, with the camera and scene still.
647
+ *
648
+ * @param {Object} [options]
649
+ * @param {number} [options.frames]
650
+ * @param {number} [options.block]
651
+ */
652
+ async function measure_cost({ frames = 360, block = 4 } = {}) {
653
+ return drive(async () => {
654
+ const arms = [ContactMethod.Off, ContactMethod.Wavefront, ContactMethod.March, ContactMethod.Linear];
655
+ const order = [0, 1, 2, 3, 3, 2, 1, 0];
656
+
657
+ await run_frames(20, false);
658
+
659
+ const session = new SpanCollector({ level: GPUProfileLevel.TIMING });
660
+
661
+ /** @type {Map<number, number>} frame index → arm */
662
+ const arm_of = new Map();
663
+
664
+ renderer.profile_session = session;
665
+
666
+ session.start();
667
+
668
+ for (let i = 0; i < frames; i++) {
669
+ const b = Math.floor(i / block);
670
+ const arm = arms[order[b % order.length]];
671
+
672
+ lab.method = arm;
673
+
674
+ if (i % block !== 0) {
675
+ arm_of.set(renderer.frame_count, arm);
676
+ }
677
+
678
+ render_frame(FIXED_DT);
679
+
680
+ await renderer.device.queue.onSubmittedWorkDone();
681
+ }
682
+
683
+ await session.stop();
684
+
685
+ renderer.profile_session = null;
686
+
687
+ apply_settings();
688
+
689
+ /** label → arm → durations, µs */
690
+ const by_label = new Map();
691
+ const frame_us = arms.map(() => []);
692
+
693
+ for (const [index, arm] of arm_of) {
694
+ const spans = session.spans.get(index);
695
+
696
+ if (spans === undefined) {
697
+ continue;
698
+ }
699
+
700
+ frame_us[arm].push(session.frames.get(index) / 1000);
701
+
702
+ for (const [label, ns] of spans) {
703
+ if (!by_label.has(label)) {
704
+ by_label.set(label, arms.map(() => []));
705
+ }
706
+
707
+ by_label.get(label)[arm].push(ns / 1000);
708
+ }
709
+ }
710
+
711
+ const names = ['off', 'wavefront', 'march', 'linear'];
712
+ const passes = {};
713
+
714
+ for (const [label, per_arm] of by_label) {
715
+ passes[label] = Object.fromEntries(per_arm.map((values, arm) => [names[arm], {
716
+ n: values.length,
717
+ median_us: median(values),
718
+ mean_us: values.reduce((a, b) => a + b, 0) / Math.max(1, values.length),
719
+ }]));
720
+ }
721
+
722
+ return {
723
+ resolution: [canvas.width, canvas.height],
724
+ frame_median_us: Object.fromEntries(frame_us.map((values, arm) => [names[arm], median(values)])),
725
+ passes,
726
+ };
727
+ });
728
+ }
729
+
730
+ /**
731
+ * The checks that make the counters mean something:
732
+ *
733
+ * 1. the composite reproduces deferred shading's sun term: taking it all back out equals a frame lit
734
+ * with the sun at zero intensity, to within the float16 rounding of the lit frame, with the cascades
735
+ * and with the virtual shadow map;
736
+ * 2. where the shadow map shadows the combine scene, the ray-traced reference does too (the reverse
737
+ * is what the scene is built to break);
738
+ * 3. the wavefront pass closes some of the shadow map's gaps there: a smoke check, not a quality bar.
739
+ */
740
+ async function verify() {
741
+ return drive(async () => {
742
+ const checks = [];
743
+
744
+ const taa = element('taa').checked;
745
+
746
+ // 1. the sun term, taken back out, against the sun switched off, with each shadow technique:
747
+ // the composite must be built for the one the deferred pass links
748
+ for (const technique of ['csm', 'vsm']) {
749
+ await configure({ scene: 'combine', path: false, taa: false, technique, method: ContactMethod.Off, combine: ContactCombine.Multiply, show: 0 });
750
+
751
+ frame_preset();
752
+
753
+ await run_frames(20, false);
754
+
755
+ const sun = world.sun;
756
+ const intensity = sun.intensity;
757
+
758
+ lab.combine = ContactCombine.RemoveSun;
759
+ lab.capture = true;
760
+
761
+ await run_frames(12, false);
762
+
763
+ const removed = await lab.read_capture();
764
+
765
+ lab.combine = ContactCombine.Multiply;
766
+ sun.intensity = 0;
767
+ world.scene.lights.needsUpdate = true;
768
+
769
+ await run_frames(12, false);
770
+
771
+ const dark = await lab.read_capture();
772
+
773
+ sun.intensity = intensity;
774
+ world.scene.lights.needsUpdate = true;
775
+
776
+ await run_frames(12, false);
777
+
778
+ const lit = await lab.read_capture();
779
+
780
+ lab.capture = false;
781
+
782
+ /*
783
+ The composite subtracts from the lit frame as the renderer stored it, in rgba16float. Four
784
+ float16 writes stand between an exact composite and the dark frame: the deferred pass's and
785
+ the indirect resolve's additive blend into the lit frame, the composite's own output, and
786
+ the resolve's blend into the dark frame (whose deferred write is exactly 0: the sun is its
787
+ one direct light). Each is off by less than a step of the lit value. The 4090 truncates
788
+ (1 + 0.75 step is written as 1), which puts the difference in (-3, 1) steps; round to
789
+ nearest would keep it within 2. Measured 2026-10-16: 1.5 at worst in cascades, 2 in VSM,
790
+ a mean of -0.43 (the composite's extra truncation); 4 in cascades when the composite left
791
+ out the direct multiscatter compensation, 34,201 in VSM when it sampled the cascades.
792
+ */
793
+ let worst_steps = 0;
794
+ let worst_absolute = 0;
795
+ let signed_steps = 0;
796
+
797
+ for (let i = 0; i < removed.rgb.length; i++) {
798
+ const magnitude = Math.max(Math.abs(lit.rgb[i]), Math.abs(dark.rgb[i]), 2 ** -14);
799
+ const step = 2 ** (Math.floor(Math.log2(magnitude)) - 10);
800
+ const difference = removed.rgb[i] - dark.rgb[i];
801
+
802
+ worst_steps = Math.max(worst_steps, Math.abs(difference) / step);
803
+ worst_absolute = Math.max(worst_absolute, Math.abs(difference));
804
+ signed_steps += difference / step;
805
+ }
806
+
807
+ checks.push({
808
+ name: `taking the whole sun term back out equals the frame with the sun off (${technique})`,
809
+ pass: worst_steps < 3,
810
+ worst_float16_steps_of_the_lit_value: worst_steps,
811
+ mean_signed_float16_steps: signed_steps / removed.rgb.length,
812
+ worst_absolute_difference: worst_absolute,
813
+ });
814
+ }
815
+
816
+ // 2 and 3. the reference, and the wavefront against it, with the cascades
817
+ await configure({ technique: 'csm' });
818
+
819
+ await run_frames(20, false);
820
+
821
+ const result = await measure_scene({
822
+ scene: 'combine',
823
+ frames: 8,
824
+ warmup: 4,
825
+ moving: false,
826
+ arms: { off: { method: ContactMethod.Off }, wavefront: { method: ContactMethod.Wavefront } },
827
+ });
828
+
829
+ const off = result.results.off;
830
+ const wavefront = result.results.wavefront;
831
+
832
+ /*
833
+ Where the cascades shadow, the reference must too: only their filtered edges may disagree.
834
+ (The other way round is the point of the scene — the cascades leave gaps at caster bases.)
835
+ */
836
+ const map_shadowed = off.reference_shadowed - off.shadow_map_missed + off.shadow_map_false;
837
+
838
+ checks.push({
839
+ name: 'where the shadow map shadows, the reference does too',
840
+ pass: map_shadowed > 1000 && off.shadow_map_false < 0.01 * map_shadowed,
841
+ shadow_map_shadowed: map_shadowed,
842
+ shadow_map_false: off.shadow_map_false,
843
+ reference_shadowed: off.reference_shadowed,
844
+ shadow_map_missed: off.shadow_map_missed,
845
+ });
846
+
847
+ checks.push({
848
+ name: 'the wavefront pass closes shadow-map gaps',
849
+ pass: wavefront.gap_closed_percent > 10,
850
+ gap_closed_percent: wavefront.gap_closed_percent,
851
+ });
852
+
853
+ element('taa').checked = taa;
854
+ apply_settings();
855
+
856
+ return { pass: checks.every(c => c.pass), checks };
857
+ });
858
+ }
859
+
860
+ globalThis.contact_lab = {
861
+ renderer,
862
+ camera,
863
+ controller,
864
+ lab,
865
+ get world() {
866
+ return world;
867
+ },
868
+ configure,
869
+ frame_preset,
870
+ /**
871
+ * Put the camera where the scene's path has it at time `t`, and the movers with it.
872
+ * @param {number} t seconds along the path
873
+ */
874
+ path_at(t) {
875
+ time = t;
876
+ world.update(t);
877
+ world.path(t, path_from, path_to);
878
+ look(path_from, path_to);
879
+ },
880
+ measure_scene,
881
+ measure_cost,
882
+ verify,
883
+ };
884
+
885
+ globalThis.verify = verify;
886
+
887
+ report(RUNNING);
888
+ }