@driftengine/core 3.62.0 → 4.0.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 (428) hide show
  1. package/CHANGELOG.json +122 -0
  2. package/NOTICE +20 -0
  3. package/README.md +1 -1
  4. package/dist/core/loop.js +18 -2
  5. package/dist/core/storage.js +5 -0
  6. package/dist/geometry/meshBuilder.d.ts +1 -1
  7. package/dist/geometry/meshBuilder.js +6 -2
  8. package/dist/index.d.ts +70 -4
  9. package/dist/index.js +123 -2
  10. package/dist/input/input.js +6 -1
  11. package/dist/math/exact.d.ts +13 -3
  12. package/dist/math/exact.js +68 -3
  13. package/dist/math/frustum.d.ts +17 -2
  14. package/dist/math/frustum.js +24 -0
  15. package/dist/render/backend/api.d.ts +34 -1
  16. package/dist/render/backend/api.js +22 -1
  17. package/dist/render/backend/budget.d.ts +7 -6
  18. package/dist/render/backend/budget.js +7 -6
  19. package/dist/render/backend/createRenderer.d.ts +57 -0
  20. package/dist/render/backend/createRenderer.js +51 -2
  21. package/dist/render/backend/materialChanges.d.ts +41 -0
  22. package/dist/render/backend/materialChanges.js +38 -0
  23. package/dist/render/backend/select.js +8 -0
  24. package/dist/render/backend/webgl2/renderer.d.ts +80 -1
  25. package/dist/render/backend/webgl2/renderer.js +208 -10
  26. package/dist/render/backend/webgpu/buffers.d.ts +20 -1
  27. package/dist/render/backend/webgpu/buffers.js +116 -58
  28. package/dist/render/backend/webgpu/fieldCompose.d.ts +156 -0
  29. package/dist/render/backend/webgpu/fieldCompose.js +396 -0
  30. package/dist/render/backend/webgpu/giFieldPass.d.ts +66 -0
  31. package/dist/render/backend/webgpu/giFieldPass.js +137 -0
  32. package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +728 -0
  33. package/dist/render/backend/webgpu/gpuDrivenPass.js +2473 -0
  34. package/dist/render/backend/webgpu/linePass.d.ts +4 -14
  35. package/dist/render/backend/webgpu/linePass.js +4 -33
  36. package/dist/render/backend/webgpu/probeBake.d.ts +148 -0
  37. package/dist/render/backend/webgpu/probeBake.js +493 -0
  38. package/dist/render/backend/webgpu/renderer.d.ts +379 -24
  39. package/dist/render/backend/webgpu/renderer.js +1369 -76
  40. package/dist/render/backend/webgpu/scatterPass.js +15 -1
  41. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +47 -14
  42. package/dist/render/backend/webgpu/surfaceTexturePass.js +128 -80
  43. package/dist/render/causticsRenderer.d.ts +3 -1
  44. package/dist/render/causticsRenderer.js +4 -1
  45. package/dist/render/depthConvention.d.ts +12 -0
  46. package/dist/render/depthConvention.js +14 -0
  47. package/dist/render/deviceFeatures.d.ts +32 -0
  48. package/dist/render/deviceFeatures.js +41 -0
  49. package/dist/render/fog.d.ts +79 -0
  50. package/dist/render/fog.js +138 -0
  51. package/dist/render/frame/alias.d.ts +30 -0
  52. package/dist/render/frame/alias.js +61 -0
  53. package/dist/render/frame/deps.d.ts +37 -0
  54. package/dist/render/frame/deps.js +122 -0
  55. package/dist/render/frame/flushGraph.d.ts +43 -0
  56. package/dist/render/frame/flushGraph.js +84 -0
  57. package/dist/render/frame/graphSchedule.d.ts +49 -0
  58. package/dist/render/frame/graphSchedule.js +120 -0
  59. package/dist/render/frame/index.d.ts +15 -0
  60. package/dist/render/frame/index.js +8 -0
  61. package/dist/render/frame/lifetime.d.ts +24 -0
  62. package/dist/render/frame/lifetime.js +36 -0
  63. package/dist/render/frame/passTimings.d.ts +42 -0
  64. package/dist/render/frame/passTimings.js +38 -0
  65. package/dist/render/frame/validate.d.ts +15 -0
  66. package/dist/render/frame/validate.js +22 -0
  67. package/dist/render/frame/virtual.d.ts +44 -0
  68. package/dist/render/frame/virtual.js +61 -0
  69. package/dist/render/gi/chain.d.ts +82 -0
  70. package/dist/render/gi/chain.js +135 -0
  71. package/dist/render/gi/denoise.d.ts +114 -0
  72. package/dist/render/gi/denoise.js +169 -0
  73. package/dist/render/gi/fieldScene.d.ts +125 -0
  74. package/dist/render/gi/fieldScene.js +219 -0
  75. package/dist/render/gi/globalField.d.ts +157 -0
  76. package/dist/render/gi/globalField.js +373 -0
  77. package/dist/render/gi/probeGridFit.d.ts +24 -0
  78. package/dist/render/gi/probeGridFit.js +71 -0
  79. package/dist/render/gi/probeTrace.d.ts +82 -0
  80. package/dist/render/gi/probeTrace.js +128 -0
  81. package/dist/render/gi/probeVolume.d.ts +136 -0
  82. package/dist/render/gi/probeVolume.js +191 -0
  83. package/dist/render/gi/reflection.d.ts +73 -0
  84. package/dist/render/gi/reflection.js +109 -0
  85. package/dist/render/gi/traceField.d.ts +91 -0
  86. package/dist/render/gi/traceField.js +129 -0
  87. package/dist/render/gi/traceScreen.d.ts +68 -0
  88. package/dist/render/gi/traceScreen.js +82 -0
  89. package/dist/render/gpuScene.d.ts +38 -0
  90. package/dist/render/gpuScene.js +41 -0
  91. package/dist/render/gpudriven/alphaTest.d.ts +28 -0
  92. package/dist/render/gpudriven/alphaTest.js +32 -0
  93. package/dist/render/gpudriven/clusterUpload.d.ts +59 -0
  94. package/dist/render/gpudriven/clusterUpload.js +75 -0
  95. package/dist/render/gpudriven/clusterWorld.d.ts +57 -0
  96. package/dist/render/gpudriven/clusterWorld.js +155 -0
  97. package/dist/render/gpudriven/compact.d.ts +51 -0
  98. package/dist/render/gpudriven/compact.js +68 -0
  99. package/dist/render/gpudriven/cullClusters.d.ts +129 -0
  100. package/dist/render/gpudriven/cullClusters.js +237 -0
  101. package/dist/render/gpudriven/decodeTables.d.ts +64 -0
  102. package/dist/render/gpudriven/decodeTables.js +219 -0
  103. package/dist/render/gpudriven/frustum.d.ts +25 -0
  104. package/dist/render/gpudriven/frustum.js +59 -0
  105. package/dist/render/gpudriven/geometryHarness.d.ts +15 -0
  106. package/dist/render/gpudriven/geometryHarness.js +31 -0
  107. package/dist/render/gpudriven/hzb.d.ts +60 -0
  108. package/dist/render/gpudriven/hzb.js +97 -0
  109. package/dist/render/gpudriven/ibl.d.ts +85 -0
  110. package/dist/render/gpudriven/ibl.js +129 -0
  111. package/dist/render/gpudriven/indirect.d.ts +67 -0
  112. package/dist/render/gpudriven/indirect.js +77 -0
  113. package/dist/render/gpudriven/instances.d.ts +43 -0
  114. package/dist/render/gpudriven/instances.js +172 -0
  115. package/dist/render/gpudriven/lit.d.ts +165 -0
  116. package/dist/render/gpudriven/lit.js +165 -0
  117. package/dist/render/gpudriven/lodCut.d.ts +28 -0
  118. package/dist/render/gpudriven/lodCut.js +38 -0
  119. package/dist/render/gpudriven/materialBin.d.ts +60 -0
  120. package/dist/render/gpudriven/materialBin.js +108 -0
  121. package/dist/render/gpudriven/materialTable.d.ts +88 -0
  122. package/dist/render/gpudriven/materialTable.js +115 -0
  123. package/dist/render/gpudriven/pipeline.d.ts +135 -0
  124. package/dist/render/gpudriven/pipeline.js +237 -0
  125. package/dist/render/gpudriven/rangeAlloc.d.ts +50 -0
  126. package/dist/render/gpudriven/rangeAlloc.js +112 -0
  127. package/dist/render/gpudriven/sceneUpload.d.ts +96 -0
  128. package/dist/render/gpudriven/sceneUpload.js +115 -0
  129. package/dist/render/gpudriven/shadeBins.d.ts +92 -0
  130. package/dist/render/gpudriven/shadeBins.js +182 -0
  131. package/dist/render/gpudriven/shadow.d.ts +136 -0
  132. package/dist/render/gpudriven/shadow.js +224 -0
  133. package/dist/render/gpudriven/shadowCamera.d.ts +87 -0
  134. package/dist/render/gpudriven/shadowCamera.js +345 -0
  135. package/dist/render/gpudriven/streamScene.d.ts +194 -0
  136. package/dist/render/gpudriven/streamScene.js +459 -0
  137. package/dist/render/gpudriven/surfaceFrame.d.ts +25 -0
  138. package/dist/render/gpudriven/surfaceFrame.js +51 -0
  139. package/dist/render/gpudriven/twoPhase.d.ts +122 -0
  140. package/dist/render/gpudriven/twoPhase.js +160 -0
  141. package/dist/render/gpudriven/visbuffer.d.ts +25 -0
  142. package/dist/render/gpudriven/visbuffer.js +37 -0
  143. package/dist/render/halfFloat.d.ts +10 -0
  144. package/dist/render/halfFloat.js +23 -4
  145. package/dist/render/inference/attentionTiled.d.ts +27 -0
  146. package/dist/render/inference/attentionTiled.js +117 -0
  147. package/dist/render/inference/denseKernels.d.ts +29 -0
  148. package/dist/render/inference/denseKernels.js +312 -0
  149. package/dist/render/inference/device.d.ts +21 -0
  150. package/dist/render/inference/device.js +32 -0
  151. package/dist/render/inference/deviceGraph.d.ts +34 -0
  152. package/dist/render/inference/deviceGraph.js +17 -0
  153. package/dist/render/inference/fuse.d.ts +15 -0
  154. package/dist/render/inference/fuse.js +37 -0
  155. package/dist/render/inference/kernelKit.d.ts +52 -0
  156. package/dist/render/inference/kernelKit.js +70 -0
  157. package/dist/render/inference/kernels.d.ts +3 -0
  158. package/dist/render/inference/kernels.js +11 -0
  159. package/dist/render/inference/plan.d.ts +13 -0
  160. package/dist/render/inference/plan.js +18 -0
  161. package/dist/render/inference/reuse.d.ts +39 -0
  162. package/dist/render/inference/reuse.js +65 -0
  163. package/dist/render/inference/runner.d.ts +31 -0
  164. package/dist/render/inference/runner.js +175 -0
  165. package/dist/render/inference/schedule.d.ts +39 -0
  166. package/dist/render/inference/schedule.js +59 -0
  167. package/dist/render/inference/shapeKernels.d.ts +10 -0
  168. package/dist/render/inference/shapeKernels.js +80 -0
  169. package/dist/render/inference/spatialKernels.d.ts +21 -0
  170. package/dist/render/inference/spatialKernels.js +179 -0
  171. package/dist/render/inference/splatRaster.wgsl.d.ts +75 -0
  172. package/dist/render/inference/splatRaster.wgsl.js +337 -0
  173. package/dist/render/inference/splatTiles.d.ts +79 -0
  174. package/dist/render/inference/splatTiles.js +161 -0
  175. package/dist/render/lineBatch.d.ts +2 -5
  176. package/dist/render/lineBatch.js +4 -24
  177. package/dist/render/mesh.d.ts +4 -0
  178. package/dist/render/mesh.js +45 -1
  179. package/dist/render/pass.d.ts +145 -8
  180. package/dist/render/prefilterEnvMap.d.ts +22 -0
  181. package/dist/render/prefilterEnvMap.js +31 -0
  182. package/dist/render/readback.d.ts +30 -0
  183. package/dist/render/readback.js +47 -0
  184. package/dist/render/recon/clamp.d.ts +36 -0
  185. package/dist/render/recon/clamp.js +92 -0
  186. package/dist/render/recon/disocclusion.d.ts +60 -0
  187. package/dist/render/recon/disocclusion.js +109 -0
  188. package/dist/render/recon/frameGen.d.ts +81 -0
  189. package/dist/render/recon/frameGen.js +150 -0
  190. package/dist/render/recon/frameSizes.d.ts +34 -0
  191. package/dist/render/recon/frameSizes.js +58 -0
  192. package/dist/render/recon/jitter.d.ts +60 -0
  193. package/dist/render/recon/jitter.js +118 -0
  194. package/dist/render/recon/motionVectors.d.ts +55 -0
  195. package/dist/render/recon/motionVectors.js +107 -0
  196. package/dist/render/recon/reproject.d.ts +41 -0
  197. package/dist/render/recon/reproject.js +131 -0
  198. package/dist/render/recon/resolve.d.ts +90 -0
  199. package/dist/render/recon/resolve.js +313 -0
  200. package/dist/render/recon/tier.d.ts +24 -0
  201. package/dist/render/recon/tier.js +8 -0
  202. package/dist/render/reflectionProbe.d.ts +26 -0
  203. package/dist/render/reflectionProbe.js +33 -0
  204. package/dist/render/renderQuality.d.ts +69 -0
  205. package/dist/render/renderQuality.js +22 -0
  206. package/dist/render/screenSpaceReflection.d.ts +23 -0
  207. package/dist/render/screenSpaceReflection.js +22 -3
  208. package/dist/render/sdfFont.js +2 -0
  209. package/dist/render/segmentQuads.d.ts +13 -0
  210. package/dist/render/segmentQuads.js +32 -0
  211. package/dist/render/shaders/flat/lobes.d.ts +27 -0
  212. package/dist/render/shaders/flat/lobes.js +33 -3
  213. package/dist/render/shaders/flat/preamble.d.ts +7 -0
  214. package/dist/render/shaders/flat/preamble.js +24 -1
  215. package/dist/render/shaders/flat/probeGrid.d.ts +1 -1
  216. package/dist/render/shaders/flat/probeGrid.js +71 -2
  217. package/dist/render/shaders/generated/flat.wgsl.d.ts +48 -8
  218. package/dist/render/shaders/generated/flat.wgsl.js +64 -24
  219. package/dist/render/shaders/gi/composeField.wgsl.d.ts +56 -0
  220. package/dist/render/shaders/gi/composeField.wgsl.js +231 -0
  221. package/dist/render/shaders/gi/marchField.wgsl.d.ts +30 -0
  222. package/dist/render/shaders/gi/marchField.wgsl.js +141 -0
  223. package/dist/render/shaders/gi/probeBake.wgsl.d.ts +113 -0
  224. package/dist/render/shaders/gi/probeBake.wgsl.js +635 -0
  225. package/dist/render/shaders/gi/probeTrace.wgsl.d.ts +72 -0
  226. package/dist/render/shaders/gi/probeTrace.wgsl.js +261 -0
  227. package/dist/render/shaders/gi/probeVolume.wgsl.d.ts +49 -0
  228. package/dist/render/shaders/gi/probeVolume.wgsl.js +242 -0
  229. package/dist/render/shaders/gi/sampleField.wgsl.d.ts +32 -0
  230. package/dist/render/shaders/gi/sampleField.wgsl.js +134 -0
  231. package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +26 -0
  232. package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +339 -0
  233. package/dist/render/shaders/gpudriven/compact.wgsl.d.ts +29 -0
  234. package/dist/render/shaders/gpudriven/compact.wgsl.js +58 -0
  235. package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +90 -0
  236. package/dist/render/shaders/gpudriven/cull.wgsl.js +423 -0
  237. package/dist/render/shaders/gpudriven/decode.wgsl.d.ts +72 -0
  238. package/dist/render/shaders/gpudriven/decode.wgsl.js +349 -0
  239. package/dist/render/shaders/gpudriven/environment.wgsl.d.ts +44 -0
  240. package/dist/render/shaders/gpudriven/environment.wgsl.js +137 -0
  241. package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +28 -0
  242. package/dist/render/shaders/gpudriven/fog.wgsl.js +107 -0
  243. package/dist/render/shaders/gpudriven/frameBlock.wgsl.d.ts +13 -0
  244. package/dist/render/shaders/gpudriven/frameBlock.wgsl.js +62 -0
  245. package/dist/render/shaders/gpudriven/materialBin.wgsl.d.ts +51 -0
  246. package/dist/render/shaders/gpudriven/materialBin.wgsl.js +112 -0
  247. package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +25 -0
  248. package/dist/render/shaders/gpudriven/materialTable.wgsl.js +43 -0
  249. package/dist/render/shaders/gpudriven/meshTransform.wgsl.d.ts +18 -0
  250. package/dist/render/shaders/gpudriven/meshTransform.wgsl.js +37 -0
  251. package/dist/render/shaders/gpudriven/present.wgsl.d.ts +43 -0
  252. package/dist/render/shaders/gpudriven/present.wgsl.js +127 -0
  253. package/dist/render/shaders/gpudriven/shade.wgsl.d.ts +127 -0
  254. package/dist/render/shaders/gpudriven/shade.wgsl.js +874 -0
  255. package/dist/render/shaders/gpudriven/shadow.wgsl.d.ts +44 -0
  256. package/dist/render/shaders/gpudriven/shadow.wgsl.js +308 -0
  257. package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.d.ts +28 -0
  258. package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.js +245 -0
  259. package/dist/render/shaders/network.wgsl.d.ts +101 -0
  260. package/dist/render/shaders/network.wgsl.js +206 -0
  261. package/dist/render/shaders/recon/motion.wgsl.d.ts +44 -0
  262. package/dist/render/shaders/recon/motion.wgsl.js +96 -0
  263. package/dist/render/shaders/recon/resolve.wgsl.d.ts +51 -0
  264. package/dist/render/shaders/recon/resolve.wgsl.js +733 -0
  265. package/dist/render/temporalAa.js +8 -33
  266. package/dist/render/textLayout.js +12 -6
  267. package/dist/render/textRenderer.d.ts +3 -1
  268. package/dist/render/textRenderer.js +4 -1
  269. package/dist/render/translucentQueue.d.ts +6 -0
  270. package/dist/render/translucentQueue.js +11 -0
  271. package/dist/render/windStreakRenderer.d.ts +2 -1
  272. package/dist/render/windStreakRenderer.js +3 -1
  273. package/dist/world/cell.d.ts +63 -0
  274. package/dist/world/cell.js +181 -0
  275. package/dist/world/cellStream.d.ts +103 -0
  276. package/dist/world/cellStream.js +198 -0
  277. package/dist/world/freeze.d.ts +81 -0
  278. package/dist/world/freeze.js +114 -0
  279. package/dist/world/rebase.d.ts +29 -0
  280. package/dist/world/rebase.js +41 -0
  281. package/package.json +8 -3
  282. package/scripts/frames.mjs +92 -0
  283. package/scripts/gpuCompute.mjs +323 -0
  284. package/scripts/png.d.mts +16 -0
  285. package/scripts/png.mjs +25 -0
  286. package/src/core/loop.ts +19 -2
  287. package/src/core/storage.ts +5 -0
  288. package/src/geometry/meshBuilder.ts +5 -1
  289. package/src/index.ts +261 -4
  290. package/src/input/input.ts +6 -1
  291. package/src/math/exact.ts +69 -3
  292. package/src/math/frustum.ts +52 -3
  293. package/src/render/backend/api.ts +42 -1
  294. package/src/render/backend/budget.ts +7 -6
  295. package/src/render/backend/createRenderer.ts +92 -3
  296. package/src/render/backend/materialChanges.ts +54 -0
  297. package/src/render/backend/select.ts +8 -0
  298. package/src/render/backend/webgl2/renderer.ts +211 -9
  299. package/src/render/backend/webgpu/buffers.ts +182 -69
  300. package/src/render/backend/webgpu/fieldCompose.ts +482 -0
  301. package/src/render/backend/webgpu/giFieldPass.ts +200 -0
  302. package/src/render/backend/webgpu/gpuDrivenPass.ts +2993 -0
  303. package/src/render/backend/webgpu/linePass.ts +4 -39
  304. package/src/render/backend/webgpu/probeBake.ts +588 -0
  305. package/src/render/backend/webgpu/renderer.ts +1481 -76
  306. package/src/render/backend/webgpu/scatterPass.ts +15 -1
  307. package/src/render/backend/webgpu/surfaceTexturePass.ts +158 -88
  308. package/src/render/causticsRenderer.ts +5 -2
  309. package/src/render/depthConvention.ts +15 -0
  310. package/src/render/deviceFeatures.ts +77 -0
  311. package/src/render/fog.ts +185 -0
  312. package/src/render/frame/alias.ts +97 -0
  313. package/src/render/frame/deps.ts +155 -0
  314. package/src/render/frame/flushGraph.ts +135 -0
  315. package/src/render/frame/graphSchedule.ts +170 -0
  316. package/src/render/frame/index.ts +52 -0
  317. package/src/render/frame/lifetime.ts +61 -0
  318. package/src/render/frame/passTimings.ts +69 -0
  319. package/src/render/frame/validate.ts +40 -0
  320. package/src/render/frame/virtual.ts +91 -0
  321. package/src/render/gi/chain.ts +225 -0
  322. package/src/render/gi/denoise.ts +276 -0
  323. package/src/render/gi/fieldScene.ts +264 -0
  324. package/src/render/gi/globalField.ts +543 -0
  325. package/src/render/gi/probeGridFit.ts +89 -0
  326. package/src/render/gi/probeTrace.ts +143 -0
  327. package/src/render/gi/probeVolume.ts +288 -0
  328. package/src/render/gi/reflection.ts +163 -0
  329. package/src/render/gi/traceField.ts +223 -0
  330. package/src/render/gi/traceScreen.ts +106 -0
  331. package/src/render/gpuScene.ts +80 -0
  332. package/src/render/gpudriven/alphaTest.ts +33 -0
  333. package/src/render/gpudriven/clusterUpload.ts +123 -0
  334. package/src/render/gpudriven/clusterWorld.ts +239 -0
  335. package/src/render/gpudriven/compact.ts +80 -0
  336. package/src/render/gpudriven/cullClusters.ts +333 -0
  337. package/src/render/gpudriven/decodeTables.ts +332 -0
  338. package/src/render/gpudriven/frustum.ts +70 -0
  339. package/src/render/gpudriven/geometryHarness.ts +51 -0
  340. package/src/render/gpudriven/hzb.ts +113 -0
  341. package/src/render/gpudriven/ibl.ts +147 -0
  342. package/src/render/gpudriven/indirect.ts +89 -0
  343. package/src/render/gpudriven/instances.ts +234 -0
  344. package/src/render/gpudriven/lit.ts +329 -0
  345. package/src/render/gpudriven/lodCut.ts +62 -0
  346. package/src/render/gpudriven/materialBin.ts +131 -0
  347. package/src/render/gpudriven/materialTable.ts +164 -0
  348. package/src/render/gpudriven/pipeline.ts +336 -0
  349. package/src/render/gpudriven/rangeAlloc.ts +122 -0
  350. package/src/render/gpudriven/sceneUpload.ts +173 -0
  351. package/src/render/gpudriven/shadeBins.ts +222 -0
  352. package/src/render/gpudriven/shadow.ts +285 -0
  353. package/src/render/gpudriven/shadowCamera.ts +406 -0
  354. package/src/render/gpudriven/streamScene.ts +575 -0
  355. package/src/render/gpudriven/surfaceFrame.ts +68 -0
  356. package/src/render/gpudriven/twoPhase.ts +214 -0
  357. package/src/render/gpudriven/visbuffer.ts +41 -0
  358. package/src/render/halfFloat.ts +22 -4
  359. package/src/render/inference/attentionTiled.ts +132 -0
  360. package/src/render/inference/denseKernels.ts +369 -0
  361. package/src/render/inference/device.ts +44 -0
  362. package/src/render/inference/deviceGraph.ts +39 -0
  363. package/src/render/inference/fuse.ts +47 -0
  364. package/src/render/inference/kernelKit.ts +120 -0
  365. package/src/render/inference/kernels.ts +18 -0
  366. package/src/render/inference/plan.ts +26 -0
  367. package/src/render/inference/reuse.ts +79 -0
  368. package/src/render/inference/runner.ts +204 -0
  369. package/src/render/inference/schedule.ts +80 -0
  370. package/src/render/inference/shapeKernels.ts +112 -0
  371. package/src/render/inference/spatialKernels.ts +220 -0
  372. package/src/render/inference/splatRaster.wgsl.ts +348 -0
  373. package/src/render/inference/splatTiles.ts +186 -0
  374. package/src/render/lineBatch.ts +4 -24
  375. package/src/render/mesh.ts +46 -1
  376. package/src/render/pass.ts +155 -10
  377. package/src/render/prefilterEnvMap.ts +33 -0
  378. package/src/render/readback.ts +73 -0
  379. package/src/render/recon/clamp.ts +113 -0
  380. package/src/render/recon/disocclusion.ts +143 -0
  381. package/src/render/recon/frameGen.ts +191 -0
  382. package/src/render/recon/frameSizes.ts +64 -0
  383. package/src/render/recon/jitter.ts +126 -0
  384. package/src/render/recon/motionVectors.ts +138 -0
  385. package/src/render/recon/reproject.ts +179 -0
  386. package/src/render/recon/resolve.ts +444 -0
  387. package/src/render/recon/tier.ts +31 -0
  388. package/src/render/reflectionProbe.ts +34 -0
  389. package/src/render/renderQuality.ts +87 -0
  390. package/src/render/screenSpaceReflection.ts +37 -3
  391. package/src/render/sdfFont.ts +2 -0
  392. package/src/render/segmentQuads.ts +39 -0
  393. package/src/render/shaders/flat/lobes.ts +35 -3
  394. package/src/render/shaders/flat/preamble.ts +25 -1
  395. package/src/render/shaders/flat/probeGrid.ts +77 -2
  396. package/src/render/shaders/generated/flat.wgsl.ts +64 -24
  397. package/src/render/shaders/gi/composeField.wgsl.ts +239 -0
  398. package/src/render/shaders/gi/marchField.wgsl.ts +146 -0
  399. package/src/render/shaders/gi/probeBake.wgsl.ts +649 -0
  400. package/src/render/shaders/gi/probeTrace.wgsl.ts +269 -0
  401. package/src/render/shaders/gi/probeVolume.wgsl.ts +246 -0
  402. package/src/render/shaders/gi/sampleField.wgsl.ts +140 -0
  403. package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +343 -0
  404. package/src/render/shaders/gpudriven/compact.wgsl.ts +59 -0
  405. package/src/render/shaders/gpudriven/cull.wgsl.ts +433 -0
  406. package/src/render/shaders/gpudriven/decode.wgsl.ts +373 -0
  407. package/src/render/shaders/gpudriven/environment.wgsl.ts +141 -0
  408. package/src/render/shaders/gpudriven/fog.wgsl.ts +110 -0
  409. package/src/render/shaders/gpudriven/frameBlock.wgsl.ts +62 -0
  410. package/src/render/shaders/gpudriven/materialBin.wgsl.ts +116 -0
  411. package/src/render/shaders/gpudriven/materialTable.wgsl.ts +46 -0
  412. package/src/render/shaders/gpudriven/meshTransform.wgsl.ts +37 -0
  413. package/src/render/shaders/gpudriven/present.wgsl.ts +129 -0
  414. package/src/render/shaders/gpudriven/shade.wgsl.ts +884 -0
  415. package/src/render/shaders/gpudriven/shadow.wgsl.ts +322 -0
  416. package/src/render/shaders/gpudriven/visbufferRaster.wgsl.ts +251 -0
  417. package/src/render/shaders/network.wgsl.ts +238 -0
  418. package/src/render/shaders/recon/motion.wgsl.ts +101 -0
  419. package/src/render/shaders/recon/resolve.wgsl.ts +741 -0
  420. package/src/render/temporalAa.ts +9 -33
  421. package/src/render/textLayout.ts +12 -6
  422. package/src/render/textRenderer.ts +5 -2
  423. package/src/render/translucentQueue.ts +11 -0
  424. package/src/render/windStreakRenderer.ts +4 -2
  425. package/src/world/cell.ts +231 -0
  426. package/src/world/cellStream.ts +278 -0
  427. package/src/world/freeze.ts +157 -0
  428. package/src/world/rebase.ts +56 -0
@@ -19,9 +19,11 @@ const SUPPORTED_VERSION = 1;
19
19
  * beside a reference and they do not match. Every other required field is checked the same way.
20
20
  */
21
21
  export function parseSdfFont(document) {
22
+ // platform: feature probe — a bake and a worker both reach here without one
22
23
  if (typeof document !== 'object' || document === null) {
23
24
  throw new Error('parseSdfFont: expected a metrics object');
24
25
  }
26
+ // platform: feature probe — guarded by the line above
25
27
  const source = document;
26
28
  if (source['version'] !== SUPPORTED_VERSION) {
27
29
  throw new Error(`parseSdfFont: metrics version ${String(source['version'])}, this build reads ${SUPPORTED_VERSION}`);
@@ -1,4 +1,5 @@
1
1
  import type { BoltSegments } from './boltPool.ts';
2
+ import type { LineSegments } from './linePoints.ts';
2
3
  /**
3
4
  * How a list of segments becomes triangles, held once for every renderer that draws one.
4
5
  *
@@ -27,3 +28,15 @@ export declare function buildSegmentQuads(capacity: number): SegmentQuads;
27
28
  * capacity — a pool that overruns loses its tail rather than the frame.
28
29
  */
29
30
  export declare function expandBoltSegments(data: BoltSegments, capacity: number, from: Float32Array, to: Float32Array, arc: Float32Array): number;
31
+ /**
32
+ * Expand this frame's segments to their four vertices each, into arrays the caller owns.
33
+ *
34
+ * Returns how many segments were written, which is the list's count clamped to the batch's
35
+ * capacity — a caller that overruns loses its tail rather than its frame, the same rule
36
+ * `expandBoltSegments` follows. Reads only `LineSegments.from`/`.to`.
37
+ *
38
+ * **Both backends call it**, which is the reason it is here: the WebGL2 batch wrote the same walk
39
+ * inline until 2026-09-19, so the number of segments a batch draws — and so whether it draws at
40
+ * all, and is counted — was one decision written twice.
41
+ */
42
+ export declare function expandLineSegments(data: LineSegments, capacity: number, from: Float32Array, to: Float32Array): number;
@@ -73,3 +73,35 @@ export function expandBoltSegments(data, capacity, from, to, arc) {
73
73
  }
74
74
  return count;
75
75
  }
76
+ /**
77
+ * Expand this frame's segments to their four vertices each, into arrays the caller owns.
78
+ *
79
+ * Returns how many segments were written, which is the list's count clamped to the batch's
80
+ * capacity — a caller that overruns loses its tail rather than its frame, the same rule
81
+ * `expandBoltSegments` follows. Reads only `LineSegments.from`/`.to`.
82
+ *
83
+ * **Both backends call it**, which is the reason it is here: the WebGL2 batch wrote the same walk
84
+ * inline until 2026-09-19, so the number of segments a batch draws — and so whether it draws at
85
+ * all, and is counted — was one decision written twice.
86
+ */
87
+ export function expandLineSegments(data, capacity, from, to) {
88
+ const count = Math.min(data.count, capacity);
89
+ for (let s = 0; s < count; s++) {
90
+ const fx = data.from[s * 3];
91
+ const fy = data.from[s * 3 + 1];
92
+ const fz = data.from[s * 3 + 2];
93
+ const tx = data.to[s * 3];
94
+ const ty = data.to[s * 3 + 1];
95
+ const tz = data.to[s * 3 + 2];
96
+ for (let c = 0; c < 4; c++) {
97
+ const v = s * 4 + c;
98
+ from[v * 3] = fx;
99
+ from[v * 3 + 1] = fy;
100
+ from[v * 3 + 2] = fz;
101
+ to[v * 3] = tx;
102
+ to[v * 3 + 1] = ty;
103
+ to[v * 3 + 2] = tz;
104
+ }
105
+ }
106
+ return count;
107
+ }
@@ -1 +1,28 @@
1
+ /**
2
+ * How much of a self-lit surface's glow a shadow may take. See the GLSL constant's own comment.
3
+ *
4
+ * Exported because the GPU-driven pipeline dims its emission by the same share, and a number two
5
+ * shaders read is a number that belongs in one place.
6
+ */
7
+ export declare const EMISSIVE_SHADOW_SHARE = 0.55;
8
+ /**
9
+ * The narrowest lobe this engine draws, as the distribution's own width.
10
+ *
11
+ * **Derived rather than chosen.** These lobes are divided by their own peak, `a2*a2 / (d*d)`, and
12
+ * the division is guarded at `1e-8` so a mirror cannot divide by nothing. At the peak `d` *is*
13
+ * `a2`, so the guard starts binding exactly where `a2*a2` reaches `1e-8` — at `a = 0.01` — and
14
+ * below that it scales the answer instead of protecting it: the peak fell to **0.0039 at roughness
15
+ * 0.05, 256 times dimmer than at 0.1**, so a polished surface had a fainter highlight than a satin
16
+ * one. Flooring `a` here keeps the peak at one for every roughness and leaves the guard as the
17
+ * guard it was meant to be.
18
+ *
19
+ * **What it gives up**: a surface smoother than this is drawn at this width rather than narrower.
20
+ * That is the same trade `sphereLobe` argues below — a reflection narrower than a fragment cannot
21
+ * be sampled and comes back as speckle — so the floor is where the engine stops pretending to
22
+ * resolve something it cannot. **What would make it wrong** is a path that integrates the lobe
23
+ * rather than sampling it at a point, where the narrow tail is carried by the integral;
24
+ * `prefilter.ts`'s `ggxDistribution` is that path, keeps the honest normalisation, and is
25
+ * deliberately not this.
26
+ */
27
+ export declare const MIN_LOBE_ALPHA = 0.01;
1
28
  export declare const LOBES_GLSL: string;
@@ -1,5 +1,32 @@
1
1
  /** How light falls off with distance, and the specular lobes a highlight is made of. */
2
2
  import { POINT_SHADOW_FADE_START } from '../../renderQuality.js';
3
+ /**
4
+ * How much of a self-lit surface's glow a shadow may take. See the GLSL constant's own comment.
5
+ *
6
+ * Exported because the GPU-driven pipeline dims its emission by the same share, and a number two
7
+ * shaders read is a number that belongs in one place.
8
+ */
9
+ export const EMISSIVE_SHADOW_SHARE = 0.55;
10
+ /**
11
+ * The narrowest lobe this engine draws, as the distribution's own width.
12
+ *
13
+ * **Derived rather than chosen.** These lobes are divided by their own peak, `a2*a2 / (d*d)`, and
14
+ * the division is guarded at `1e-8` so a mirror cannot divide by nothing. At the peak `d` *is*
15
+ * `a2`, so the guard starts binding exactly where `a2*a2` reaches `1e-8` — at `a = 0.01` — and
16
+ * below that it scales the answer instead of protecting it: the peak fell to **0.0039 at roughness
17
+ * 0.05, 256 times dimmer than at 0.1**, so a polished surface had a fainter highlight than a satin
18
+ * one. Flooring `a` here keeps the peak at one for every roughness and leaves the guard as the
19
+ * guard it was meant to be.
20
+ *
21
+ * **What it gives up**: a surface smoother than this is drawn at this width rather than narrower.
22
+ * That is the same trade `sphereLobe` argues below — a reflection narrower than a fragment cannot
23
+ * be sampled and comes back as speckle — so the floor is where the engine stops pretending to
24
+ * resolve something it cannot. **What would make it wrong** is a path that integrates the lobe
25
+ * rather than sampling it at a point, where the narrow tail is carried by the integral;
26
+ * `prefilter.ts`'s `ggxDistribution` is that path, keeps the honest normalisation, and is
27
+ * deliberately not this.
28
+ */
29
+ export const MIN_LOBE_ALPHA = 0.01;
3
30
  export const LOBES_GLSL = `float shadowReach(float distance, float maxDistance) {
4
31
  return 1.0 - smoothstep(
5
32
  maxDistance * ${POINT_SHADOW_FADE_START.toFixed(2)},
@@ -52,7 +79,10 @@ const float MAX_FILTER_RADIUS = 0.25;
52
79
  * something passed in front of it, which is worse. Just over half reads as an inlay lit
53
80
  * from within a deck that is itself in shade.
54
81
  */
55
- const float EMISSIVE_SHADOW_SHARE = 0.55;
82
+ const float EMISSIVE_SHADOW_SHARE = ${EMISSIVE_SHADOW_SHARE};
83
+
84
+ /* The narrowest lobe this engine draws. See MIN_LOBE_ALPHA in this module for why it is this. */
85
+ const float MIN_LOBE_ALPHA = ${MIN_LOBE_ALPHA};
56
86
 
57
87
  /*
58
88
  * Trowbridge-Reitz, because the width of a highlight is the whole effect.
@@ -76,7 +106,7 @@ const float EMISSIVE_SHADOW_SHARE = 0.55;
76
106
  * is a multiply cheaper than the honest spelling as well.
77
107
  */
78
108
  float specularLobe(float ndh, float roughness) {
79
- float a = max(roughness * roughness, 1e-3);
109
+ float a = max(roughness * roughness, MIN_LOBE_ALPHA);
80
110
  float a2 = a * a;
81
111
  float d = ndh * ndh * (a2 - 1.0) + 1.0;
82
112
  return (a2 * a2) / max(d * d, 1e-8);
@@ -102,7 +132,7 @@ float specularLobe(float ndh, float roughness) {
102
132
  * scene ever does, so r/d is large and its highlight is genuinely broad.
103
133
  */
104
134
  float sphereLobe(float ndh, float roughness, float sourceRadius, float dist) {
105
- float a = max(roughness * roughness, 1e-3);
135
+ float a = max(roughness * roughness, MIN_LOBE_ALPHA);
106
136
  float widened = clamp(a + sourceRadius / max(2.0 * dist, 1e-3), a, 1.0);
107
137
  float energy = (a / widened) * (a / widened);
108
138
  float w2 = widened * widened;
@@ -1,3 +1,10 @@
1
+ /**
2
+ * How much roughness a relieved or normal-mapped surface gains per unit of relief.
3
+ *
4
+ * Exported because the GPU-driven pipeline widens its roughness by a normal map's strength the way
5
+ * this shader does, and one number read by two shaders is a number that cannot drift between them.
6
+ */
7
+ export declare const RELIEF_ROUGHNESS = 0.35;
1
8
  import type { LightBudget } from '../../uniformVectorBudget.ts';
2
9
  /**
3
10
  * The preamble, built for one light budget.
@@ -1,6 +1,13 @@
1
1
  /** Version, inputs, uniforms and the defines the rest of the fragment shader is written against. */
2
2
  import { COOKIE_TILE } from '../../lightBudget.js';
3
3
  import { CLUSTER_TEXELS, CLUSTER_X, CLUSTER_Y, CLUSTER_Z, LIGHT_REGION_TEXELS, LIGHT_TEXELS, MAX_LIGHTS_PER_CLUSTER, TABLE_WIDTH, } from '../../clusteredLights.js';
4
+ /**
5
+ * How much roughness a relieved or normal-mapped surface gains per unit of relief.
6
+ *
7
+ * Exported because the GPU-driven pipeline widens its roughness by a normal map's strength the way
8
+ * this shader does, and one number read by two shaders is a number that cannot drift between them.
9
+ */
10
+ export const RELIEF_ROUGHNESS = 0.35;
4
11
  import { MAX_SHADOW_FILTER_TAPS } from '../../renderQuality.js';
5
12
  import { FOG_GLSL } from '../fog.js';
6
13
  /**
@@ -37,7 +44,7 @@ in float vRoughness;
37
44
  * because the amplitude is known here rather than measured off the screen.
38
45
  */
39
46
  #define RELIEF_TILT 1.6
40
- #define RELIEF_ROUGHNESS 0.35
47
+ #define RELIEF_ROUGHNESS ${RELIEF_ROUGHNESS}
41
48
  /**
42
49
  * The furthest a texture-derived bump may turn the shading normal, as a tangent.
43
50
  *
@@ -471,6 +478,22 @@ uniform float uEnvironmentMaxLod;
471
478
  * under-sampled and forced to a roughness it does not have.
472
479
  */
473
480
  uniform float uEnvironmentEdge;
481
+ /**
482
+ * Whether the probe blend consults what each probe can see, and where those moments are.
483
+ *
484
+ * **Zero is off, and off is what every published scene is gated at.** On, each probe's visibility
485
+ * map is a *layer of this same array*, offset past the radiance layers by the grid's probe count:
486
+ * two moments a texel, the mean distance to geometry along a direction and the mean of its square.
487
+ *
488
+ * **In this array rather than a sampler of its own, and branched at run time rather than compiled
489
+ * in or out.** A sampler of its own would be a seventeenth on a backend that guarantees sixteen
490
+ * units — the reason \`environmentProbe\` is a permutation at all — and a permutation flag of its
491
+ * own would double the generated shader corpus for every consumer, which \`scripts/wgsl.ts\` prices
492
+ * at 400,728 to 597,638 gzipped bytes. Sharing the array costs neither: no new unit, no new
493
+ * permutation, and the arithmetic sits behind a branch on this uniform the way the clustered light
494
+ * table's does.
495
+ */
496
+ uniform float uProbeVisibilityEnabled;
474
497
  /**
475
498
  * The level holding the cosine convolution, which is the scene's diffuse ambient.
476
499
  *
@@ -18,4 +18,4 @@
18
18
  * reflection's four are two probes at two levels. A grid of one collapses to one and two, because
19
19
  * every corner resolves to the same layer and the zero-weight ones are skipped.
20
20
  */
21
- export declare const PROBEGRID_GLSL = "#if ENVIRONMENT_PROBE\n/**\n * Where a direction lands in one layer at one level, inset past that level's gutter.\n *\n * The level's own edge rather than the map's, since a gutter is one texel at every level and its\n * share of the map doubles as the chain coarsens.\n */\nvec3 probeCoord(vec3 dir, float level, float layer) {\n float levelEdge = max(uEnvironmentEdge / exp2(level), 4.0);\n return vec3(octInsetUv(dir, levelEdge), layer);\n}\n\n/**\n * A layer index from whole lattice coordinates: x fastest, then y, then z.\n *\n * Clamped, which is what makes an axis one probe wide safe: the second corner of a pair that does\n * not exist resolves to the first, at a weight the caller has already set to zero.\n */\nfloat probeLayer(vec3 index) {\n vec3 top = max(uProbeGridCounts - 1.0, vec3(0.0));\n vec3 held = clamp(index, vec3(0.0), top);\n return held.x + uProbeGridCounts.x * (held.y + uProbeGridCounts.y * held.z);\n}\n\n/**\n * The cell a world position is in, as a base corner and the fraction past it.\n *\n * **Clamped rather than wrapped**, so a point outside the grid takes the nearest probes at full\n * weight \u2014 the environment it would have had one step inside. Wrapping would light one end of a\n * world with the probe from the other end, which is invisible in any test that stays indoors.\n *\n * An axis one probe wide has its fraction forced to zero, so that axis contributes a factor of one\n * to every corner weight and the eight corners collapse onto fewer layers whose weights still sum\n * to one.\n */\nvoid probeCell(vec3 worldPos, out vec3 base, out vec3 frac) {\n vec3 top = max(uProbeGridCounts - 1.0, vec3(0.0));\n vec3 local = clamp((worldPos - uProbeGridOrigin) * uProbeGridInvSpacing, vec3(0.0), top);\n base = min(floor(local), max(top - 1.0, vec3(0.0)));\n frac = local - base;\n frac *= step(vec3(1.5), uProbeGridCounts);\n}\n\n/** One probe's diffuse light: the cosine convolution, at its own level, in one fetch. */\nvec3 probeIrradiance(vec3 dir, float layer) {\n float level = uEnvironmentIrradianceLevel;\n return textureLod(uEnvironment, probeCoord(dir, level, layer), level).rgb;\n}\n\n/**\n * One probe's reflection at a roughness, as two levels mixed by hand.\n *\n * textureLod rather than texture throughout, per the 2026-08-07 rule and for a second reason on\n * top of it: the level is wanted here, and the fetches sit inside a loop that no compiler can\n * prove uniform.\n */\nvec3 probeRadiance(vec3 dir, float lod, float layer) {\n float lo = clamp(floor(lod), 0.0, uEnvironmentMaxLod);\n float hi = min(lo + 1.0, uEnvironmentMaxLod);\n vec3 coarse = textureLod(uEnvironment, probeCoord(dir, hi, layer), hi).rgb;\n vec3 fine = textureLod(uEnvironment, probeCoord(dir, lo, layer), lo).rgb;\n return mix(fine, coarse, clamp(lod - lo, 0.0, 1.0));\n}\n\n/**\n * The grid's diffuse light at a point, trilinear over the eight probes around it.\n *\n * **Eight, because diffuse is the term a grid exists for.** A floor spanning four probes is the\n * case the whole row was costed against, and a hard selection steps visibly across it \u2014 which is\n * exactly where a lit surface has nothing else going on to hide the seam.\n *\n * Zero-weight corners are skipped, so a grid of one does one fetch rather than eight.\n *\n * The cell is recomputed here rather than passed in, because the two terms sit in separate\n * conditional blocks of the lit pass and threading a pair of vectors between them would mean a\n * third. Six arithmetic operations against that.\n */\nvec3 gridIrradiance(vec3 dir, vec3 worldPos) {\n vec3 base;\n vec3 frac;\n probeCell(worldPos, base, frac);\n vec3 sum = vec3(0.0);\n for (int c = 0; c < 8; c++) {\n vec3 corner = vec3(float(c & 1), float((c >> 1) & 1), float((c >> 2) & 1));\n vec3 axisWeight = mix(1.0 - frac, frac, corner);\n float weight = axisWeight.x * axisWeight.y * axisWeight.z;\n if (weight <= 0.0) continue;\n sum += probeIrradiance(dir, probeLayer(base + corner)) * weight;\n }\n return sum;\n}\n\n/**\n * The grid's reflection at a point: two probes along the axis the point is most between.\n *\n * **Two rather than eight, and the axis is chosen rather than fixed.** Sixteen fetches for a\n * reflection is not affordable on the parts this engine targets, and a single probe pops as a\n * smooth surface crosses a cell boundary. Blending along the axis with the largest betweenness\n * removes the pop where it is largest for one extra pair of fetches; the other two axes take their\n * nearest probe, where the switch happens at the point the blend would have been half and half.\n *\n * Full trilinear here is recorded as deferred rather than refused, with its reversal condition: a\n * consumer measuring the remaining seam as their constraint.\n */\nvec3 gridRadiance(vec3 dir, float lod, vec3 worldPos) {\n vec3 base;\n vec3 frac;\n probeCell(worldPos, base, frac);\n vec3 between = min(frac, 1.0 - frac);\n vec3 nearest = base + step(vec3(0.5), frac);\n vec3 low = nearest;\n vec3 high = nearest;\n float t = 0.0;\n if (between.x >= between.y && between.x >= between.z) {\n low.x = base.x;\n high.x = base.x + 1.0;\n t = frac.x;\n } else if (between.y >= between.z) {\n low.y = base.y;\n high.y = base.y + 1.0;\n t = frac.y;\n } else {\n low.z = base.z;\n high.z = base.z + 1.0;\n t = frac.z;\n }\n vec3 near = probeRadiance(dir, lod, probeLayer(low));\n if (t <= 0.0) return near;\n return mix(near, probeRadiance(dir, lod, probeLayer(high)), t);\n}\n#endif";
21
+ export declare const PROBEGRID_GLSL: string;
@@ -1,4 +1,9 @@
1
1
  /** Reading the probe array: which layers a point sits between, and what each of them holds. */
2
+ import { PROBE_VISIBILITY_CRUSH, PROBE_VISIBILITY_SHARPNESS, PROBE_VISIBILITY_VARIANCE_FLOOR, } from '../../gi/probeVolume.js';
3
+ /** A number as GLSL always reads it as a float, so an integer constant is not an `int`. */
4
+ function glslFloat(value) {
5
+ return Number.isInteger(value) ? value.toFixed(1) : String(value);
6
+ }
2
7
  /**
3
8
  * The lit pass's half of the grid, and the two things it has to get right.
4
9
  *
@@ -82,6 +87,41 @@ vec3 probeRadiance(vec3 dir, float lod, float layer) {
82
87
  return mix(fine, coarse, clamp(lod - lo, 0.0, 1.0));
83
88
  }
84
89
 
90
+ /** Layers of radiance in the array, which is where the visibility moments start. */
91
+ float probeLayerCount() {
92
+ return uProbeGridCounts.x * uProbeGridCounts.y * uProbeGridCounts.z;
93
+ }
94
+
95
+ /**
96
+ * How much of a probe a point can actually see, from one to zero.
97
+ *
98
+ * **The same arithmetic as "probeVisibilityWeight", and the constants are interpolated from it**
99
+ * rather than written again: one in front of what the probe saw along that direction, and behind it
100
+ * a Chebyshev bound on the variance of the distances the probe recorded — confident where the
101
+ * geometry is flat, uncertain where it is not, which is exactly where a hard answer would be wrong.
102
+ *
103
+ * The variance floor is not a tolerance. A probe facing a flat wall records the same distance in
104
+ * every direction of its cone, so the variance is exactly zero and the bound becomes a step: one in
105
+ * front of the wall and zero behind it, with a hard line between them that crawls every time the
106
+ * probes are rebaked.
107
+ *
108
+ * The moments live in the radiance array, offset past its layers by the grid's probe count, at
109
+ * level zero. See "uProbeVisibilityEnabled".
110
+ */
111
+ float probeVisible(vec3 fromProbe, float distanceM, float layer) {
112
+ vec2 moments = textureLod(
113
+ uEnvironment,
114
+ vec3(octInsetUv(fromProbe, uEnvironmentEdge), layer + probeLayerCount()),
115
+ 0.0
116
+ ).rg;
117
+ if (distanceM <= moments.x) return 1.0;
118
+ float variance =
119
+ max(abs(moments.x * moments.x - moments.y), ${glslFloat(PROBE_VISIBILITY_VARIANCE_FLOOR)});
120
+ float beyond = distanceM - moments.x;
121
+ float chebyshev = variance / (variance + beyond * beyond);
122
+ return pow(chebyshev, ${glslFloat(PROBE_VISIBILITY_SHARPNESS)});
123
+ }
124
+
85
125
  /**
86
126
  * The grid's diffuse light at a point, trilinear over the eight probes around it.
87
127
  *
@@ -100,14 +140,43 @@ vec3 gridIrradiance(vec3 dir, vec3 worldPos) {
100
140
  vec3 frac;
101
141
  probeCell(worldPos, base, frac);
102
142
  vec3 sum = vec3(0.0);
143
+ /*
144
+ * **The weights are renormalised rather than used as they fall.** Multiplying by visibility takes
145
+ * energy out of the blend, and a blend that quietly drops a share of its probes darkens every
146
+ * bounce — the property "visibleProbes" states and the white furnace rests on.
147
+ *
148
+ * And a point every probe is blind to still gets an answer: inside a solid, or in a sealed void
149
+ * with a probe on each side of a wall, every weight crushes to nothing and the nearest probe
150
+ * takes the lot. This is the last level of the chain and there is nothing behind it.
151
+ */
152
+ float total = 0.0;
153
+ float nearestDistance = 1.0e30;
154
+ vec3 nearestColour = vec3(0.0);
103
155
  for (int c = 0; c < 8; c++) {
104
156
  vec3 corner = vec3(float(c & 1), float((c >> 1) & 1), float((c >> 2) & 1));
105
157
  vec3 axisWeight = mix(1.0 - frac, frac, corner);
106
158
  float weight = axisWeight.x * axisWeight.y * axisWeight.z;
107
159
  if (weight <= 0.0) continue;
108
- sum += probeIrradiance(dir, probeLayer(base + corner)) * weight;
160
+ float layer = probeLayer(base + corner);
161
+ vec3 colour = probeIrradiance(dir, layer);
162
+ float kept = weight;
163
+ if (uProbeVisibilityEnabled > 0.5) {
164
+ vec3 fromProbe = worldPos - (uProbeGridOrigin + (base + corner) / uProbeGridInvSpacing);
165
+ float distanceM = length(fromProbe);
166
+ /* A point standing exactly on a probe is seen by it, and has no direction to ask about. */
167
+ float seen = distanceM > 0.0 ? probeVisible(fromProbe / distanceM, distanceM, layer) : 1.0;
168
+ kept = weight * seen;
169
+ kept = kept < ${glslFloat(PROBE_VISIBILITY_CRUSH)} ? 0.0 : kept;
170
+ if (distanceM < nearestDistance) {
171
+ nearestDistance = distanceM;
172
+ nearestColour = colour;
173
+ }
174
+ }
175
+ sum += colour * kept;
176
+ total += kept;
109
177
  }
110
- return sum;
178
+ if (uProbeVisibilityEnabled <= 0.5) return sum;
179
+ return total > 0.0 ? sum / total : nearestColour;
111
180
  }
112
181
 
113
182
  /**
@@ -2337,11 +2337,16 @@ export declare const FLAT_BINDINGS: {
2337
2337
  readonly size: 4;
2338
2338
  readonly type: "float";
2339
2339
  };
2340
- readonly uEnvironmentIrradianceLevel: {
2340
+ readonly uProbeVisibilityEnabled: {
2341
2341
  readonly offset: 320;
2342
2342
  readonly size: 4;
2343
2343
  readonly type: "float";
2344
2344
  };
2345
+ readonly uEnvironmentIrradianceLevel: {
2346
+ readonly offset: 324;
2347
+ readonly size: 4;
2348
+ readonly type: "float";
2349
+ };
2345
2350
  readonly uProbeGridOrigin: {
2346
2351
  readonly offset: 336;
2347
2352
  readonly size: 12;
@@ -2818,11 +2823,16 @@ export declare const FLAT_BINDINGS: {
2818
2823
  readonly size: 4;
2819
2824
  readonly type: "float";
2820
2825
  };
2821
- readonly uEnvironmentIrradianceLevel: {
2826
+ readonly uProbeVisibilityEnabled: {
2822
2827
  readonly offset: 320;
2823
2828
  readonly size: 4;
2824
2829
  readonly type: "float";
2825
2830
  };
2831
+ readonly uEnvironmentIrradianceLevel: {
2832
+ readonly offset: 324;
2833
+ readonly size: 4;
2834
+ readonly type: "float";
2835
+ };
2826
2836
  readonly uProbeGridOrigin: {
2827
2837
  readonly offset: 336;
2828
2838
  readonly size: 12;
@@ -3461,11 +3471,16 @@ export declare const FLAT_BINDINGS: {
3461
3471
  readonly size: 4;
3462
3472
  readonly type: "float";
3463
3473
  };
3464
- readonly uEnvironmentIrradianceLevel: {
3474
+ readonly uProbeVisibilityEnabled: {
3465
3475
  readonly offset: 352;
3466
3476
  readonly size: 4;
3467
3477
  readonly type: "float";
3468
3478
  };
3479
+ readonly uEnvironmentIrradianceLevel: {
3480
+ readonly offset: 356;
3481
+ readonly size: 4;
3482
+ readonly type: "float";
3483
+ };
3469
3484
  readonly uProbeGridOrigin: {
3470
3485
  readonly offset: 368;
3471
3486
  readonly size: 12;
@@ -3990,11 +4005,16 @@ export declare const FLAT_BINDINGS: {
3990
4005
  readonly size: 4;
3991
4006
  readonly type: "float";
3992
4007
  };
3993
- readonly uEnvironmentIrradianceLevel: {
4008
+ readonly uProbeVisibilityEnabled: {
3994
4009
  readonly offset: 352;
3995
4010
  readonly size: 4;
3996
4011
  readonly type: "float";
3997
4012
  };
4013
+ readonly uEnvironmentIrradianceLevel: {
4014
+ readonly offset: 356;
4015
+ readonly size: 4;
4016
+ readonly type: "float";
4017
+ };
3998
4018
  readonly uProbeGridOrigin: {
3999
4019
  readonly offset: 368;
4000
4020
  readonly size: 12;
@@ -6750,11 +6770,16 @@ export declare const FLAT_BINDINGS: {
6750
6770
  readonly size: 4;
6751
6771
  readonly type: "float";
6752
6772
  };
6753
- readonly uEnvironmentIrradianceLevel: {
6773
+ readonly uProbeVisibilityEnabled: {
6754
6774
  readonly offset: 324;
6755
6775
  readonly size: 4;
6756
6776
  readonly type: "float";
6757
6777
  };
6778
+ readonly uEnvironmentIrradianceLevel: {
6779
+ readonly offset: 328;
6780
+ readonly size: 4;
6781
+ readonly type: "float";
6782
+ };
6758
6783
  readonly uProbeGridOrigin: {
6759
6784
  readonly offset: 336;
6760
6785
  readonly size: 12;
@@ -7236,11 +7261,16 @@ export declare const FLAT_BINDINGS: {
7236
7261
  readonly size: 4;
7237
7262
  readonly type: "float";
7238
7263
  };
7239
- readonly uEnvironmentIrradianceLevel: {
7264
+ readonly uProbeVisibilityEnabled: {
7240
7265
  readonly offset: 324;
7241
7266
  readonly size: 4;
7242
7267
  readonly type: "float";
7243
7268
  };
7269
+ readonly uEnvironmentIrradianceLevel: {
7270
+ readonly offset: 328;
7271
+ readonly size: 4;
7272
+ readonly type: "float";
7273
+ };
7244
7274
  readonly uProbeGridOrigin: {
7245
7275
  readonly offset: 336;
7246
7276
  readonly size: 12;
@@ -7884,11 +7914,16 @@ export declare const FLAT_BINDINGS: {
7884
7914
  readonly size: 4;
7885
7915
  readonly type: "float";
7886
7916
  };
7887
- readonly uEnvironmentIrradianceLevel: {
7917
+ readonly uProbeVisibilityEnabled: {
7888
7918
  readonly offset: 356;
7889
7919
  readonly size: 4;
7890
7920
  readonly type: "float";
7891
7921
  };
7922
+ readonly uEnvironmentIrradianceLevel: {
7923
+ readonly offset: 360;
7924
+ readonly size: 4;
7925
+ readonly type: "float";
7926
+ };
7892
7927
  readonly uProbeGridOrigin: {
7893
7928
  readonly offset: 368;
7894
7929
  readonly size: 12;
@@ -8418,11 +8453,16 @@ export declare const FLAT_BINDINGS: {
8418
8453
  readonly size: 4;
8419
8454
  readonly type: "float";
8420
8455
  };
8421
- readonly uEnvironmentIrradianceLevel: {
8456
+ readonly uProbeVisibilityEnabled: {
8422
8457
  readonly offset: 356;
8423
8458
  readonly size: 4;
8424
8459
  readonly type: "float";
8425
8460
  };
8461
+ readonly uEnvironmentIrradianceLevel: {
8462
+ readonly offset: 360;
8463
+ readonly size: 4;
8464
+ readonly type: "float";
8465
+ };
8426
8466
  readonly uProbeGridOrigin: {
8427
8467
  readonly offset: 368;
8428
8468
  readonly size: 12;