@driftengine/core 3.63.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 +111 -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 +69 -4
  9. package/dist/index.js +112 -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 +19 -9
  42. package/dist/render/backend/webgpu/surfaceTexturePass.js +58 -32
  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 +246 -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 +63 -36
  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
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Streaming world cells by the prediction that already streams texture tiles.
3
+ *
4
+ * **Almost no new mechanism, and that is the point.** Wave 3B built the speculative advance, the
5
+ * queue and the budget generically *for this* — its own header says so: "Wave 4B streams world
6
+ * cells by exactly this mechanism", and writing a second speculative advance here would be a
7
+ * second place for "put the simulation back exactly" to be got wrong, in a subsystem where being
8
+ * wrong means the world runs at double speed only while streaming is on. What is new here is
9
+ * `needs` — which cells a predicted view enters — and the load and the unload.
10
+ *
11
+ * **The predictor is satisfied structurally rather than imported.** `@driftengine/texture` has no
12
+ * dependencies and core must not gain it as one: `scripts/size-gate.test.mjs` asserts that
13
+ * importing core alone pulls in no optional package, and that assertion is worth more than an
14
+ * import. The shape here *is* `Predictor<number>`, and `cellStream.test.ts` proves it by running
15
+ * the real `runPrediction` over it through a dev dependency.
16
+ *
17
+ * **A cell is dropped after a hysteresis and never immediately.** A camera that turns round should
18
+ * not pay to reload what it just left, and dropping on the frame a cell leaves the radius makes
19
+ * walking back and forth across a boundary reload it every few frames — the most visible failure a
20
+ * streamer has.
21
+ */
22
+ import { mat4 } from 'gl-matrix';
23
+ import { cellCoordsOf, cellsInFrustum, cellsInRadius, createCellGrid } from './cell.ts';
24
+ import type { CellGrid } from './cell.ts';
25
+
26
+ /** What a stream needs of whatever holds a cell's contents. */
27
+ export interface CellStore {
28
+ loaded(id: number): boolean;
29
+ /** Begin loading. Lower `priority` is sooner, matching the queue's convention. */
30
+ load(id: number, priority: number): void;
31
+ unload(id: number): void;
32
+ }
33
+
34
+ export interface CellStreamOptions {
35
+ readonly store: CellStore;
36
+ /** Cell edge length, world units. */
37
+ readonly size: number;
38
+ /** How far around a view cells are wanted. */
39
+ readonly radius: number;
40
+ /** How many pumps a cell may go unwanted before it is dropped. */
41
+ readonly hysteresis: number;
42
+ /** The render origin the predicted views are relative to. Absent means the world origin. */
43
+ readonly origin?: ArrayLike<number>;
44
+ /**
45
+ * The projection the predicted views are drawn through. With it, a stream also wants the cells
46
+ * those views look into, out to its far plane; without it, only the cells within `radius`.
47
+ */
48
+ readonly projection?: ArrayLike<number>;
49
+ /** The most cells one view's query may walk. See `CellGrid`. */
50
+ readonly maxCells?: number;
51
+ }
52
+
53
+ export interface CellStream {
54
+ readonly store: CellStore;
55
+ readonly size: number;
56
+ readonly radius: number;
57
+ readonly hysteresis: number;
58
+ /**
59
+ * Where the predicted views' origin is, in absolute world coordinates.
60
+ *
61
+ * **A view matrix is `Float32Array`, and that is why this exists.** `runPrediction` writes views
62
+ * into single precision — which is right, because a view matrix is what a renderer takes — and
63
+ * single precision stops resolving whole metres past 2²⁴. A world larger than that cannot put an
64
+ * absolute position through one: at 2²⁵ the spacing is four metres, so the camera position
65
+ * recovered from the matrix is wrong by up to two. Streaming survives it, because
66
+ * `cellsInRadius` is conservative and four metres against a five-hundred-metre cell only ever
67
+ * adds a cell — but it is wrong, and it is wrong in exactly the place this mechanism exists for.
68
+ *
69
+ * So the views are render-space, relative to this, and the stream adds it back. Zero by default,
70
+ * which is what every consumer that fits inside single precision already had.
71
+ */
72
+ readonly origin: Float64Array;
73
+ /** Cell identifier to the frame it was last wanted. What the hysteresis counts against. */
74
+ readonly lastWanted: Map<number, number>;
75
+ /** Pumps so far. Monotonic, and the only clock this has. */
76
+ frame: number;
77
+ readonly grid: CellGrid;
78
+ /**
79
+ * The caller's own array, read on every predicted frame — so a lens that zooms or pulls its far
80
+ * plane in is followed without telling the stream.
81
+ */
82
+ readonly projection: ArrayLike<number> | null;
83
+ }
84
+
85
+ export function createCellStream(options: CellStreamOptions): CellStream {
86
+ return {
87
+ store: options.store,
88
+ size: options.size,
89
+ radius: options.radius,
90
+ hysteresis: options.hysteresis,
91
+ origin:
92
+ options.origin === undefined
93
+ ? new Float64Array(3)
94
+ : Float64Array.from(options.origin, Number),
95
+ lastWanted: new Map<number, number>(),
96
+ frame: 0,
97
+ grid: createCellGrid(options.size, options.maxCells),
98
+ projection: options.projection ?? null,
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Move the origin the predicted views are relative to.
104
+ *
105
+ * Called with whatever `renderOrigin` answered for this frame, so the two cannot drift apart. It is
106
+ * a write rather than a parameter to `needs` because the predictor's shape is `Predictor<number>`
107
+ * and that interface is Wave 3B's, shared with texture tiles, which have no origin.
108
+ */
109
+ export function setCellStreamOrigin(stream: CellStream, x: number, y: number, z: number): void {
110
+ stream.origin[0] = x;
111
+ stream.origin[1] = y;
112
+ stream.origin[2] = z;
113
+ }
114
+
115
+ /**
116
+ * Where the camera is, out of a view matrix, into `out`.
117
+ *
118
+ * **A view matrix is `R · T(−p)`, so its translation column is in *view* space** and negating it is
119
+ * right only while the camera is unrotated. The camera's world position is `−Rᵀ · t`, and the
120
+ * transpose is the inverse because a view rotation is orthonormal. Getting this wrong is invisible
121
+ * in any test whose camera is not turned, and wrong by the whole camera offset in every other.
122
+ *
123
+ * Column-major, as `gl-matrix` writes one: `m[0..2]` is the first column.
124
+ */
125
+ export function cameraPositionFrom(view: ArrayLike<number>, out: Float64Array): void {
126
+ const tx = view[12] as number;
127
+ const ty = view[13] as number;
128
+ const tz = view[14] as number;
129
+ /* Rᵀ · t, which is a dot with each *column* of R — and a column of R is a row of Rᵀ. */
130
+ out[0] = -((view[0] as number) * tx + (view[1] as number) * ty + (view[2] as number) * tz);
131
+ out[1] = -((view[4] as number) * tx + (view[5] as number) * ty + (view[6] as number) * tz);
132
+ out[2] = -((view[8] as number) * tx + (view[9] as number) * ty + (view[10] as number) * tz);
133
+ }
134
+
135
+ /* Reused across calls: this runs per predicted frame and these are its only allocations. */
136
+ const POSITION = new Float64Array(3);
137
+ const WANTED: number[] = [];
138
+ const AHEAD: number[] = [];
139
+ const AROUND = new Set<number>();
140
+ const VIEW = new Float64Array(16);
141
+ const LENS = new Float64Array(16);
142
+ const VIEW_PROJECTION = new Float64Array(16);
143
+ const SHIFT = new Float64Array(3);
144
+ const EYE = new Float64Array(3);
145
+ const CELL = new Int32Array(3);
146
+ let cellEdge = 1;
147
+
148
+ /** How far a cell's centre is from `EYE`, squared. */
149
+ function reachOf(id: number): number {
150
+ cellCoordsOf(id, CELL);
151
+ const x = ((CELL[0] as number) + 0.5) * cellEdge - (EYE[0] as number);
152
+ const y = ((CELL[1] as number) + 0.5) * cellEdge - (EYE[1] as number);
153
+ const z = ((CELL[2] as number) + 0.5) * cellEdge - (EYE[2] as number);
154
+ return x * x + y * y + z * z;
155
+ }
156
+
157
+ /**
158
+ * Nearest first. Two cells as near keep the order the query listed them in, which is identifier
159
+ * order, because a sort in this language is stable — so the order is the view's alone.
160
+ */
161
+ function nearerFirst(a: number, b: number): number {
162
+ return reachOf(a) - reachOf(b);
163
+ }
164
+
165
+ /**
166
+ * The cells a view looks into that the radius did not already name, appended to `WANTED`, nearest
167
+ * first — so that a budget smaller than both keeps the ground round the camera and then the view's
168
+ * nearest cells.
169
+ */
170
+ function appendView(stream: CellStream, projection: ArrayLike<number>, view: Float32Array): void {
171
+ VIEW.set(view);
172
+ LENS.set(projection);
173
+ mat4.multiply(VIEW_PROJECTION, LENS, VIEW);
174
+ /* The views are render-space; the cells are absolute. Shift in double precision. */
175
+ SHIFT[0] = -(stream.origin[0] as number);
176
+ SHIFT[1] = -(stream.origin[1] as number);
177
+ SHIFT[2] = -(stream.origin[2] as number);
178
+ mat4.translate(VIEW_PROJECTION, VIEW_PROJECTION, SHIFT);
179
+ cellsInFrustum(stream.grid, VIEW_PROJECTION, AHEAD);
180
+
181
+ AROUND.clear();
182
+ for (const id of WANTED) AROUND.add(id);
183
+ let kept = 0;
184
+ for (const id of AHEAD) {
185
+ if (!AROUND.has(id)) {
186
+ AHEAD[kept] = id;
187
+ kept += 1;
188
+ }
189
+ }
190
+ AHEAD.length = kept;
191
+ cellEdge = stream.size;
192
+ AHEAD.sort(nearerFirst);
193
+ for (const id of AHEAD) WANTED.push(id);
194
+ }
195
+
196
+ /**
197
+ * The stream as a `Predictor<number>` over cell identifiers.
198
+ *
199
+ * Structurally typed on purpose — see the header. A caller passes the result straight to
200
+ * `runPrediction` from `@driftengine/texture`.
201
+ */
202
+ export function cellPredictor(stream: CellStream): {
203
+ needs(view: Float32Array, out: number[], budget: number): number;
204
+ resident(id: number): boolean;
205
+ request(id: number, priority: number): void;
206
+ } {
207
+ return {
208
+ needs(view: Float32Array, out: number[], budget: number): number {
209
+ cameraPositionFrom(view, POSITION);
210
+ /* Back to absolute, in double precision, before anything is quantised into a cell. */
211
+ EYE[0] = (POSITION[0] as number) + (stream.origin[0] as number);
212
+ EYE[1] = (POSITION[1] as number) + (stream.origin[1] as number);
213
+ EYE[2] = (POSITION[2] as number) + (stream.origin[2] as number);
214
+ cellsInRadius(
215
+ EYE[0] as number,
216
+ EYE[1] as number,
217
+ EYE[2] as number,
218
+ stream.radius,
219
+ stream.size,
220
+ WANTED,
221
+ );
222
+ if (stream.projection !== null) appendView(stream, stream.projection, view);
223
+ /*
224
+ * Wanting is recorded for every cell a predicted view enters, not only for the ones that fit
225
+ * inside the budget. Otherwise a budget-limited frame would let a cell the camera is heading
226
+ * straight for start its unload countdown.
227
+ */
228
+ const take = Math.min(budget, WANTED.length);
229
+ out.length = 0;
230
+ for (let at = 0; at < WANTED.length; at += 1) {
231
+ const id = WANTED[at] as number;
232
+ stream.lastWanted.set(id, stream.frame);
233
+ if (at < take) out.push(id);
234
+ }
235
+ return out.length;
236
+ },
237
+
238
+ resident(id: number): boolean {
239
+ return stream.store.loaded(id);
240
+ },
241
+
242
+ request(id: number, priority: number): void {
243
+ stream.store.load(id, priority);
244
+ },
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Mark what is in range *now*, then drop what has gone unwanted long enough. Returns how many went.
250
+ *
251
+ * **The pump marks as well as drops, and the first draft only dropped.** Prediction marks what is
252
+ * coming; without the pump marking what is here, a camera standing still wants nothing — its
253
+ * predicted path never leaves the cell it is in, the horizon moves past every cell it already
254
+ * occupies, and the streamer unloads the ground somebody is standing on. That is not a case to
255
+ * guard against separately: it is the same question as "what does this camera want", asked about
256
+ * the present instead of the future.
257
+ *
258
+ * So there is no special case for the camera's own cell. `cellsInRadius` includes it at any
259
+ * radius, including zero, which means the guarantee follows from the marking rather than from a
260
+ * check somebody could delete without a test failing.
261
+ */
262
+ export function pumpCellStream(stream: CellStream, x: number, y: number, z: number): number {
263
+ stream.frame += 1;
264
+
265
+ cellsInRadius(x, y, z, stream.radius, stream.size, WANTED);
266
+ for (const id of WANTED) stream.lastWanted.set(id, stream.frame);
267
+
268
+ let dropped = 0;
269
+ for (const [id, wanted] of stream.lastWanted) {
270
+ if (stream.frame - wanted <= stream.hysteresis) continue;
271
+ if (stream.store.loaded(id)) {
272
+ stream.store.unload(id);
273
+ dropped += 1;
274
+ }
275
+ stream.lastWanted.delete(id);
276
+ }
277
+ return dropped;
278
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * What an unloaded region does, decided rather than discovered.
3
+ *
4
+ * **An unloaded region is frozen: it is exactly reproducible and it does not simulate.** An agent
5
+ * in an unloaded cell does not walk anywhere, does not age, does not finish what it was doing. That
6
+ * is a decision with consequences a consumer has to know about, which is why it is written into
7
+ * `docs/CAPABILITIES.md` as well as here — a consumer discovering it from behaviour is the failure
8
+ * this file exists to prevent.
9
+ *
10
+ * **Freezing is a simulation decision and unloading is a memory one, and that separation is the
11
+ * whole design.** A frozen cell does not simulate whether or not its contents are resident, and
12
+ * only a frozen cell may be unloaded. So streaming cannot change what the simulation computes; it
13
+ * can only change where the bytes live. The alternative — unloading causes freezing — makes the
14
+ * simulation depend on how much memory a machine had, which is a divergence that appears on one
15
+ * player's computer and nowhere else.
16
+ *
17
+ * **A frozen cell still contributes to the fingerprint.** Dropping its contribution would make two
18
+ * runs agree only at the end, once everything had thawed, and agreeing only at the end means they
19
+ * disagreed for a while — in a rollback netcode, for a while during which those numbers were
20
+ * already sent.
21
+ */
22
+
23
+ /**
24
+ * What freezing needs of a world.
25
+ *
26
+ * Taken as a parameter rather than imported, on `AGENTS.md`'s rule: core has no entity store and a
27
+ * consumer may be holding one of several. Six methods, all of which any store can answer.
28
+ */
29
+ export interface FreezableWorld {
30
+ /** Every entity whose home is this cell, live or not. */
31
+ entitiesIn(cell: number): readonly number[];
32
+ /** Write an entity's whole state into `out` and return how many values were written. */
33
+ readState(entity: number, out: Float64Array): number;
34
+ /** Put a state back, exactly. */
35
+ writeState(entity: number, values: Float64Array, count: number): void;
36
+ simulating(entity: number): boolean;
37
+ setSimulating(entity: number, on: boolean): void;
38
+ }
39
+
40
+ /**
41
+ * One cell's frozen contents. Entities in ascending order, so the packing is deterministic.
42
+ *
43
+ * Exported because whoever unloads a cell has to write this somewhere and read it back.
44
+ */
45
+ export interface FrozenCell {
46
+ readonly entities: number[];
47
+ /** Each entity's values, one after another. */
48
+ readonly values: Float64Array;
49
+ /** How many values each entity contributed, parallel to `entities`. */
50
+ readonly counts: Int32Array;
51
+ /** Computed once when the cell froze. Frozen state does not change, so neither does this. */
52
+ readonly digest: number;
53
+ }
54
+
55
+ export interface FrozenCells {
56
+ readonly cells: Map<number, FrozenCell>;
57
+ }
58
+
59
+ export function createFrozenCells(): FrozenCells {
60
+ return { cells: new Map<number, FrozenCell>() };
61
+ }
62
+
63
+ export function isCellFrozen(frozen: FrozenCells, cell: number): boolean {
64
+ return frozen.cells.has(cell);
65
+ }
66
+
67
+ /** The entities a cell froze, ascending. Empty for a cell that is not frozen. */
68
+ export function frozenEntities(frozen: FrozenCells, cell: number): readonly number[] {
69
+ return frozen.cells.get(cell)?.entities ?? [];
70
+ }
71
+
72
+ const OFFSET_BASIS = 0x811c9dc5;
73
+ const PRIME = 0x01000193;
74
+ const SCRATCH = new Float64Array(64);
75
+ const BYTES = new DataView(new ArrayBuffer(8));
76
+
77
+ /**
78
+ * FNV-1a over the eight bytes of every value, which is the construction `Fingerprint` uses.
79
+ *
80
+ * **Over the bytes and not over the numbers**, for the reason that file gives: two doubles a
81
+ * hundredth apart may print the same and are a divergence, and the bytes are what tells them
82
+ * apart. `-0` and `+0` therefore hash differently, and that is correct — two peers holding
83
+ * different zeroes have genuinely diverged.
84
+ */
85
+ function digestOf(entities: readonly number[], values: Float64Array, used: number): number {
86
+ let h = OFFSET_BASIS;
87
+ const eat = (value: number): void => {
88
+ BYTES.setFloat64(0, value);
89
+ for (let at = 0; at < 8; at += 1) {
90
+ h = Math.imul(h ^ BYTES.getUint8(at), PRIME) >>> 0;
91
+ }
92
+ };
93
+ for (const entity of entities) eat(entity);
94
+ for (let at = 0; at < used; at += 1) eat(values[at] as number);
95
+ return h >>> 0;
96
+ }
97
+
98
+ /**
99
+ * Stop a cell simulating and capture exactly what it held. `false` if it was already frozen.
100
+ *
101
+ * **Refuses rather than throws**, because the caller is a streamer inside a frame and the honest
102
+ * answer to "freeze this again" is that there is nothing to do.
103
+ */
104
+ export function freezeCell(world: FreezableWorld, frozen: FrozenCells, cell: number): boolean {
105
+ if (frozen.cells.has(cell)) return false;
106
+
107
+ const entities = [...world.entitiesIn(cell)].sort((a, b) => a - b);
108
+ const counts = new Int32Array(entities.length);
109
+ let used = 0;
110
+ for (let at = 0; at < entities.length; at += 1) {
111
+ const entity = entities[at] as number;
112
+ const count = world.readState(entity, SCRATCH.subarray(used));
113
+ counts[at] = count;
114
+ used += count;
115
+ }
116
+
117
+ const values = new Float64Array(used);
118
+ values.set(SCRATCH.subarray(0, used));
119
+ for (const entity of entities) world.setSimulating(entity, false);
120
+
121
+ frozen.cells.set(cell, { entities, values, counts, digest: digestOf(entities, values, used) });
122
+ return true;
123
+ }
124
+
125
+ /**
126
+ * Put a cell back exactly as it was frozen and let it simulate again. `false` if it was not frozen.
127
+ *
128
+ * **Exactly as it was frozen, and never where it would have got to.** An extrapolated thaw is how
129
+ * an unloaded region silently diverges from a loaded one: nothing throws, the numbers are
130
+ * plausible, and the fingerprints stop matching at a frame nobody can point at.
131
+ */
132
+ export function thawCell(world: FreezableWorld, frozen: FrozenCells, cell: number): boolean {
133
+ const held = frozen.cells.get(cell);
134
+ if (held === undefined) return false;
135
+
136
+ let at = 0;
137
+ for (let index = 0; index < held.entities.length; index += 1) {
138
+ const entity = held.entities[index] as number;
139
+ const count = held.counts[index] as number;
140
+ world.writeState(entity, held.values.subarray(at, at + count), count);
141
+ world.setSimulating(entity, true);
142
+ at += count;
143
+ }
144
+ frozen.cells.delete(cell);
145
+ return true;
146
+ }
147
+
148
+ /**
149
+ * What a frozen cell contributes to the world's fingerprint. Zero for a cell nothing froze.
150
+ *
151
+ * **Constant for as long as the cell is frozen**, which is what makes a streamed run and an
152
+ * unstreamed one agree at every frame rather than only once everything has thawed. A consumer
153
+ * feeds this into whatever fingerprint it already keeps, alongside its live entities.
154
+ */
155
+ export function frozenFingerprintContribution(frozen: FrozenCells, cell: number): number {
156
+ return frozen.cells.get(cell)?.digest ?? 0;
157
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Where rendering puts its origin, and the rule that the simulation never moves.
3
+ *
4
+ * **Rebasing is a rendering concern. The simulation never rebases.** This is the rule the whole
5
+ * large-world design hangs on. A rebase that touched simulation state would change floating-point
6
+ * results — and therefore the replay fingerprint — for no reason a player could see, and the
7
+ * divergence would appear only in sessions that happened to cross an origin boundary. That is a
8
+ * defect nobody reproduces on demand and nobody attributes correctly.
9
+ *
10
+ * So: simulation coordinates stay absolute, in double precision, where the fixed-point kernel's
11
+ * range of roughly ±2³⁷ is more world than anybody has. Render coordinates are single precision
12
+ * relative to an origin that follows the camera.
13
+ *
14
+ * **The origin moves in whole cells and never continuously.** A continuously-moving origin
15
+ * re-quantises every vertex every frame, which is visible as the whole world shimmering — the
16
+ * precision problem it was meant to solve, wearing a different hat.
17
+ */
18
+
19
+ /** The render origin for a camera at this position: its cell's minimum corner. */
20
+ export function renderOrigin(
21
+ cameraX: number,
22
+ cameraY: number,
23
+ cameraZ: number,
24
+ cellSize: number,
25
+ out: Float64Array,
26
+ ): void {
27
+ out[0] = Math.floor(cameraX / cellSize) * cellSize;
28
+ out[1] = Math.floor(cameraY / cellSize) * cellSize;
29
+ out[2] = Math.floor(cameraZ / cellSize) * cellSize;
30
+ }
31
+
32
+ /**
33
+ * A world position in render space, as single precision.
34
+ *
35
+ * The subtraction happens in double precision and only the result narrows, which is the whole
36
+ * point: subtracting two large doubles and then narrowing keeps the precision, where narrowing
37
+ * first and subtracting loses it before the subtraction can help.
38
+ */
39
+ export function toRenderSpace(
40
+ worldX: number,
41
+ worldY: number,
42
+ worldZ: number,
43
+ origin: Float64Array,
44
+ out: Float32Array,
45
+ ): void {
46
+ out[0] = worldX - (origin[0] as number);
47
+ out[1] = worldY - (origin[1] as number);
48
+ out[2] = worldZ - (origin[2] as number);
49
+ }
50
+
51
+ /** Back to absolute, in double precision. Exact for anything `toRenderSpace` produced. */
52
+ export function toWorldSpace(render: Float32Array, origin: Float64Array, out: Float64Array): void {
53
+ out[0] = (render[0] as number) + (origin[0] as number);
54
+ out[1] = (render[1] as number) + (origin[1] as number);
55
+ out[2] = (render[2] as number) + (origin[2] as number);
56
+ }