@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
package/src/index.ts CHANGED
@@ -6,7 +6,7 @@ export type { LoopHooks, FrameSource, LoopOptions } from './core/loop.ts';
6
6
  export { StepBudget } from './core/stepBudget.ts';
7
7
  export type { StepBudgetOptions } from './core/stepBudget.ts';
8
8
  export { hashToUnit, mulberry32, pickBySeed, savableMulberry32 } from './core/rng.ts';
9
- export { exactAcos, exactCos, exactExp, exactSin } from './math/exact.ts';
9
+ export { exactAcos, exactCos, exactExp, exactLog, exactSin } from './math/exact.ts';
10
10
  export type { SavableRandom } from './core/rng.ts';
11
11
  export { TickTrace } from './core/tickTrace.ts';
12
12
  export type { TickTraceLike } from './core/tickTrace.ts';
@@ -120,8 +120,13 @@ export type { PickHit, PickableSource } from './render/pickable.ts';
120
120
  /* How big a piece of geometry is, which everything that culls or picks a detail level starts from. */
121
121
  export { boundsOfBox, boundsOfPositions, createBounds } from './math/bounds.ts';
122
122
  export type { Bounds } from './math/bounds.ts';
123
- export { createFrustum, frustumFromViewProjection, sphereInFrustum } from './math/frustum.ts';
124
- export type { Frustum } from './math/frustum.ts';
123
+ export {
124
+ boxInFrustum,
125
+ createFrustum,
126
+ frustumFromViewProjection,
127
+ sphereInFrustum,
128
+ } from './math/frustum.ts';
129
+ export type { Frustum, FrustumPlanes } from './math/frustum.ts';
125
130
  export { boundsVisible } from './render/visibility.ts';
126
131
  export { apparentSize, lodForBounds } from './render/lod.ts';
127
132
  /* A transform hierarchy. Additive: nothing in the renderer knows a node exists. */
@@ -158,7 +163,27 @@ export type {
158
163
  * write to the frame stays refused while a write to a pass-owned target does not is written out.
159
164
  */
160
165
  export type { PassAttachmentOptions, PassTarget } from './render/passTarget.ts';
166
+ /*
167
+ * The mip chain a pass has to build for itself on WebGPU, and the level count it needs to ask for.
168
+ *
169
+ * **Public because `gl.generateMipmap` has no WebGPU equivalent and every contributed pass that
170
+ * uploads a texture meets that the moment its texture is ever minified.** `ui2d` met it with a
171
+ * glyph atlas baked at 96 px and drawn at 11; writing the blit a second time there would have been
172
+ * a second WGSL shader to keep in step with this one, and the copy that quietly disagrees about
173
+ * the colour space is the one that would ship. `MipPipelines` is an interface rather than the
174
+ * renderer's cache so a pass can hand over a `Map` and nothing more.
175
+ */
176
+ export {
177
+ generateMipChain,
178
+ mipLevelCount,
179
+ type MipPipelines,
180
+ } from './render/backend/webgpu/surfaceTexturePass.ts';
161
181
  export { createPassAttachment } from './render/passTarget.ts';
182
+ /*
183
+ * What a pass drawing the world does with `PrepareContext.jitter`, so a reconstructed frame's
184
+ * resolve finds its geometry where the renderer's own verbs put theirs.
185
+ */
186
+ export { jitterClip } from './render/recon/jitter.ts';
162
187
  export type { FrameResource } from './render/frame/index.ts';
163
188
  /*
164
189
  * Occlusion culling, which is arithmetic rather than a GPU feature — so the class is public and a
@@ -191,7 +216,172 @@ export { createRenderer } from './render/backend/createRenderer.ts';
191
216
  * one is to write the object inline at the call — which is exactly how a choice ends up
192
217
  * duplicated across the several places an application creates a renderer.
193
218
  */
194
- export type { CreatedRenderer, CreateRendererOptions } from './render/backend/createRenderer.ts';
219
+ export type {
220
+ CreatedRenderer,
221
+ CreateRendererOptions,
222
+ RenderPipeline,
223
+ } from './render/backend/createRenderer.ts';
224
+ /*
225
+ * The second pipeline, as the two things a consumer assembles: the scene packing and the pass
226
+ * that draws it.
227
+ *
228
+ * **Exported here and reached by nobody who does not ask for it.** `pipeline: 'gpu-driven'` on
229
+ * `createRenderer` is the permission — it fails at boot where the backend cannot run this — and
230
+ * `GpuDrivenPass` is the implementation, registered the way `@driftengine/splats` registers one.
231
+ * A consumer who names neither pays nothing: `core-only` is measured with these exported and does
232
+ * not move, because nothing in the forward path reaches them.
233
+ *
234
+ * It draws vertex colour, one directional term, a hemispheric ambient and an emissive add — not
235
+ * the standard material. `DRAFT_SCENES`, never `SCENES`, until it draws the six published ones.
236
+ */
237
+ export {
238
+ GPU_DRIVEN_LISTS,
239
+ GpuDrivenPass,
240
+ MATERIAL_FLOATS,
241
+ } from './render/backend/webgpu/gpuDrivenPass.ts';
242
+ export type {
243
+ GpuDrivenList,
244
+ GpuDrivenMaterial,
245
+ GpuDrivenShadowOptions,
246
+ GpuDrivenView,
247
+ } from './render/backend/webgpu/gpuDrivenPass.ts';
248
+ /*
249
+ * **One environment, one haze, on both pipelines.** `GpuDrivenView.fog` is the medium the forward
250
+ * path binds, and a consumer drawing both in one frame fills it from `atmosphereFog` rather than
251
+ * working the numbers out again — the voxel sandbox's port is the first.
252
+ */
253
+ export { atmosphereFog, createFogTarget } from './render/fog.ts';
254
+ export type { FogOptions, FogTarget } from './render/fog.ts';
255
+ export { buildGpuDrivenScene } from './render/gpudriven/sceneUpload.ts';
256
+ export type { GpuDrivenMesh, GpuDrivenScene } from './render/gpudriven/sceneUpload.ts';
257
+ /*
258
+ * **The scene a `GpuDrivenPass` takes**, which is a streaming one since 2026-09-18 — a static
259
+ * scene is one filled once, so there is a single path rather than two. `buildGpuDrivenScene` stays
260
+ * exported because it is the packer `streamScene.test.ts` holds the streaming layout to.
261
+ */
262
+ export { StreamingScene, streamingScene } from './render/gpudriven/streamScene.ts';
263
+ export type {
264
+ DirtySpan,
265
+ GeometrySink,
266
+ StreamCapacity,
267
+ StreamHandle,
268
+ StreamUpload,
269
+ } from './render/gpudriven/streamScene.ts';
270
+ export type { ClusterSource } from './render/gpudriven/clusterUpload.ts';
271
+ export { packDecodeTables, programFromEncoded } from './render/gpudriven/decodeTables.ts';
272
+ export type {
273
+ DecodeTables,
274
+ EncodedProgramShape,
275
+ GpuDrivenLatent,
276
+ GpuDrivenNetwork,
277
+ GpuDrivenProgram,
278
+ } from './render/gpudriven/decodeTables.ts';
279
+ export type { GpuDrivenTextures } from './render/gpudriven/materialTable.ts';
280
+ /*
281
+ * **A network graph on a device**: the one neural runtime's device half. `@driftengine/texture`
282
+ * holds the references and validates a graph; this runs the validated graph, whose shapes it takes
283
+ * as given, on a device opened from whichever `GPU` the caller has — a browser's or the native
284
+ * host's Dawn. Exported because the device may not leave `render/`, so a package that runs a
285
+ * network does so through here or not at all.
286
+ */
287
+ export { openInferenceDevice } from './render/inference/device.ts';
288
+ export type { InferenceDevice } from './render/inference/device.ts';
289
+ export { createGraphRunner } from './render/inference/runner.ts';
290
+ /* The buffer-reuse rule, exported because `@driftengine/texture`'s evaluator plans by this one
291
+ rather than by a second copy of it — see `reuse.ts` for why it is on this side of the arrow. */
292
+ export { planReuse } from './render/inference/reuse.ts';
293
+ /* The tile lists a device draws a splat cloud from, beside the shader that walks them. */
294
+ export {
295
+ countSplatTiles,
296
+ fillSplatTiles,
297
+ splatPixelBox,
298
+ splatTileGrid,
299
+ splatTileOffsets,
300
+ SPLAT_BIN_FLOATS,
301
+ SPLAT_TILE,
302
+ } from './render/inference/splatTiles.ts';
303
+ export type { BufferReuse } from './render/inference/reuse.ts';
304
+ export type { GraphRunner } from './render/inference/runner.ts';
305
+ export type {
306
+ DeviceAttribute,
307
+ DeviceGraph,
308
+ DeviceGraphNode,
309
+ } from './render/inference/deviceGraph.ts';
310
+ /**
311
+ * **Indirect light, as three levels that fall back to each other and never off the end.**
312
+ *
313
+ * `ROADMAP.md` refused screen-space global illumination because its error is unbounded — a ray
314
+ * that leaves the frame has no answer, and every technique that ships one anyway invents one from
315
+ * whatever happened to be on screen. This does not reverse that refusal: the screen is an
316
+ * accelerator with a world-space distance field behind it, whose error is bounded by its own
317
+ * resolution, and a probe volume behind *that*, which is never wrong and only ever coarse.
318
+ *
319
+ * **CPU-side, and reached by nobody who does not ask.** There is no WGSL, no pass and no renderer
320
+ * option yet, so no scene renders differently for these existing — this wave's first constraint,
321
+ * measured rather than asserted: the eight published scenes are 0 of 921,600 pixels against the
322
+ * build before them, and `core-only` is byte-identical with these exported and without them.
323
+ * Exported anyway, for the reason `bake/cluster.ts` was not: a capability with no route out of its
324
+ * package is one the first consumer finds by failing a boundary test.
325
+ */
326
+ export {
327
+ GI_SOURCE_FIELD,
328
+ GI_SOURCE_PROBES,
329
+ GI_SOURCE_SCREEN,
330
+ newIndirectResult,
331
+ traceIndirect,
332
+ } from './render/gi/chain.ts';
333
+ export type { GiResources, GiSource, IndirectRay, IndirectResult } from './render/gi/chain.ts';
334
+ export {
335
+ GLOBAL_FIELD_BLEND,
336
+ composeGlobalField,
337
+ createGlobalField,
338
+ sampleGlobalField,
339
+ } from './render/gi/globalField.ts';
340
+ export type {
341
+ FieldSource,
342
+ GlobalField,
343
+ GlobalFieldCascade,
344
+ GlobalFieldInstance,
345
+ } from './render/gi/globalField.ts';
346
+ export {
347
+ GI_SCREEN_MARCH,
348
+ SCREEN_TRACE_BIAS_M,
349
+ screenRayOrigin,
350
+ traceScreen,
351
+ } from './render/gi/traceScreen.ts';
352
+ export { FIELD_MARCH, coneRadiusAt, newFieldHit, traceField } from './render/gi/traceField.ts';
353
+ export type { FieldHit, FieldMarch } from './render/gi/traceField.ts';
354
+ export {
355
+ PROBE_VISIBILITY_SHARPNESS,
356
+ bakeProbeVisibility,
357
+ createProbeVisibility,
358
+ probeUpdateSchedule,
359
+ probeVisibilityWeight,
360
+ sampleProbeVolume,
361
+ visibleProbes,
362
+ } from './render/gi/probeVolume.ts';
363
+ export type { ProbeVisibility } from './render/gi/probeVolume.ts';
364
+ export {
365
+ DENOISE_MIN_ALPHA,
366
+ filterStepFor,
367
+ newTemporalPixel,
368
+ spatialDenoise,
369
+ temporalDenoise,
370
+ } from './render/gi/denoise.ts';
371
+ export type { DenoiseFrame, SpatialOptions, TemporalPixel } from './render/gi/denoise.ts';
372
+ export { reflectDirection, reflectionCone, traceReflection } from './render/gi/reflection.ts';
373
+ /*
374
+ * The pass that draws the renderer's field on a device. WebGPU only, and it says so at
375
+ * registration rather than at the first frame: a distance field is composed by compute and WebGL2
376
+ * has none. It no longer composes one of its own — `addDistanceField` is how a scene declares
377
+ * what its indirect light may be traced against, and this marches what the renderer made of them.
378
+ */
379
+ export { GiFieldPass } from './render/backend/webgpu/giFieldPass.ts';
380
+ export type { GiFieldOptions } from './render/backend/webgpu/giFieldPass.ts';
381
+ export { DistanceFieldScene, MAX_DISTANCE_FIELDS } from './render/gi/fieldScene.ts';
382
+ export type { DistanceFieldInstance } from './render/gi/fieldScene.ts';
383
+ export { placeCascade } from './render/gi/globalField.ts';
384
+ export type { ReflectionOptions, ReflectiveSample } from './render/gi/reflection.ts';
195
385
  /*
196
386
  * The acceptance probe, exported because a consumer may want to ask the question itself — an
197
387
  * editor deciding whether to offer a backend, a shell deciding what to tell the player — and
@@ -462,6 +652,13 @@ export { DebugLines } from './render/debugLines.ts';
462
652
  * over and what a drag does, and fills line buffers the caller draws with `drawLines`.
463
653
  * Nothing here touches a context.
464
654
  */
655
+ /*
656
+ * Ray intersection, exported because a consumer building a tool needs the same arithmetic the
657
+ * gizmo does. `editor/src/viewport/gizmo.ts` reaching into `src/math/intersect.ts` by path would
658
+ * be the editor using a private hook, which `ARCHITECTURE.md` treats as a hole in the engine
659
+ * rather than as the editor's problem — so the hole is closed here.
660
+ */
661
+ export { rayClosestOnLine, rayPlane, raySphere } from './math/intersect.ts';
465
662
  export {
466
663
  GIZMO_GROUP_ACTIVE,
467
664
  GIZMO_GROUP_COLORS,
@@ -645,6 +842,30 @@ export type { ContactReport } from './dev/contactProbe.ts';
645
842
 
646
843
  export { GPU_SLOTS, GpuTimer } from './render/gpuTimer.ts';
647
844
  export type { GpuSample, GpuSlot } from './render/gpuTimer.ts';
845
+
846
+ /*
847
+ * Per-pass timings, which are a readout rather than a frame graph.
848
+ *
849
+ * **`render/frame/index.ts` says nothing under it may be reached from outside `render/` yet, and
850
+ * this module is the exception with a reason.** The rest of that directory is the graph's
851
+ * construction — declarations, lifetimes, aliasing, scheduling — whose public shape the design
852
+ * leaves to a later phase, and exporting it now would fix a shape nobody has had to live with.
853
+ * A timing readout is not that: it is seven functions over three arrays, its own header argues why
854
+ * it is not a widening of `GpuTimer`, and anything that profiles a frame needs it.
855
+ *
856
+ * The editor is what made this concrete. `AGENTS.md`'s rule is that a consumer needing a private
857
+ * import has found a hole in the engine, and the hole is fixed here rather than worked around
858
+ * there — which is the whole reason the editor was built outside `packages/`.
859
+ */
860
+ export {
861
+ createPassTimings,
862
+ passLabel,
863
+ passMs,
864
+ recordPassLabel,
865
+ recordPassSample,
866
+ resetPassTimings,
867
+ } from './render/frame/passTimings.ts';
868
+ export type { PassTimings } from './render/frame/passTimings.ts';
648
869
  export { classifyRightGesture } from './input/rightGesture.ts';
649
870
  export type { RightGesture, RightGestureOptions } from './input/rightGesture.ts';
650
871
  export { createWindState, sampleWind } from './render/wind.ts';
@@ -728,3 +949,39 @@ export type { TreeParams, TreeGeometry } from './geometry/treeBuilder.ts';
728
949
  export type { InstanceData } from './render/instancedMesh.ts';
729
950
  export type { MeshInstances } from './render/instances.ts';
730
951
  export type { WindProfile, WindState } from './render/wind.ts';
952
+
953
+ /*
954
+ * Large worlds: the cell grid that streams and freezes, and the origin that rendering rebases
955
+ * against while the simulation never does. See `world/rebase.ts` for why that asymmetry is the
956
+ * rule the whole design hangs on.
957
+ */
958
+ export {
959
+ cellBounds,
960
+ cellCoord,
961
+ cellCoordInRange,
962
+ cellCoordsOf,
963
+ cellIdFor,
964
+ cellIdFrom,
965
+ cellsInFrustum,
966
+ cellsInRadius,
967
+ createCellGrid,
968
+ } from './world/cell.ts';
969
+ export type { CellGrid } from './world/cell.ts';
970
+ export { renderOrigin, toRenderSpace, toWorldSpace } from './world/rebase.ts';
971
+ export {
972
+ cameraPositionFrom,
973
+ cellPredictor,
974
+ createCellStream,
975
+ pumpCellStream,
976
+ setCellStreamOrigin,
977
+ } from './world/cellStream.ts';
978
+ export type { CellStore, CellStream, CellStreamOptions } from './world/cellStream.ts';
979
+ export {
980
+ createFrozenCells,
981
+ freezeCell,
982
+ frozenEntities,
983
+ frozenFingerprintContribution,
984
+ isCellFrozen,
985
+ thawCell,
986
+ } from './world/freeze.ts';
987
+ export type { FreezableWorld, FrozenCell, FrozenCells } from './world/freeze.ts';
@@ -482,7 +482,12 @@ export class InputSource {
482
482
  ) {
483
483
  this.target = target;
484
484
  this.preventDefaultCodes = new Set(preventDefaultCodes);
485
- this.isCoarse = window.matchMedia('(pointer: coarse)').matches;
485
+ /* Guarded, and `ui/fullscreen.ts` guards the identical query with the identical test. This
486
+ line is in a constructor, so unguarded it did not degrade a hint — it threw, and an embedder
487
+ without `matchMedia` could not construct input at all. False is what a runtime with no
488
+ pointer media query honestly is. */
489
+ this.isCoarse =
490
+ typeof window.matchMedia === 'function' && window.matchMedia('(pointer: coarse)').matches;
486
491
  this.deadzone = options.deadzone ?? DEFAULT_DEADZONE;
487
492
  this.autoPoll = options.autoPoll ?? true;
488
493
  for (const name of ['keyboard', 'mouse', 'touch', 'gamepad'] as const) {
package/src/math/exact.ts CHANGED
@@ -18,9 +18,10 @@
18
18
  *
19
19
  * ## What is here, and what is deliberately not
20
20
  *
21
- * `exactSin`, `exactCos`, `exactExp`, `exactAcos`. Four, because four is what the engine and its
22
- * first consumer actually reach for: the terrain binding's slope angle needs `acos`, a lockstep
23
- * fixture rotating anything needs `sin` and `cos`, and exponential decay needs `exp`.
21
+ * `exactSin`, `exactCos`, `exactExp`, `exactAcos` and `exactLog`. Five, because five is what the
22
+ * engine and its first consumer actually reach for: the terrain binding's slope angle needs `acos`,
23
+ * a lockstep fixture rotating anything needs `sin` and `cos`, exponential decay needs `exp`, and a
24
+ * detector's box prior is a logit of the patch grid, which needs `log`.
24
25
  *
25
26
  * **`atan2` is absent.** It is the obvious fifth and nothing here needs one: `shape.ts` sorts by a
26
27
  * comparison key computed from two in-plane axes rather than by an angle, and `joints.ts` compares
@@ -239,6 +240,71 @@ export function exactExp(x: number): number {
239
240
  return sum * pow2(k);
240
241
  }
241
242
 
243
+ /* fdlibm's `log` polynomial in s², for log(1 + f) around f = 0 by way of s = f / (2 + f). */
244
+ const LG1 = 6.66666666666673513e-1;
245
+ const LG2 = 3.999999999940941908e-1;
246
+ const LG3 = 2.857142874366239149e-1;
247
+ const LG4 = 2.222219843214978396e-1;
248
+ const LG5 = 1.818357216161805012e-1;
249
+ const LG6 = 1.531383769920937332e-1;
250
+ const LG7 = 1.479819860511658591e-1;
251
+ const TWO54 = 1.8014398509481984e16;
252
+ const SMALLEST_NORMAL = 2.2250738585072014e-308;
253
+
254
+ /* A double's two words, for reading and setting an exponent; one view, reused. */
255
+ const words = new DataView(new ArrayBuffer(8));
256
+
257
+ /**
258
+ * `Math.log`, reproducibly: fdlibm's algorithm, which is also V8's.
259
+ *
260
+ * Take the power of two out as `k` and leave a significand in [√2/2, √2), so that `f = m - 1` is
261
+ * small either side of zero; then log(1 + f) = f - f²/2 + s·(f²/2 + R(s²)) with s = f/(2 + f), and
262
+ * `k·ln 2` added back in two parts so the large part loses nothing. The exponent is read and the
263
+ * significand rescaled through the double's own words — integer operations, not transcendentals.
264
+ */
265
+ export function exactLog(x: number): number {
266
+ if (Number.isNaN(x) || x < 0) return Number.NaN;
267
+ if (x === 0) return Number.NEGATIVE_INFINITY;
268
+ if (x === Number.POSITIVE_INFINITY) return x;
269
+
270
+ let k = 0;
271
+ let value = x;
272
+ if (value < SMALLEST_NORMAL) {
273
+ k = -54;
274
+ value *= TWO54;
275
+ }
276
+ words.setFloat64(0, value);
277
+ let hx = words.getUint32(0);
278
+ k += (hx >>> 20) - 1023;
279
+ hx &= 0x000fffff;
280
+ /* Keep the significand at or above √2/2: past √2, halve it and count one more power of two. */
281
+ const i = (hx + 0x95f64) & 0x100000;
282
+ words.setUint32(0, hx | (i ^ 0x3ff00000));
283
+ k += i >>> 20;
284
+ const f = words.getFloat64(0) - 1;
285
+
286
+ if ((0x000fffff & (2 + hx)) < 3) {
287
+ /* |f| < 2^-20: two terms of the series are the whole answer. */
288
+ if (f === 0) return k === 0 ? 0 : k * LN2_HI + k * LN2_LO;
289
+ const r = f * f * (0.5 - 0.33333333333333333 * f);
290
+ return k === 0 ? f - r : k * LN2_HI - (r - k * LN2_LO - f);
291
+ }
292
+ const s = f / (2 + f);
293
+ const z = s * s;
294
+ const w = z * z;
295
+ const t1 = w * (LG2 + w * (LG4 + w * LG6));
296
+ const t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
297
+ const r = t2 + t1;
298
+ /* Far enough from one that f²/2 is worth carrying apart from f. */
299
+ if (((hx - 0x6147a) | (0x6b851 - hx)) > 0) {
300
+ const half = 0.5 * f * f;
301
+ return k === 0
302
+ ? f - (half - s * (half + r))
303
+ : k * LN2_HI - (half - (s * (half + r) + k * LN2_LO) - f);
304
+ }
305
+ return k === 0 ? f - s * (f - r) : k * LN2_HI - (s * (f - r) - k * LN2_LO - f);
306
+ }
307
+
242
308
  /** fdlibm's `asin` rational on `z = x²`, valid where `z` is small. */
243
309
  function asinRational(z: number): number {
244
310
  const numerator = z * (P0 + z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * P5)))));
@@ -12,6 +12,12 @@ import type { ReadonlyMat4 } from 'gl-matrix';
12
12
  */
13
13
  export type Frustum = Float32Array;
14
14
 
15
+ /**
16
+ * Planes in either precision. **Double precision is for a world past 2^24 units**, where a plane's
17
+ * offset is a number a single float cannot hold to the metre; `cellsInFrustum` asks for it.
18
+ */
19
+ export type FrustumPlanes = Float32Array | Float64Array;
20
+
15
21
  /** Left, right, bottom, top, near, far — the order the extraction below produces. */
16
22
  const PLANE_COUNT = 6;
17
23
 
@@ -36,7 +42,10 @@ export function createFrustum(): Frustum {
36
42
  *
37
43
  * gl-matrix stores column-major, so `m[column * 4 + row]`.
38
44
  */
39
- export function frustumFromViewProjection(m: ReadonlyMat4, out: Frustum): Frustum {
45
+ export function frustumFromViewProjection<T extends FrustumPlanes>(
46
+ m: ReadonlyMat4 | Float64Array,
47
+ out: T,
48
+ ): T {
40
49
  const m0 = m[0] ?? 0;
41
50
  const m1 = m[1] ?? 0;
42
51
  const m2 = m[2] ?? 0;
@@ -71,7 +80,14 @@ export function frustumFromViewProjection(m: ReadonlyMat4, out: Frustum): Frustu
71
80
  return out;
72
81
  }
73
82
 
74
- function setPlane(out: Frustum, index: number, x: number, y: number, z: number, d: number): void {
83
+ function setPlane(
84
+ out: FrustumPlanes,
85
+ index: number,
86
+ x: number,
87
+ y: number,
88
+ z: number,
89
+ d: number,
90
+ ): void {
75
91
  const length = Math.sqrt(x * x + y * y + z * z);
76
92
  /* A degenerate matrix gives a zero-length normal; leaving it unscaled is better than NaN,
77
93
  and the plane then accepts everything, which is the safe direction for a cull to fail. */
@@ -96,7 +112,7 @@ function setPlane(out: Frustum, index: number, x: number, y: number, z: number,
96
112
  * a draw that was visible, which is the only asymmetry a cull may have.
97
113
  */
98
114
  export function sphereInFrustum(
99
- frustum: Frustum,
115
+ frustum: FrustumPlanes,
100
116
  x: number,
101
117
  y: number,
102
118
  z: number,
@@ -113,3 +129,36 @@ export function sphereInFrustum(
113
129
  }
114
130
  return true;
115
131
  }
132
+
133
+ /**
134
+ * Whether an axis-aligned box is anywhere inside the frustum, by the same question the sphere test
135
+ * asks: outside only when wholly beyond one plane.
136
+ *
137
+ * **The corner that decides it is chosen per plane** — the one furthest along that plane's normal.
138
+ * A fixed corner answers correctly for the planes whose normals happen to point its way and culls a
139
+ * box straddling any of the others. Conservative at the edges, as the sphere test is: a box near a
140
+ * corner of the frustum can be outside it and still kept.
141
+ */
142
+ export function boxInFrustum(
143
+ frustum: FrustumPlanes,
144
+ minX: number,
145
+ minY: number,
146
+ minZ: number,
147
+ maxX: number,
148
+ maxY: number,
149
+ maxZ: number,
150
+ ): boolean {
151
+ for (let plane = 0; plane < PLANE_COUNT; plane += 1) {
152
+ const at = plane * 4;
153
+ const nx = frustum[at] ?? 0;
154
+ const ny = frustum[at + 1] ?? 0;
155
+ const nz = frustum[at + 2] ?? 0;
156
+ const reach =
157
+ nx * (nx >= 0 ? maxX : minX) +
158
+ ny * (ny >= 0 ? maxY : minY) +
159
+ nz * (nz >= 0 ? maxZ : minZ) +
160
+ (frustum[at + 3] ?? 0);
161
+ if (reach < 0) return false;
162
+ }
163
+ return true;
164
+ }
@@ -761,7 +761,25 @@ export type RendererApi = Omit<
761
761
  updateMesh(mesh: MeshHandle, positions: Float32Array, normals?: Float32Array): void;
762
762
 
763
763
  /** Draw a handle this renderer made. Passing one from the other backend is a caller error. */
764
- drawMesh(mesh: MeshHandle, model: ReadonlyMat4, depthLayer?: number, tint?: Vec3 | null): void;
764
+ drawMesh(
765
+ mesh: MeshHandle,
766
+ model: ReadonlyMat4,
767
+ depthLayer?: number,
768
+ tint?: Vec3 | null,
769
+ /**
770
+ * Where this mesh's surface was last frame, for a reconstruction's motion target.
771
+ *
772
+ * **Only a reconstruction reads it**, and only on WebGPU: it is what turns a moving object's
773
+ * stale history from a smear into a reprojection. A draw that says nothing gets the camera's
774
+ * motion, derived from the depth, which is exactly right for anything that did not move and
775
+ * wrong in proportion to how far a mover moved. Null and omitted mean the same thing.
776
+ *
777
+ * It is the *model* matrix this mesh was drawn with last frame, not a velocity: the pass
778
+ * transforms each vertex twice and lets the perspective divide do the rest, so a rotation and a
779
+ * scale are as correct as a translation.
780
+ */
781
+ previousModel?: ReadonlyMat4 | null,
782
+ ): void;
765
783
 
766
784
  /** Release the geometry behind a handle. */
767
785
  disposeMesh(mesh: MeshHandle): void;
@@ -800,3 +818,26 @@ export type RendererApi = Omit<
800
818
 
801
819
  /** Which backend is actually drawing. Reported, never inferred. */
802
820
  export type RenderBackend = 'webgl2' | 'webgpu';
821
+
822
+ /**
823
+ * Whether this backend can be driven from buffers the GPU itself wrote.
824
+ *
825
+ * **A fact about the backend, not a method on this surface, and that is the finding rather than
826
+ * the shortcut.** Indirect execution needs a render or compute pass encoder, and both are already
827
+ * in the hands of the code that would use them: `PassContext` hands a contributed pass the
828
+ * `GPURenderPassEncoder`, and `ComputeDefinition.dispatch` hands a definition the
829
+ * `GPUComputePassEncoder` while saying in as many words that the workgroup count is the
830
+ * definition's and does not cross this surface. A `drawIndexedIndirect` here would be a second
831
+ * way to reach an encoder a caller already holds.
832
+ *
833
+ * So what is missing is not a verb. It is an answer to *may I*, which a GPU-driven pipeline has
834
+ * to ask before it builds an argument buffer nothing can consume.
835
+ *
836
+ * **WebGL2 is a refusal rather than an omission.** It has no compute stage to write an argument
837
+ * buffer and no indirect draw to read one. Emulating it means reading the buffer back to the
838
+ * processor and issuing the draws from there, which is slower than the ordinary path it would be
839
+ * pretending to replace — so this reports false and the GPU-driven pipeline is WebGPU-only.
840
+ */
841
+ export function indirectSupport(backend: 'webgl2' | 'webgpu'): boolean {
842
+ return backend === 'webgpu';
843
+ }
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * What a frame asked of a backend, against what that backend allows.
3
3
  *
4
- * **This exists because a ceiling firing was unobservable.** The WebGPU backend holds ten per-frame
5
- * ceilings — draws, material changes, overlays, water bodies, light volumes, plumes, three kinds of
6
- * effect batch and the scatter shadow round — and past any of them it skips the work and writes one
7
- * `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and draws everything.
8
- * So a scene over a ceiling renders differently on the two backends, silently, and a consumer
9
- * developing against WebGL2 has no way to see it coming.
4
+ * **This exists because a ceiling firing was unobservable.** The WebGPU backend holds fourteen
5
+ * per-frame ceilings — draws, material changes, two kinds of shadow draw, water bodies, light
6
+ * volumes, four kinds of effect batch and four kinds of overlay — and past any of them it skips the
7
+ * work and writes one `console.warn` for the lifetime of the renderer. WebGL2 holds none of them and
8
+ * draws everything. So a scene over a ceiling renders differently on the two backends, silently,
9
+ * and a consumer developing against WebGL2 had no way to see it coming — which is why WebGL2 counts
10
+ * the same fifteen lines by the same rules, and reports the number the other backend rations.
10
11
  *
11
12
  * **The cost of that was measured from outside.** A consumer spent weeks on ground that
12
13
  * vanished and reappeared as the camera moved; its own report still lists, as the decisive