@driftengine/core 3.63.0 → 4.1.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 +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,343 @@
1
+ import { GPU_DRIVEN_VERTEX_FLOATS } from '../../gpudriven/sceneUpload.ts';
2
+ import { DECODE_WGSL, decodeResourcesWgsl } from './decode.wgsl.ts';
3
+ import { ENVIRONMENT_WGSL } from './environment.wgsl.ts';
4
+ import { FOG_WGSL } from './fog.wgsl.ts';
5
+ import { FRAME_BLOCK_WGSL } from './frameBlock.wgsl.ts';
6
+ import { MATERIAL_SLOTS, MATERIAL_TABLE_WGSL } from './materialTable.wgsl.ts';
7
+ import { MESH_TRANSFORM_WGSL } from './meshTransform.wgsl.ts';
8
+ import { SHADE_LIGHTING_WGSL } from './shade.wgsl.ts';
9
+
10
+ /**
11
+ * The transparent half: one indirect draw, blended, shaded in the fragment stage.
12
+ *
13
+ * **A visibility buffer stores one surface a pixel and therefore cannot hold a blend at all.** That
14
+ * is architecture rather than an omission: the whole saving of the opaque path is that shading
15
+ * happens once per pixel, after the frame knows which triangle won, and a pane of glass has no
16
+ * winner. So the transparent set skips the visibility buffer and is drawn again here, shading where
17
+ * it stands, with the divergence that implies — exactly as every fragment on the forward path does.
18
+ *
19
+ * **What it reuses is the pipeline's front half.** `instanceCull` and the cut answer "which
20
+ * clusters, at which level of detail", and that question is the same for a pane as for a wall, so
21
+ * they run a second time over the other half of the scene rather than being written again. The
22
+ * material's blend flag is what the cut filters on; `cull.wgsl.ts` carries the filter.
23
+ *
24
+ * **It includes `SHADE_LIGHTING_WGSL` rather than restating it**, so the expression a pane of glass
25
+ * is lit by is the expression a wall is lit by, character for character. That is why the lighting
26
+ * was packaged as an includable function in the first place, and `scripts/gpu-parity.mjs` holds
27
+ * both to `gpudriven/lit.ts`.
28
+ *
29
+ * **Two targets and two blend states, both of which commute.** The accumulation sums weighted
30
+ * colour and the revealage multiplies what each layer let through, so the frame stops depending on
31
+ * which surface was submitted first. `orderIndependent.ts` is the arithmetic on the CPU and says
32
+ * what it approximates; `flatPass.ts`'s `oitTarget` is the same pair of blend states on the forward
33
+ * path. The weight is `oitWeight`, which both paths share.
34
+ *
35
+ * **Depth attached read-only.** A pane behind a wall is rejected at the wall, and nothing here
36
+ * writes depth, so two panes do not hide each other and there is something left to blend.
37
+ *
38
+ * **A transparent surface is not shadowed here**, which is the one place it is lit differently from
39
+ * an opaque one. `shadowFactor` wants a receiver plane, the shading pass derives one from
40
+ * barycentric gradients because a compute invocation has no neighbours, and a fragment stage would
41
+ * have to derive it another way — a second expression for a term whose whole point is that there is
42
+ * one. `docs/IMPROVEMENTS.md` carries the row. A pane in shadow therefore reads as a pane in
43
+ * sunlight, which is visible on a bright scene and is stated rather than hidden.
44
+ */
45
+ /**
46
+ * The weighted-transparency arithmetic, declared once for the three things that need it.
47
+ *
48
+ * **The blended raster, the resolve and the parity entry point are three readers of one rule**, and
49
+ * the first version of this file gave each of them its own copy. It was caught by the audit the
50
+ * plan asks for rather than by anything failing: perturbing the weight broke the check while the
51
+ * shader that draws the frame went on using the old one, which is the exact shape of a gate that
52
+ * watches a copy of the thing it is guarding.
53
+ *
54
+ * `render/orderIndependent.ts` is the reference all of this is written against — `oitWeight` and
55
+ * `resolveOit`, where both clamps are argued and the algebra is asserted against numbers — and
56
+ * `flat/main.ts` computes the same weight on the forward path.
57
+ */
58
+ const OIT_WGSL = /* wgsl */ `
59
+ fn oitWeight(viewDepth: f32, alpha: f32) -> f32 {
60
+ let z = max(viewDepth, 0.0) / 200.0;
61
+ let falloff = 0.03 / (1e-5 + z * z * z * z);
62
+ return alpha * clamp(falloff, 1e-2, 3e3);
63
+ }
64
+
65
+ /* Premultiplied and weighted, against a blend of "one, one": the target holds the two sums. */
66
+ fn oitAccumulate(colour: vec3<f32>, alpha: f32, weight: f32) -> vec4<f32> {
67
+ return vec4<f32>(colour * alpha * weight, alpha * weight);
68
+ }
69
+
70
+ /*
71
+ * The two targets, as a premultiplied fragment to lay over what is behind them.
72
+ *
73
+ * The weighted sum divided by the weighted alpha is the average colour the layers make, and the
74
+ * revealage says how much of the background still shows. The division is guarded because a pixel no
75
+ * fragment touched has a weighted alpha of zero — and its revealage of one discards whatever this
76
+ * produces anyway.
77
+ */
78
+ fn oitResolved(accum: vec4<f32>, reveal: f32) -> vec4<f32> {
79
+ let average = accum.xyz / max(accum.w, 1e-5);
80
+ let covered = 1.0 - reveal;
81
+ return vec4<f32>(average * covered, covered);
82
+ }
83
+ `;
84
+
85
+ export const BLEND_RASTER_WGSL = /* wgsl */ `
86
+ struct BlendVarying {
87
+ @builtin(position) position: vec4<f32>,
88
+ @location(0) world: vec3<f32>,
89
+ @location(1) normal: vec3<f32>,
90
+ @location(2) colour: vec3<f32>,
91
+ @location(3) uv: vec2<f32>,
92
+ @location(4) @interpolate(flat) material: u32,
93
+ /* The vertex's own glow, added to the material's in the fragment as the shading pass adds it. */
94
+ @location(5) emissive: f32,
95
+ }
96
+ ${MATERIAL_TABLE_WGSL}
97
+ ${FRAME_BLOCK_WGSL}
98
+ @group(0) @binding(0) var<storage, read> viewProj: array<f32, 16>;
99
+ /** The compacted list of blended clusters, from the cut's second run. */
100
+ @group(0) @binding(1) var<storage, read> blendList: array<u32>;
101
+ @group(0) @binding(2) var<storage, read> clusterMeta: array<u32>;
102
+ @group(0) @binding(3) var<storage, read> indices: array<u32>;
103
+ @group(0) @binding(4) var<storage, read> vertices: array<f32>;
104
+ @group(0) @binding(5) var<storage, read> transforms: array<f32>;
105
+ @group(0) @binding(6) var<storage, read> materialOf: array<u32>;
106
+ @group(0) @binding(7) var<uniform> materials: array<Material, ${MATERIAL_SLOTS}>;
107
+ @group(0) @binding(8) var<uniform> frame: Frame;
108
+ @group(0) @binding(9) var environmentMap: texture_2d_array<f32>;
109
+ @group(0) @binding(10) var environmentSampler: sampler;
110
+ ${decodeResourcesWgsl({ group: 0, latents: 11, clampSampler: 12, repeatSampler: 13, nodes: 14, weights: 15 })}
111
+ fn decodeLatentSize() -> f32 {
112
+ return frame.size.w;
113
+ }
114
+
115
+ ${DECODE_WGSL}
116
+ /*
117
+ * **Layer 0, which is this pipeline reading one probe of a grid**, and the same fetch
118
+ * shade.wgsl.ts makes for the same reason: what this pipeline owns is a fixed cluster set a few
119
+ * metres across, where a grid would pop as a surface crossed a cell.
120
+ */
121
+ fn environmentSample(uv: vec2<f32>, level: f32) -> vec3<f32> {
122
+ return textureSampleLevel(environmentMap, environmentSampler, uv, 0, level).rgb;
123
+ }
124
+ ${ENVIRONMENT_WGSL}
125
+ ${MESH_TRANSFORM_WGSL}
126
+ ${SHADE_LIGHTING_WGSL}
127
+ ${FOG_WGSL}
128
+ ${OIT_WGSL}
129
+
130
+ const NO_PROGRAM_HERE: u32 = ${0xffffffff}u;
131
+
132
+ /*
133
+ * The same fetch the visibility raster does, keeping the attributes instead of an identifier.
134
+ *
135
+ * **"metaAt", because "meta" is a reserved word in WGSL** — the visibility raster's own comment
136
+ * records that, and this shader indexes the same buffer the same way.
137
+ */
138
+ @vertex
139
+ fn blendVert(
140
+ @builtin(vertex_index) vertex: u32,
141
+ @builtin(instance_index) slot: u32,
142
+ ) -> BlendVarying {
143
+ var out: BlendVarying;
144
+ out.world = vec3<f32>(0.0);
145
+ out.normal = vec3<f32>(0.0, 1.0, 0.0);
146
+ out.colour = vec3<f32>(0.0);
147
+ out.uv = vec2<f32>(0.0);
148
+ out.material = 0u;
149
+ out.emissive = 0.0;
150
+ let cluster = blendList[slot];
151
+ let metaAt = cluster * 4u;
152
+ let indexOffset = clusterMeta[metaAt];
153
+ let indexCount = clusterMeta[metaAt + 1u];
154
+ let mesh = clusterMeta[metaAt + 3u];
155
+
156
+ let triangle = vertex / 3u;
157
+ /* Past this cluster's triangles: collapse to a point, which covers no pixel. */
158
+ if (triangle * 3u >= indexCount) {
159
+ out.position = vec4<f32>(0.0, 0.0, 0.0, 0.0);
160
+ return out;
161
+ }
162
+
163
+ let index = indices[indexOffset + vertex];
164
+ let at = index * ${GPU_DRIVEN_VERTEX_FLOATS}u;
165
+ let local = vec3<f32>(vertices[at], vertices[at + 1u], vertices[at + 2u]);
166
+ let world = worldOf(mesh, local);
167
+
168
+ out.world = world;
169
+ out.normal = rotatedOf(mesh, vec3<f32>(vertices[at + 3u], vertices[at + 4u], vertices[at + 5u]));
170
+ out.colour = vec3<f32>(vertices[at + 6u], vertices[at + 7u], vertices[at + 8u]);
171
+ out.uv = vec2<f32>(vertices[at + 9u], vertices[at + 10u]);
172
+ out.emissive = vertices[at + 11u];
173
+ out.material = materialOf[cluster];
174
+ out.position = vec4<f32>(
175
+ viewProj[0] * world.x + viewProj[4] * world.y + viewProj[8] * world.z + viewProj[12],
176
+ viewProj[1] * world.x + viewProj[5] * world.y + viewProj[9] * world.z + viewProj[13],
177
+ viewProj[2] * world.x + viewProj[6] * world.y + viewProj[10] * world.z + viewProj[14],
178
+ viewProj[3] * world.x + viewProj[7] * world.y + viewProj[11] * world.z + viewProj[15],
179
+ );
180
+ return out;
181
+ }
182
+
183
+ struct BlendTargets {
184
+ @location(0) accum: vec4<f32>,
185
+ @location(1) reveal: vec4<f32>,
186
+ }
187
+
188
+ @fragment
189
+ fn blendFrag(in: BlendVarying) -> BlendTargets {
190
+ var out: BlendTargets;
191
+ let entry = materials[min(in.material, ${MATERIAL_SLOTS - 1}u)];
192
+ let uv = in.uv * entry.maps.xy;
193
+ let lod = 0.0;
194
+
195
+ var baseColour = vec4<f32>(1.0);
196
+ if (entry.programs.x != NO_PROGRAM_HERE) {
197
+ baseColour = decodeProgram(entry.programs.x, uv, lod, frame.size.z);
198
+ }
199
+ /* The material's own opacity times whatever its base-colour map said about this texel. */
200
+ let alpha = clamp(entry.extra.x * baseColour.w, 0.0, 1.0);
201
+ let toEye = normalize(frame.eye.xyz - in.world);
202
+
203
+ var surface: LitSurface;
204
+ surface.albedo = in.colour * entry.tint.xyz * baseColour.xyz;
205
+ surface.normal = normalize(in.normal);
206
+ surface.toEye = toEye;
207
+ surface.roughness = entry.surface.x;
208
+ surface.specular = entry.surface.y;
209
+ surface.emissive = entry.tint.w + in.emissive;
210
+ /* Where the pane glows, as the shading pass decides it: the albedo times the emissive map. */
211
+ var emissiveMapped = vec3<f32>(1.0);
212
+ if (entry.programs.w != NO_PROGRAM_HERE) {
213
+ emissiveMapped = decodeProgram(entry.programs.w, uv, lod, frame.size.z).xyz;
214
+ }
215
+ surface.emissiveColour = surface.albedo * emissiveMapped;
216
+ /* Unshadowed, and the header says why and what it costs. */
217
+ surface.shade = 1.0;
218
+ surface.reflectivity = entry.surface.z;
219
+ surface.metalness = entry.surface.w;
220
+ surface.occlusion = 1.0;
221
+
222
+ var room: LitEnvironment;
223
+ room.lightDir = frame.lightDir.xyz;
224
+ room.lightColour = frame.lightColour.xyz;
225
+ room.sky = frame.sky.xyz;
226
+ room.ground = frame.ground.xyz;
227
+ let probeBound = frame.environment.w;
228
+ let edge = frame.environment.x;
229
+ let maxLod = frame.environment.y;
230
+ room.radiance = probeRadianceAt(reflect(-toEye, surface.normal), edge, clamp(entry.surface.x * maxLod, 0.0, maxLod), maxLod);
231
+ room.radianceAmount = probeBound;
232
+ room.irradiance = probeIrradianceAt(surface.normal, edge, frame.environment.z);
233
+ room.irradianceAmount = frame.environmentMix.x;
234
+ room.prefiltered = probeBound;
235
+ room.emission = frame.environmentMix.y;
236
+
237
+ /*
238
+ * **The haze multiplies the colour and not the alpha.** A pane at the render edge should take the
239
+ * haze's colour, not become more transparent: fogging its alpha would make distant glass vanish
240
+ * where it ought to grey out, and the two read completely differently across a large view
241
+ * distance — which is the whole reason this pipeline gained a fog.
242
+ */
243
+ let toward = distance(in.world, frame.eye.xyz);
244
+ let colour = mix(litColour(surface, room), mediumColour(), mediumFog(toward, in.world.y));
245
+
246
+ /*
247
+ * **The distance to the eye, not the clip-space depth**, because that is what oitWeight's falloff
248
+ * is written in metres against — render/orderIndependent.ts divides by 200 and flat/main.ts takes
249
+ * "distance(vWorldPos, uCameraPos)". A weight fed a 0-to-1 depth instead would put every layer of
250
+ * every scene inside the first hundredth of the falloff.
251
+ */
252
+ let weight = oitWeight(toward, alpha);
253
+ out.accum = oitAccumulate(colour, alpha, weight);
254
+ /* One channel, and it multiplies: what this layer let through. See the blend state. */
255
+ out.reveal = vec4<f32>(alpha, 0.0, 0.0, alpha);
256
+ return out;
257
+ }
258
+ `;
259
+
260
+ /**
261
+ * The two targets composited over what the opaque half drew.
262
+ *
263
+ * **`resolveOit` in `render/orderIndependent.ts`, transcribed**, and the division's guard is that
264
+ * file's: a pixel no fragment touched has a weighted alpha of zero, and its revealage of one
265
+ * discards whatever this produced anyway.
266
+ *
267
+ * **Premultiplied, where the forward path's composite is a lerp**, and the difference is what the
268
+ * alpha channel means on each side. `renderer.ts` resolves over a scene target whose alpha is not a
269
+ * coverage mask; this pipeline's colour target has one, because the blit reads it to decide whether
270
+ * the pass drew a pixel at all. Writing `average * (1 - reveal)` with `1 - reveal` in alpha and
271
+ * blending `(one, one-minus-src-alpha)` gives both at once: the colour is the same lerp, and the
272
+ * coverage becomes `1 - (1 - covered) * reveal` — so a pane over empty sky marks the pixel as
273
+ * drawn, which a lerp would not have.
274
+ */
275
+ export const BLEND_RESOLVE_WGSL = /* wgsl */ `
276
+ @group(0) @binding(0) var accumMap: texture_2d<f32>;
277
+ @group(0) @binding(1) var revealMap: texture_2d<f32>;
278
+ ${OIT_WGSL}
279
+
280
+ struct Corner {
281
+ @builtin(position) position: vec4<f32>,
282
+ }
283
+
284
+ @vertex
285
+ fn resolveVert(@builtin(vertex_index) vertex: u32) -> Corner {
286
+ /* One triangle covering the target, which needs no vertex buffer and no clip correction. */
287
+ var out: Corner;
288
+ let x = f32((vertex << 1u) & 2u) * 2.0 - 1.0;
289
+ let y = f32(vertex & 2u) * 2.0 - 1.0;
290
+ out.position = vec4<f32>(x, y, 0.0, 1.0);
291
+ return out;
292
+ }
293
+
294
+ @fragment
295
+ fn resolveFrag(in: Corner) -> @location(0) vec4<f32> {
296
+ let at = vec2<u32>(in.position.xy);
297
+ let accum = textureLoad(accumMap, at, 0);
298
+ let reveal = textureLoad(revealMap, at, 0).x;
299
+ return oitResolved(accum, reveal);
300
+ }
301
+ `;
302
+
303
+ /**
304
+ * The weight and the resolve alone, as a dispatch, so both can be checked against the reference.
305
+ *
306
+ * **What a picture cannot show is whether the weight is the forward path's.** Two panes blended by
307
+ * a weight twice as steep still look like two panes; what it changes is how much a far layer keeps,
308
+ * and nothing about the frame says so. So the arithmetic is lifted out and compared against
309
+ * `oitWeight` and `resolveOit` over generated cases.
310
+ */
311
+ export const BLEND_OIT_PARITY_WGSL = /* wgsl */ `
312
+ /** Six floats a case: depth, alpha, colour, and the background behind it. */
313
+ @group(0) @binding(0) var<storage, read> cases: array<f32>;
314
+ /** Four out: the weight, and the three resolved channels. */
315
+ @group(0) @binding(1) var<storage, read_write> results: array<f32>;
316
+ ${OIT_WGSL}
317
+ @compute @workgroup_size(64)
318
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
319
+ if (id.x * 8u + 7u >= arrayLength(&cases)) { return; }
320
+ let at = id.x * 8u;
321
+ let depth = cases[at];
322
+ let alpha = cases[at + 1u];
323
+ let colour = vec3<f32>(cases[at + 2u], cases[at + 3u], cases[at + 4u]);
324
+ let background = vec3<f32>(cases[at + 5u], cases[at + 6u], cases[at + 7u]);
325
+
326
+ let weight = oitWeight(depth, alpha);
327
+ /* One fragment folded in, which is the anchor: for a single layer this reduces to "over". */
328
+ let accum = oitAccumulate(colour, alpha, weight);
329
+ let reveal = 1.0 - alpha;
330
+ /*
331
+ * The resolve's own fragment, then the blend state applied by hand: the pipeline lays it over
332
+ * the target with "one, one-minus-src-alpha", so the background keeps the revealage.
333
+ */
334
+ let over = oitResolved(accum, reveal);
335
+ let resolved = over.xyz + background * (1.0 - over.w);
336
+
337
+ let out = id.x * 4u;
338
+ results[out] = weight;
339
+ results[out + 1u] = resolved.x;
340
+ results[out + 2u] = resolved.y;
341
+ results[out + 3u] = resolved.z;
342
+ }
343
+ `;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Three flag buffers into one list, and the block that draws it.
3
+ *
4
+ * **Hand-written WGSL for the reason `cull.wgsl.ts` gives**: there is no GLSL original, because
5
+ * WebGL2 has neither a compute stage nor an indirect draw. What keeps it honest is
6
+ * `scripts/gpu-parity.mjs`, which runs it against `gpudriven/compact.ts` over generated flags.
7
+ *
8
+ * **The atomic is the whole of it and it is on the draw block rather than on a counter beside
9
+ * it.** `instanceCount` is the number of clusters this phase draws; incrementing it *is* claiming
10
+ * a slot in the list, so a separate counter would be the same number in two places and the block
11
+ * would be written by whoever remembered. The other three words never change — the vertex count is
12
+ * a cluster's index cap and the two firsts are zero — so a caller writes them once at creation and
13
+ * clears the one word a frame.
14
+ *
15
+ * **Which phase is a setting rather than two shaders.** The two differ only in which side of the
16
+ * history they take, and a second entry point would be a second place for the cut and the cull to
17
+ * be applied — which is the half that must be identical in both. See `compact.ts` for the
18
+ * invariant this is obeying: the history decides which phase a cluster is judged in and never
19
+ * whether it is judged.
20
+ */
21
+
22
+ /**
23
+ * One invocation a cluster.
24
+ *
25
+ * `settings` is the phase — 0 for the half the history holds, 1 for the rest — and the cluster
26
+ * count. `drawn` is next frame's history and **only phase two writes it**, for every cluster it
27
+ * keeps whichever half judged it, because only phase two's cull has seen this frame's pyramid; see
28
+ * `compactPhase` in `compact.ts`. A caller clears it once a frame.
29
+ */
30
+ export const COMPACT_CLUSTERS_WGSL = `
31
+ /** phase, clusterCount. */
32
+ @group(0) @binding(0) var<storage, read> settings: array<u32, 2>;
33
+ @group(0) @binding(1) var<storage, read> selected: array<u32>;
34
+ @group(0) @binding(2) var<storage, read> keep: array<u32>;
35
+ @group(0) @binding(3) var<storage, read> history: array<u32>;
36
+ @group(0) @binding(4) var<storage, read_write> list: array<u32>;
37
+ @group(0) @binding(5) var<storage, read_write> drawn: array<u32>;
38
+ /** A four-word non-indexed draw block. Only word one is touched here; see the header. */
39
+ @group(0) @binding(6) var<storage, read_write> args: array<atomic<u32>>;
40
+
41
+ @compute @workgroup_size(64)
42
+ fn main(@builtin(global_invocation_id) id: vec3<u32>) {
43
+ if (id.x >= settings[1]) { return; }
44
+
45
+ let seen = history[id.x] != 0u;
46
+ let phaseOne = settings[0] == 0u;
47
+ let visible = selected[id.x] != 0u && keep[id.x] != 0u;
48
+ /* Next frame's history is phase two's answer, for the clusters phase one drew as well. */
49
+ if (!phaseOne && visible) { drawn[id.x] = 1u; }
50
+
51
+ /* The history decides which half judges this cluster, never whether one does. */
52
+ if (seen != phaseOne || !visible) { return; }
53
+
54
+ /* Claiming the slot and counting the instance are one operation, which is why the atomic is on
55
+ the draw block. The order slots are handed out in is the scheduler's and is not an answer. */
56
+ let slot = atomicAdd(&args[1], 1u);
57
+ list[slot] = id.x;
58
+ }
59
+ `;