@driftengine/core 3.61.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 (955) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/README.md +9 -0
  4. package/dist/behavior/behaviorTree.d.ts +140 -0
  5. package/dist/behavior/behaviorTree.js +289 -0
  6. package/dist/build/shaderComments.d.ts +64 -0
  7. package/dist/build/shaderComments.js +0 -0
  8. package/dist/cinematic/player.d.ts +80 -0
  9. package/dist/cinematic/player.js +184 -0
  10. package/dist/cinematic/script.d.ts +63 -0
  11. package/dist/cinematic/script.js +141 -0
  12. package/dist/core/bootGate.d.ts +37 -0
  13. package/dist/core/bootGate.js +47 -0
  14. package/dist/core/loadTracker.d.ts +78 -0
  15. package/dist/core/loadTracker.js +106 -0
  16. package/dist/core/loop.d.ts +118 -0
  17. package/dist/core/loop.js +84 -0
  18. package/dist/core/messageQueue.d.ts +61 -0
  19. package/dist/core/messageQueue.js +104 -0
  20. package/dist/core/onceSet.d.ts +27 -0
  21. package/dist/core/onceSet.js +62 -0
  22. package/dist/core/preferences.d.ts +47 -0
  23. package/dist/core/preferences.js +140 -0
  24. package/dist/core/remoteSave.d.ts +154 -0
  25. package/dist/core/remoteSave.js +249 -0
  26. package/dist/core/rng.d.ts +64 -0
  27. package/dist/core/rng.js +72 -0
  28. package/dist/core/stepBudget.d.ts +91 -0
  29. package/dist/core/stepBudget.js +105 -0
  30. package/dist/core/storage.d.ts +52 -0
  31. package/dist/core/storage.js +85 -0
  32. package/dist/core/tickTrace.d.ts +72 -0
  33. package/dist/core/tickTrace.js +102 -0
  34. package/dist/core/timeCurve.d.ts +83 -0
  35. package/dist/core/timeCurve.js +107 -0
  36. package/dist/core/withDefaults.d.ts +21 -0
  37. package/dist/core/withDefaults.js +29 -0
  38. package/dist/dev/contactProbe.d.ts +41 -0
  39. package/dist/dev/contactProbe.js +58 -0
  40. package/dist/dev/fpsMeter.d.ts +45 -0
  41. package/dist/dev/fpsMeter.js +86 -0
  42. package/dist/environment/celestialClock.d.ts +141 -0
  43. package/dist/environment/celestialClock.js +262 -0
  44. package/dist/geometry/decal.d.ts +61 -0
  45. package/dist/geometry/decal.js +178 -0
  46. package/dist/geometry/filmPatch.d.ts +35 -0
  47. package/dist/geometry/filmPatch.js +112 -0
  48. package/dist/geometry/growable.d.ts +70 -0
  49. package/dist/geometry/growable.js +167 -0
  50. package/dist/geometry/lightVolume.d.ts +76 -0
  51. package/dist/geometry/lightVolume.js +65 -0
  52. package/dist/geometry/meshBuilder.d.ts +426 -0
  53. package/dist/geometry/meshBuilder.js +1184 -0
  54. package/dist/geometry/pixelFont.d.ts +59 -0
  55. package/dist/geometry/pixelFont.js +179 -0
  56. package/dist/geometry/ribbon.d.ts +101 -0
  57. package/dist/geometry/ribbon.js +546 -0
  58. package/dist/geometry/shellFill.d.ts +101 -0
  59. package/dist/geometry/shellFill.js +203 -0
  60. package/dist/geometry/spline.d.ts +162 -0
  61. package/dist/geometry/spline.js +527 -0
  62. package/dist/geometry/tangents.d.ts +30 -0
  63. package/dist/geometry/tangents.js +142 -0
  64. package/dist/geometry/textMesh.d.ts +51 -0
  65. package/dist/geometry/textMesh.js +57 -0
  66. package/dist/geometry/treeBuilder.d.ts +37 -0
  67. package/dist/geometry/treeBuilder.js +56 -0
  68. package/dist/host/display.d.ts +135 -0
  69. package/dist/host/display.js +114 -0
  70. package/dist/host/files.d.ts +25 -0
  71. package/dist/host/files.js +44 -0
  72. package/dist/host/lifecycle.d.ts +45 -0
  73. package/dist/host/lifecycle.js +28 -0
  74. package/dist/host/platformServices.d.ts +23 -0
  75. package/dist/host/platformServices.js +1 -0
  76. package/dist/host/screen.d.ts +49 -0
  77. package/dist/host/screen.js +90 -0
  78. package/dist/index.d.ts +289 -0
  79. package/dist/index.js +320 -0
  80. package/dist/input/actionMap.d.ts +181 -0
  81. package/dist/input/actionMap.js +314 -0
  82. package/dist/input/activeDevice.d.ts +55 -0
  83. package/dist/input/activeDevice.js +83 -0
  84. package/dist/input/gamepadIdentity.d.ts +43 -0
  85. package/dist/input/gamepadIdentity.js +108 -0
  86. package/dist/input/gamepadMapping.d.ts +56 -0
  87. package/dist/input/gamepadMapping.js +91 -0
  88. package/dist/input/input.d.ts +281 -0
  89. package/dist/input/input.js +703 -0
  90. package/dist/input/inputHarness.d.ts +42 -0
  91. package/dist/input/inputHarness.js +193 -0
  92. package/dist/input/rightGesture.d.ts +57 -0
  93. package/dist/input/rightGesture.js +49 -0
  94. package/dist/input/rumble.d.ts +71 -0
  95. package/dist/input/rumble.js +119 -0
  96. package/dist/input/touchControls.d.ts +138 -0
  97. package/dist/input/touchControls.js +352 -0
  98. package/dist/input/typingTarget.d.ts +6 -0
  99. package/dist/input/typingTarget.js +27 -0
  100. package/dist/math/bounds.d.ts +61 -0
  101. package/dist/math/bounds.js +121 -0
  102. package/dist/math/color.d.ts +8 -0
  103. package/dist/math/color.js +35 -0
  104. package/dist/math/exact.d.ts +66 -0
  105. package/dist/math/exact.js +262 -0
  106. package/dist/math/frustum.d.ts +44 -0
  107. package/dist/math/frustum.js +90 -0
  108. package/dist/math/intersect.d.ts +76 -0
  109. package/dist/math/intersect.js +185 -0
  110. package/dist/math/scalar.d.ts +51 -0
  111. package/dist/math/scalar.js +99 -0
  112. package/dist/math/spring.d.ts +59 -0
  113. package/dist/math/spring.js +88 -0
  114. package/dist/nav/navGraph.d.ts +71 -0
  115. package/dist/nav/navGraph.js +111 -0
  116. package/dist/nav/navPath.d.ts +93 -0
  117. package/dist/nav/navPath.js +162 -0
  118. package/dist/nav/navSearch.d.ts +74 -0
  119. package/dist/nav/navSearch.js +198 -0
  120. package/dist/physics/boxSurface.d.ts +48 -0
  121. package/dist/physics/boxSurface.js +73 -0
  122. package/dist/physics/colliderSurface.d.ts +46 -0
  123. package/dist/physics/colliderSurface.js +146 -0
  124. package/dist/physics/compositeSurface.d.ts +33 -0
  125. package/dist/physics/compositeSurface.js +108 -0
  126. package/dist/physics/heightSurface.d.ts +103 -0
  127. package/dist/physics/heightSurface.js +153 -0
  128. package/dist/physics/ribbonSurface.d.ts +239 -0
  129. package/dist/physics/ribbonSurface.js +522 -0
  130. package/dist/render/ambientOcclusionPass.d.ts +53 -0
  131. package/dist/render/ambientOcclusionPass.js +179 -0
  132. package/dist/render/areaLights.d.ts +116 -0
  133. package/dist/render/areaLights.js +91 -0
  134. package/dist/render/areaShadowSet.d.ts +184 -0
  135. package/dist/render/areaShadowSet.js +277 -0
  136. package/dist/render/atmosphere.d.ts +94 -0
  137. package/dist/render/atmosphere.js +91 -0
  138. package/dist/render/backend/api.d.ts +496 -0
  139. package/dist/render/backend/api.js +1 -0
  140. package/dist/render/backend/budget.d.ts +82 -0
  141. package/dist/render/backend/budget.js +99 -0
  142. package/dist/render/backend/createRenderer.d.ts +135 -0
  143. package/dist/render/backend/createRenderer.js +201 -0
  144. package/dist/render/backend/deadline.d.ts +24 -0
  145. package/dist/render/backend/deadline.js +38 -0
  146. package/dist/render/backend/probe.d.ts +30 -0
  147. package/dist/render/backend/probe.js +129 -0
  148. package/dist/render/backend/select.d.ts +70 -0
  149. package/dist/render/backend/select.js +249 -0
  150. package/dist/render/backend/timer.d.ts +50 -0
  151. package/dist/render/backend/timer.js +1 -0
  152. package/dist/render/backend/webgl2/instanced.d.ts +21 -0
  153. package/dist/render/backend/webgl2/instanced.js +42 -0
  154. package/dist/render/backend/webgl2/morphTexture.d.ts +21 -0
  155. package/dist/render/backend/webgl2/morphTexture.js +55 -0
  156. package/dist/render/backend/webgl2/renderer.d.ts +3027 -0
  157. package/dist/render/backend/webgl2/renderer.js +6041 -0
  158. package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +32 -0
  159. package/dist/render/backend/webgl2/skinPaletteTexture.js +68 -0
  160. package/dist/render/backend/webgpu/boltPass.d.ts +42 -0
  161. package/dist/render/backend/webgpu/boltPass.js +160 -0
  162. package/dist/render/backend/webgpu/buffers.d.ts +159 -0
  163. package/dist/render/backend/webgpu/buffers.js +402 -0
  164. package/dist/render/backend/webgpu/causticsPass.d.ts +36 -0
  165. package/dist/render/backend/webgpu/causticsPass.js +138 -0
  166. package/dist/render/backend/webgpu/clusterBinner.d.ts +51 -0
  167. package/dist/render/backend/webgpu/clusterBinner.js +206 -0
  168. package/dist/render/backend/webgpu/depthPass.d.ts +114 -0
  169. package/dist/render/backend/webgpu/depthPass.js +228 -0
  170. package/dist/render/backend/webgpu/device.d.ts +52 -0
  171. package/dist/render/backend/webgpu/device.js +121 -0
  172. package/dist/render/backend/webgpu/drawCommand.d.ts +43 -0
  173. package/dist/render/backend/webgpu/drawCommand.js +54 -0
  174. package/dist/render/backend/webgpu/environmentTexels.d.ts +28 -0
  175. package/dist/render/backend/webgpu/environmentTexels.js +79 -0
  176. package/dist/render/backend/webgpu/filmPass.d.ts +29 -0
  177. package/dist/render/backend/webgpu/filmPass.js +97 -0
  178. package/dist/render/backend/webgpu/flatPass.d.ts +213 -0
  179. package/dist/render/backend/webgpu/flatPass.js +482 -0
  180. package/dist/render/backend/webgpu/flockPass.d.ts +34 -0
  181. package/dist/render/backend/webgpu/flockPass.js +129 -0
  182. package/dist/render/backend/webgpu/gpuTimestamps.d.ts +94 -0
  183. package/dist/render/backend/webgpu/gpuTimestamps.js +213 -0
  184. package/dist/render/backend/webgpu/insetPass.d.ts +19 -0
  185. package/dist/render/backend/webgpu/insetPass.js +108 -0
  186. package/dist/render/backend/webgpu/instanced.d.ts +27 -0
  187. package/dist/render/backend/webgpu/instanced.js +49 -0
  188. package/dist/render/backend/webgpu/lightVolumePass.d.ts +75 -0
  189. package/dist/render/backend/webgpu/lightVolumePass.js +154 -0
  190. package/dist/render/backend/webgpu/linePass.d.ts +90 -0
  191. package/dist/render/backend/webgpu/linePass.js +220 -0
  192. package/dist/render/backend/webgpu/morphTexture.d.ts +18 -0
  193. package/dist/render/backend/webgpu/morphTexture.js +51 -0
  194. package/dist/render/backend/webgpu/panelPass.d.ts +37 -0
  195. package/dist/render/backend/webgpu/panelPass.js +114 -0
  196. package/dist/render/backend/webgpu/particlePass.d.ts +89 -0
  197. package/dist/render/backend/webgpu/particlePass.js +280 -0
  198. package/dist/render/backend/webgpu/pipelineCache.d.ts +93 -0
  199. package/dist/render/backend/webgpu/pipelineCache.js +140 -0
  200. package/dist/render/backend/webgpu/plumePass.d.ts +69 -0
  201. package/dist/render/backend/webgpu/plumePass.js +213 -0
  202. package/dist/render/backend/webgpu/pointShadowPass.d.ts +88 -0
  203. package/dist/render/backend/webgpu/pointShadowPass.js +280 -0
  204. package/dist/render/backend/webgpu/postPass.d.ts +342 -0
  205. package/dist/render/backend/webgpu/postPass.js +366 -0
  206. package/dist/render/backend/webgpu/probePass.d.ts +108 -0
  207. package/dist/render/backend/webgpu/probePass.js +188 -0
  208. package/dist/render/backend/webgpu/reflectionPass.d.ts +29 -0
  209. package/dist/render/backend/webgpu/reflectionPass.js +87 -0
  210. package/dist/render/backend/webgpu/renderer.d.ts +3082 -0
  211. package/dist/render/backend/webgpu/renderer.js +10911 -0
  212. package/dist/render/backend/webgpu/scatterPass.d.ts +95 -0
  213. package/dist/render/backend/webgpu/scatterPass.js +266 -0
  214. package/dist/render/backend/webgpu/sdfTextPass.d.ts +86 -0
  215. package/dist/render/backend/webgpu/sdfTextPass.js +190 -0
  216. package/dist/render/backend/webgpu/shaderModules.d.ts +9 -0
  217. package/dist/render/backend/webgpu/shaderModules.js +45 -0
  218. package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.d.ts +23 -0
  219. package/dist/render/backend/webgpu/shaders/clusterBin.wgsl.js +208 -0
  220. package/dist/render/backend/webgpu/skinPaletteRing.d.ts +67 -0
  221. package/dist/render/backend/webgpu/skinPaletteRing.js +97 -0
  222. package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +17 -0
  223. package/dist/render/backend/webgpu/skinPaletteTexture.js +68 -0
  224. package/dist/render/backend/webgpu/skyPass.d.ts +102 -0
  225. package/dist/render/backend/webgpu/skyPass.js +70 -0
  226. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +41 -0
  227. package/dist/render/backend/webgpu/surfaceTexturePass.js +228 -0
  228. package/dist/render/backend/webgpu/textPass.d.ts +73 -0
  229. package/dist/render/backend/webgpu/textPass.js +190 -0
  230. package/dist/render/backend/webgpu/uniformRing.d.ts +133 -0
  231. package/dist/render/backend/webgpu/uniformRing.js +208 -0
  232. package/dist/render/backend/webgpu/waterPass.d.ts +73 -0
  233. package/dist/render/backend/webgpu/waterPass.js +160 -0
  234. package/dist/render/backend/webgpu/windStreakPass.d.ts +46 -0
  235. package/dist/render/backend/webgpu/windStreakPass.js +153 -0
  236. package/dist/render/billboard.d.ts +27 -0
  237. package/dist/render/billboard.js +79 -0
  238. package/dist/render/bloomChain.d.ts +66 -0
  239. package/dist/render/bloomChain.js +83 -0
  240. package/dist/render/bloomPass.d.ts +54 -0
  241. package/dist/render/bloomPass.js +219 -0
  242. package/dist/render/boltBatch.d.ts +39 -0
  243. package/dist/render/boltBatch.js +121 -0
  244. package/dist/render/boltPool.d.ts +135 -0
  245. package/dist/render/boltPool.js +259 -0
  246. package/dist/render/boom.d.ts +46 -0
  247. package/dist/render/boom.js +81 -0
  248. package/dist/render/camera.d.ts +119 -0
  249. package/dist/render/camera.js +304 -0
  250. package/dist/render/causticsRenderer.d.ts +63 -0
  251. package/dist/render/causticsRenderer.js +119 -0
  252. package/dist/render/cinematicCamera.d.ts +102 -0
  253. package/dist/render/cinematicCamera.js +227 -0
  254. package/dist/render/clusteredLights.d.ts +260 -0
  255. package/dist/render/clusteredLights.js +479 -0
  256. package/dist/render/colourGrade.d.ts +62 -0
  257. package/dist/render/colourGrade.js +91 -0
  258. package/dist/render/compute.d.ts +74 -0
  259. package/dist/render/compute.js +8 -0
  260. package/dist/render/contextLoss.d.ts +32 -0
  261. package/dist/render/contextLoss.js +46 -0
  262. package/dist/render/debugLines.d.ts +75 -0
  263. package/dist/render/debugLines.js +281 -0
  264. package/dist/render/decalPass.d.ts +34 -0
  265. package/dist/render/decalPass.js +103 -0
  266. package/dist/render/decalProjector.d.ts +140 -0
  267. package/dist/render/decalProjector.js +282 -0
  268. package/dist/render/decalQueue.d.ts +53 -0
  269. package/dist/render/decalQueue.js +87 -0
  270. package/dist/render/depthConvention.d.ts +314 -0
  271. package/dist/render/depthConvention.js +346 -0
  272. package/dist/render/drawingBuffer.d.ts +52 -0
  273. package/dist/render/drawingBuffer.js +67 -0
  274. package/dist/render/emptyTexture.d.ts +60 -0
  275. package/dist/render/emptyTexture.js +103 -0
  276. package/dist/render/envProbeArray.d.ts +85 -0
  277. package/dist/render/envProbeArray.js +164 -0
  278. package/dist/render/equirectToCube.d.ts +54 -0
  279. package/dist/render/equirectToCube.js +123 -0
  280. package/dist/render/flockGeometry.d.ts +23 -0
  281. package/dist/render/flockGeometry.js +43 -0
  282. package/dist/render/flockRenderer.d.ts +37 -0
  283. package/dist/render/flockRenderer.js +70 -0
  284. package/dist/render/frame/arena.d.ts +32 -0
  285. package/dist/render/frame/arena.js +65 -0
  286. package/dist/render/frame/index.d.ts +18 -0
  287. package/dist/render/frame/index.js +4 -0
  288. package/dist/render/frame/replay.d.ts +34 -0
  289. package/dist/render/frame/replay.js +48 -0
  290. package/dist/render/frame/resources.d.ts +25 -0
  291. package/dist/render/frame/resources.js +55 -0
  292. package/dist/render/frame/schedule.d.ts +37 -0
  293. package/dist/render/frame/schedule.js +61 -0
  294. package/dist/render/frameView.d.ts +19 -0
  295. package/dist/render/frameView.js +1 -0
  296. package/dist/render/gizmo.d.ts +236 -0
  297. package/dist/render/gizmo.js +727 -0
  298. package/dist/render/globalMedium.d.ts +124 -0
  299. package/dist/render/globalMedium.js +100 -0
  300. package/dist/render/globalMediumPass.d.ts +101 -0
  301. package/dist/render/globalMediumPass.js +250 -0
  302. package/dist/render/gpuCapability.d.ts +111 -0
  303. package/dist/render/gpuCapability.js +194 -0
  304. package/dist/render/gpuTimer.d.ts +87 -0
  305. package/dist/render/gpuTimer.js +145 -0
  306. package/dist/render/halfFloat.d.ts +4 -0
  307. package/dist/render/halfFloat.js +38 -0
  308. package/dist/render/handleRegistry.d.ts +54 -0
  309. package/dist/render/handleRegistry.js +84 -0
  310. package/dist/render/iesProfile.d.ts +64 -0
  311. package/dist/render/iesProfile.js +179 -0
  312. package/dist/render/imageTexels.d.ts +50 -0
  313. package/dist/render/imageTexels.js +91 -0
  314. package/dist/render/instancedMesh.d.ts +48 -0
  315. package/dist/render/instancedMesh.js +127 -0
  316. package/dist/render/instances.d.ts +69 -0
  317. package/dist/render/instances.js +52 -0
  318. package/dist/render/lightBudget.d.ts +397 -0
  319. package/dist/render/lightBudget.js +524 -0
  320. package/dist/render/lightMatrix.d.ts +3 -0
  321. package/dist/render/lightMatrix.js +45 -0
  322. package/dist/render/lightVolumeDraw.d.ts +132 -0
  323. package/dist/render/lightVolumeDraw.js +181 -0
  324. package/dist/render/lineBatch.d.ts +60 -0
  325. package/dist/render/lineBatch.js +160 -0
  326. package/dist/render/linePoints.d.ts +33 -0
  327. package/dist/render/linePoints.js +46 -0
  328. package/dist/render/livePointShadowSet.d.ts +72 -0
  329. package/dist/render/livePointShadowSet.js +258 -0
  330. package/dist/render/lod.d.ts +35 -0
  331. package/dist/render/lod.js +65 -0
  332. package/dist/render/mesh.d.ts +177 -0
  333. package/dist/render/mesh.js +466 -0
  334. package/dist/render/occlusion.d.ts +81 -0
  335. package/dist/render/occlusion.js +378 -0
  336. package/dist/render/oitPass.d.ts +67 -0
  337. package/dist/render/oitPass.js +213 -0
  338. package/dist/render/orderIndependent.d.ts +92 -0
  339. package/dist/render/orderIndependent.js +108 -0
  340. package/dist/render/particleBatch.d.ts +140 -0
  341. package/dist/render/particleBatch.js +186 -0
  342. package/dist/render/particleMaterial.d.ts +54 -0
  343. package/dist/render/particleMaterial.js +42 -0
  344. package/dist/render/particlePool.d.ts +124 -0
  345. package/dist/render/particlePool.js +182 -0
  346. package/dist/render/pass.d.ts +195 -0
  347. package/dist/render/pass.js +9 -0
  348. package/dist/render/passTarget.d.ts +86 -0
  349. package/dist/render/passTarget.js +121 -0
  350. package/dist/render/pickable.d.ts +31 -0
  351. package/dist/render/pickable.js +172 -0
  352. package/dist/render/planarReflection.d.ts +59 -0
  353. package/dist/render/planarReflection.js +194 -0
  354. package/dist/render/planarReflectionDraw.d.ts +31 -0
  355. package/dist/render/planarReflectionDraw.js +65 -0
  356. package/dist/render/plumeGeometry.d.ts +25 -0
  357. package/dist/render/plumeGeometry.js +61 -0
  358. package/dist/render/plumeMaterial.d.ts +31 -0
  359. package/dist/render/plumeMaterial.js +64 -0
  360. package/dist/render/plumeRenderer.d.ts +96 -0
  361. package/dist/render/plumeRenderer.js +185 -0
  362. package/dist/render/pointLightSelection.d.ts +175 -0
  363. package/dist/render/pointLightSelection.js +301 -0
  364. package/dist/render/pointShadowArray.d.ts +95 -0
  365. package/dist/render/pointShadowArray.js +219 -0
  366. package/dist/render/pointShadowBudget.d.ts +118 -0
  367. package/dist/render/pointShadowBudget.js +221 -0
  368. package/dist/render/pointShadowImage.d.ts +265 -0
  369. package/dist/render/pointShadowImage.js +339 -0
  370. package/dist/render/pointShadowMap.d.ts +93 -0
  371. package/dist/render/pointShadowMap.js +167 -0
  372. package/dist/render/pointShadowSystem.d.ts +195 -0
  373. package/dist/render/pointShadowSystem.js +336 -0
  374. package/dist/render/prefilterEnvMap.d.ts +124 -0
  375. package/dist/render/prefilterEnvMap.js +146 -0
  376. package/dist/render/prefilterPass.d.ts +44 -0
  377. package/dist/render/prefilterPass.js +98 -0
  378. package/dist/render/probeGrid.d.ts +122 -0
  379. package/dist/render/probeGrid.js +174 -0
  380. package/dist/render/rainField.d.ts +99 -0
  381. package/dist/render/rainField.js +168 -0
  382. package/dist/render/reflectionProbe.d.ts +188 -0
  383. package/dist/render/reflectionProbe.js +437 -0
  384. package/dist/render/renderQuality.d.ts +699 -0
  385. package/dist/render/renderQuality.js +293 -0
  386. package/dist/render/rendererHarness.d.ts +39 -0
  387. package/dist/render/rendererHarness.js +185 -0
  388. package/dist/render/resolutionGovernor.d.ts +107 -0
  389. package/dist/render/resolutionGovernor.js +144 -0
  390. package/dist/render/scatterDeform.d.ts +17 -0
  391. package/dist/render/scatterDeform.js +46 -0
  392. package/dist/render/sceneTarget.d.ts +288 -0
  393. package/dist/render/sceneTarget.js +856 -0
  394. package/dist/render/screenSpaceReflection.d.ts +233 -0
  395. package/dist/render/screenSpaceReflection.js +415 -0
  396. package/dist/render/sdfFont.d.ts +77 -0
  397. package/dist/render/sdfFont.js +86 -0
  398. package/dist/render/sdfTextLayout.d.ts +46 -0
  399. package/dist/render/sdfTextLayout.js +145 -0
  400. package/dist/render/sdfTextRenderer.d.ts +75 -0
  401. package/dist/render/sdfTextRenderer.js +194 -0
  402. package/dist/render/seaState.d.ts +25 -0
  403. package/dist/render/seaState.js +34 -0
  404. package/dist/render/segmentQuads.d.ts +29 -0
  405. package/dist/render/segmentQuads.js +75 -0
  406. package/dist/render/shader.d.ts +5 -0
  407. package/dist/render/shader.js +172 -0
  408. package/dist/render/shaders/ambientOcclusion.d.ts +45 -0
  409. package/dist/render/shaders/ambientOcclusion.js +352 -0
  410. package/dist/render/shaders/arcane.d.ts +19 -0
  411. package/dist/render/shaders/arcane.js +102 -0
  412. package/dist/render/shaders/bloom.d.ts +70 -0
  413. package/dist/render/shaders/bloom.js +227 -0
  414. package/dist/render/shaders/bolt.d.ts +17 -0
  415. package/dist/render/shaders/bolt.js +161 -0
  416. package/dist/render/shaders/caustics.d.ts +38 -0
  417. package/dist/render/shaders/caustics.js +167 -0
  418. package/dist/render/shaders/conditionals.d.ts +21 -0
  419. package/dist/render/shaders/conditionals.js +55 -0
  420. package/dist/render/shaders/decalProject.d.ts +25 -0
  421. package/dist/render/shaders/decalProject.js +125 -0
  422. package/dist/render/shaders/depth.d.ts +14 -0
  423. package/dist/render/shaders/depth.js +114 -0
  424. package/dist/render/shaders/depthOfField.d.ts +41 -0
  425. package/dist/render/shaders/depthOfField.js +139 -0
  426. package/dist/render/shaders/film.d.ts +15 -0
  427. package/dist/render/shaders/film.js +283 -0
  428. package/dist/render/shaders/fire.d.ts +12 -0
  429. package/dist/render/shaders/fire.js +178 -0
  430. package/dist/render/shaders/flat/directionalShadow.d.ts +1 -0
  431. package/dist/render/shaders/flat/directionalShadow.js +195 -0
  432. package/dist/render/shaders/flat/index.d.ts +135 -0
  433. package/dist/render/shaders/flat/index.js +387 -0
  434. package/dist/render/shaders/flat/lobes.d.ts +1 -0
  435. package/dist/render/shaders/flat/lobes.js +398 -0
  436. package/dist/render/shaders/flat/main.d.ts +2 -0
  437. package/dist/render/shaders/flat/main.js +1630 -0
  438. package/dist/render/shaders/flat/pointShadow.d.ts +1 -0
  439. package/dist/render/shaders/flat/pointShadow.js +322 -0
  440. package/dist/render/shaders/flat/preamble.d.ts +15 -0
  441. package/dist/render/shaders/flat/preamble.js +864 -0
  442. package/dist/render/shaders/flat/probeGrid.d.ts +21 -0
  443. package/dist/render/shaders/flat/probeGrid.js +151 -0
  444. package/dist/render/shaders/flat/surface.d.ts +2 -0
  445. package/dist/render/shaders/flat/surface.js +40 -0
  446. package/dist/render/shaders/flock.d.ts +11 -0
  447. package/dist/render/shaders/flock.js +102 -0
  448. package/dist/render/shaders/fog.d.ts +37 -0
  449. package/dist/render/shaders/fog.js +98 -0
  450. package/dist/render/shaders/fullscreen.d.ts +16 -0
  451. package/dist/render/shaders/fullscreen.js +27 -0
  452. package/dist/render/shaders/generated/ambientOcclusion.wgsl.d.ts +65 -0
  453. package/dist/render/shaders/generated/ambientOcclusion.wgsl.js +71 -0
  454. package/dist/render/shaders/generated/arcane.wgsl.d.ts +90 -0
  455. package/dist/render/shaders/generated/arcane.wgsl.js +96 -0
  456. package/dist/render/shaders/generated/bloom.wgsl.d.ts +69 -0
  457. package/dist/render/shaders/generated/bloom.wgsl.js +75 -0
  458. package/dist/render/shaders/generated/bolt.wgsl.d.ts +118 -0
  459. package/dist/render/shaders/generated/bolt.wgsl.js +124 -0
  460. package/dist/render/shaders/generated/caustics.wgsl.d.ts +118 -0
  461. package/dist/render/shaders/generated/caustics.wgsl.js +124 -0
  462. package/dist/render/shaders/generated/decalProject.wgsl.d.ts +61 -0
  463. package/dist/render/shaders/generated/decalProject.wgsl.js +67 -0
  464. package/dist/render/shaders/generated/depth.wgsl.d.ts +131 -0
  465. package/dist/render/shaders/generated/depth.wgsl.js +137 -0
  466. package/dist/render/shaders/generated/film.wgsl.d.ts +134 -0
  467. package/dist/render/shaders/generated/film.wgsl.js +140 -0
  468. package/dist/render/shaders/generated/fire.wgsl.d.ts +128 -0
  469. package/dist/render/shaders/generated/fire.wgsl.js +134 -0
  470. package/dist/render/shaders/generated/flat.wgsl.d.ts +9163 -0
  471. package/dist/render/shaders/generated/flat.wgsl.js +9192 -0
  472. package/dist/render/shaders/generated/flock.wgsl.d.ts +73 -0
  473. package/dist/render/shaders/generated/flock.wgsl.js +79 -0
  474. package/dist/render/shaders/generated/fullscreen.wgsl.d.ts +12 -0
  475. package/dist/render/shaders/generated/fullscreen.wgsl.js +18 -0
  476. package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +130 -0
  477. package/dist/render/shaders/generated/globalMedium.wgsl.js +136 -0
  478. package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +230 -0
  479. package/dist/render/shaders/generated/lightVolume.wgsl.js +239 -0
  480. package/dist/render/shaders/generated/line.wgsl.d.ts +128 -0
  481. package/dist/render/shaders/generated/line.wgsl.js +134 -0
  482. package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +51 -0
  483. package/dist/render/shaders/generated/octahedralResolve.wgsl.js +57 -0
  484. package/dist/render/shaders/generated/oitResolve.wgsl.d.ts +23 -0
  485. package/dist/render/shaders/generated/oitResolve.wgsl.js +29 -0
  486. package/dist/render/shaders/generated/panel.wgsl.d.ts +48 -0
  487. package/dist/render/shaders/generated/panel.wgsl.js +54 -0
  488. package/dist/render/shaders/generated/particle.wgsl.d.ts +332 -0
  489. package/dist/render/shaders/generated/particle.wgsl.js +338 -0
  490. package/dist/render/shaders/generated/prefilter.wgsl.d.ts +61 -0
  491. package/dist/render/shaders/generated/prefilter.wgsl.js +67 -0
  492. package/dist/render/shaders/generated/rush.wgsl.d.ts +131 -0
  493. package/dist/render/shaders/generated/rush.wgsl.js +137 -0
  494. package/dist/render/shaders/generated/scatter.wgsl.d.ts +195 -0
  495. package/dist/render/shaders/generated/scatter.wgsl.js +201 -0
  496. package/dist/render/shaders/generated/sdfText.wgsl.d.ts +69 -0
  497. package/dist/render/shaders/generated/sdfText.wgsl.js +75 -0
  498. package/dist/render/shaders/generated/sky.wgsl.d.ts +100 -0
  499. package/dist/render/shaders/generated/sky.wgsl.js +106 -0
  500. package/dist/render/shaders/generated/smoke.wgsl.d.ts +85 -0
  501. package/dist/render/shaders/generated/smoke.wgsl.js +91 -0
  502. package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +18 -0
  503. package/dist/render/shaders/generated/ssrResolve.wgsl.js +24 -0
  504. package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +86 -0
  505. package/dist/render/shaders/generated/ssrTrace.wgsl.js +92 -0
  506. package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +46 -0
  507. package/dist/render/shaders/generated/temporalResolve.wgsl.js +52 -0
  508. package/dist/render/shaders/generated/text.wgsl.d.ts +98 -0
  509. package/dist/render/shaders/generated/text.wgsl.js +104 -0
  510. package/dist/render/shaders/generated/water.wgsl.d.ts +247 -0
  511. package/dist/render/shaders/generated/water.wgsl.js +253 -0
  512. package/dist/render/shaders/generated/windStreaks.wgsl.d.ts +73 -0
  513. package/dist/render/shaders/generated/windStreaks.wgsl.js +79 -0
  514. package/dist/render/shaders/gerstner.d.ts +21 -0
  515. package/dist/render/shaders/gerstner.js +110 -0
  516. package/dist/render/shaders/globalMedium.d.ts +56 -0
  517. package/dist/render/shaders/globalMedium.js +393 -0
  518. package/dist/render/shaders/lightVolume.d.ts +61 -0
  519. package/dist/render/shaders/lightVolume.js +527 -0
  520. package/dist/render/shaders/line.d.ts +18 -0
  521. package/dist/render/shaders/line.js +122 -0
  522. package/dist/render/shaders/morph.d.ts +26 -0
  523. package/dist/render/shaders/morph.js +61 -0
  524. package/dist/render/shaders/octahedral.d.ts +76 -0
  525. package/dist/render/shaders/octahedral.js +161 -0
  526. package/dist/render/shaders/octahedralResolve.d.ts +25 -0
  527. package/dist/render/shaders/octahedralResolve.js +81 -0
  528. package/dist/render/shaders/oitResolve.d.ts +17 -0
  529. package/dist/render/shaders/oitResolve.js +42 -0
  530. package/dist/render/shaders/outputTransform.d.ts +37 -0
  531. package/dist/render/shaders/outputTransform.js +106 -0
  532. package/dist/render/shaders/panel.d.ts +17 -0
  533. package/dist/render/shaders/panel.js +50 -0
  534. package/dist/render/shaders/particle.d.ts +82 -0
  535. package/dist/render/shaders/particle.js +431 -0
  536. package/dist/render/shaders/prefilter.d.ts +37 -0
  537. package/dist/render/shaders/prefilter.js +276 -0
  538. package/dist/render/shaders/rush.d.ts +21 -0
  539. package/dist/render/shaders/rush.js +355 -0
  540. package/dist/render/shaders/scatter.d.ts +14 -0
  541. package/dist/render/shaders/scatter.js +206 -0
  542. package/dist/render/shaders/sdfText.d.ts +9 -0
  543. package/dist/render/shaders/sdfText.js +65 -0
  544. package/dist/render/shaders/skinning.d.ts +17 -0
  545. package/dist/render/shaders/skinning.js +59 -0
  546. package/dist/render/shaders/sky.d.ts +10 -0
  547. package/dist/render/shaders/sky.js +242 -0
  548. package/dist/render/shaders/smoke.d.ts +8 -0
  549. package/dist/render/shaders/smoke.js +88 -0
  550. package/dist/render/shaders/ssrResolve.d.ts +15 -0
  551. package/dist/render/shaders/ssrResolve.js +28 -0
  552. package/dist/render/shaders/ssrTrace.d.ts +22 -0
  553. package/dist/render/shaders/ssrTrace.js +230 -0
  554. package/dist/render/shaders/tangentFrame.d.ts +17 -0
  555. package/dist/render/shaders/tangentFrame.js +70 -0
  556. package/dist/render/shaders/temporalResolve.d.ts +1 -0
  557. package/dist/render/shaders/temporalResolve.js +150 -0
  558. package/dist/render/shaders/text.d.ts +17 -0
  559. package/dist/render/shaders/text.js +155 -0
  560. package/dist/render/shaders/vertexChannel.d.ts +39 -0
  561. package/dist/render/shaders/vertexChannel.js +69 -0
  562. package/dist/render/shaders/water.d.ts +18 -0
  563. package/dist/render/shaders/water.js +354 -0
  564. package/dist/render/shaders/windStreaks.d.ts +14 -0
  565. package/dist/render/shaders/windStreaks.js +129 -0
  566. package/dist/render/shadowCasters.d.ts +107 -0
  567. package/dist/render/shadowCasters.js +1 -0
  568. package/dist/render/shadowMap.d.ts +10 -0
  569. package/dist/render/shadowMap.js +80 -0
  570. package/dist/render/shotPlacement.d.ts +80 -0
  571. package/dist/render/shotPlacement.js +183 -0
  572. package/dist/render/skinPalette.d.ts +90 -0
  573. package/dist/render/skinPalette.js +136 -0
  574. package/dist/render/ssrPass.d.ts +59 -0
  575. package/dist/render/ssrPass.js +196 -0
  576. package/dist/render/surfaceSheet.d.ts +52 -0
  577. package/dist/render/surfaceSheet.js +99 -0
  578. package/dist/render/surfaceTexture.d.ts +197 -0
  579. package/dist/render/surfaceTexture.js +116 -0
  580. package/dist/render/temporalAa.d.ts +104 -0
  581. package/dist/render/temporalAa.js +194 -0
  582. package/dist/render/temporalPass.d.ts +54 -0
  583. package/dist/render/temporalPass.js +135 -0
  584. package/dist/render/textLayout.d.ts +88 -0
  585. package/dist/render/textLayout.js +201 -0
  586. package/dist/render/textRenderer.d.ts +32 -0
  587. package/dist/render/textRenderer.js +176 -0
  588. package/dist/render/thirdPersonCamera.d.ts +272 -0
  589. package/dist/render/thirdPersonCamera.js +479 -0
  590. package/dist/render/trample.d.ts +57 -0
  591. package/dist/render/trample.js +134 -0
  592. package/dist/render/translucentQueue.d.ts +76 -0
  593. package/dist/render/translucentQueue.js +90 -0
  594. package/dist/render/uniformVectorBudget.d.ts +105 -0
  595. package/dist/render/uniformVectorBudget.js +201 -0
  596. package/dist/render/uploadStep.d.ts +14 -0
  597. package/dist/render/uploadStep.js +14 -0
  598. package/dist/render/vertexDefaults.d.ts +48 -0
  599. package/dist/render/vertexDefaults.js +111 -0
  600. package/dist/render/visibility.d.ts +22 -0
  601. package/dist/render/visibility.js +47 -0
  602. package/dist/render/waterDraw.d.ts +57 -0
  603. package/dist/render/waterDraw.js +102 -0
  604. package/dist/render/waterGrid.d.ts +62 -0
  605. package/dist/render/waterGrid.js +151 -0
  606. package/dist/render/waterRenderer.d.ts +163 -0
  607. package/dist/render/waterRenderer.js +165 -0
  608. package/dist/render/wind.d.ts +45 -0
  609. package/dist/render/wind.js +32 -0
  610. package/dist/render/windField.d.ts +34 -0
  611. package/dist/render/windField.js +13 -0
  612. package/dist/render/windStreakDraw.d.ts +73 -0
  613. package/dist/render/windStreakDraw.js +86 -0
  614. package/dist/render/windStreakRenderer.d.ts +37 -0
  615. package/dist/render/windStreakRenderer.js +86 -0
  616. package/dist/scene/node.d.ts +128 -0
  617. package/dist/scene/node.js +319 -0
  618. package/dist/scene/visit.d.ts +38 -0
  619. package/dist/scene/visit.js +43 -0
  620. package/dist/ui/clipMime.d.ts +46 -0
  621. package/dist/ui/clipMime.js +88 -0
  622. package/dist/ui/exportTarget.d.ts +305 -0
  623. package/dist/ui/exportTarget.js +368 -0
  624. package/dist/ui/frameOverlay.d.ts +59 -0
  625. package/dist/ui/frameOverlay.js +76 -0
  626. package/dist/ui/framePacer.d.ts +142 -0
  627. package/dist/ui/framePacer.js +284 -0
  628. package/dist/ui/frameRecorder.d.ts +188 -0
  629. package/dist/ui/frameRecorder.js +221 -0
  630. package/dist/ui/fullscreen.d.ts +72 -0
  631. package/dist/ui/fullscreen.js +92 -0
  632. package/dist/ui/pixelCursor.d.ts +28 -0
  633. package/dist/ui/pixelCursor.js +66 -0
  634. package/dist/ui/splash.d.ts +86 -0
  635. package/dist/ui/splash.js +300 -0
  636. package/dist/ui/stillFrame.d.ts +22 -0
  637. package/dist/ui/stillFrame.js +40 -0
  638. package/package.json +60 -0
  639. package/src/behavior/behaviorTree.ts +346 -0
  640. package/src/build/shaderComments.ts +0 -0
  641. package/src/cinematic/player.ts +209 -0
  642. package/src/cinematic/script.ts +231 -0
  643. package/src/core/bootGate.ts +49 -0
  644. package/src/core/loadTracker.ts +144 -0
  645. package/src/core/loop.ts +211 -0
  646. package/src/core/messageQueue.ts +145 -0
  647. package/src/core/onceSet.ts +65 -0
  648. package/src/core/preferences.ts +177 -0
  649. package/src/core/remoteSave.ts +347 -0
  650. package/src/core/rng.ts +101 -0
  651. package/src/core/stepBudget.ts +136 -0
  652. package/src/core/storage.ts +114 -0
  653. package/src/core/tickTrace.ts +129 -0
  654. package/src/core/timeCurve.ts +175 -0
  655. package/src/core/withDefaults.ts +28 -0
  656. package/src/dev/contactProbe.ts +115 -0
  657. package/src/dev/fpsMeter.ts +101 -0
  658. package/src/environment/celestialClock.ts +385 -0
  659. package/src/geometry/decal.ts +260 -0
  660. package/src/geometry/filmPatch.ts +158 -0
  661. package/src/geometry/growable.ts +165 -0
  662. package/src/geometry/lightVolume.ts +161 -0
  663. package/src/geometry/meshBuilder.ts +1397 -0
  664. package/src/geometry/pixelFont.ts +189 -0
  665. package/src/geometry/ribbon.ts +790 -0
  666. package/src/geometry/shellFill.ts +265 -0
  667. package/src/geometry/spline.ts +659 -0
  668. package/src/geometry/tangents.ts +173 -0
  669. package/src/geometry/textMesh.ts +96 -0
  670. package/src/geometry/treeBuilder.ts +114 -0
  671. package/src/host/display.ts +180 -0
  672. package/src/host/files.ts +77 -0
  673. package/src/host/lifecycle.ts +63 -0
  674. package/src/host/platformServices.ts +23 -0
  675. package/src/host/screen.ts +134 -0
  676. package/src/index.ts +730 -0
  677. package/src/input/actionMap.ts +377 -0
  678. package/src/input/activeDevice.ts +86 -0
  679. package/src/input/gamepadIdentity.ts +131 -0
  680. package/src/input/gamepadMapping.ts +121 -0
  681. package/src/input/input.ts +872 -0
  682. package/src/input/inputHarness.ts +226 -0
  683. package/src/input/rightGesture.ts +76 -0
  684. package/src/input/rumble.ts +138 -0
  685. package/src/input/touchControls.ts +451 -0
  686. package/src/input/typingTarget.ts +26 -0
  687. package/src/math/bounds.ts +153 -0
  688. package/src/math/color.ts +37 -0
  689. package/src/math/exact.ts +274 -0
  690. package/src/math/frustum.ts +115 -0
  691. package/src/math/intersect.ts +228 -0
  692. package/src/math/scalar.ts +109 -0
  693. package/src/math/spring.ts +106 -0
  694. package/src/nav/navGraph.ts +168 -0
  695. package/src/nav/navPath.ts +217 -0
  696. package/src/nav/navSearch.ts +200 -0
  697. package/src/physics/boxSurface.ts +96 -0
  698. package/src/physics/colliderSurface.ts +213 -0
  699. package/src/physics/compositeSurface.ts +111 -0
  700. package/src/physics/heightSurface.ts +234 -0
  701. package/src/physics/ribbonSurface.ts +642 -0
  702. package/src/render/ambientOcclusionPass.ts +200 -0
  703. package/src/render/areaLights.ts +194 -0
  704. package/src/render/areaShadowSet.ts +405 -0
  705. package/src/render/atmosphere.ts +186 -0
  706. package/src/render/backend/api.ts +802 -0
  707. package/src/render/backend/budget.ts +139 -0
  708. package/src/render/backend/createRenderer.ts +343 -0
  709. package/src/render/backend/deadline.ts +37 -0
  710. package/src/render/backend/probe.ts +152 -0
  711. package/src/render/backend/select.ts +288 -0
  712. package/src/render/backend/timer.ts +59 -0
  713. package/src/render/backend/webgl2/instanced.ts +46 -0
  714. package/src/render/backend/webgl2/morphTexture.ts +58 -0
  715. package/src/render/backend/webgl2/renderer.ts +7484 -0
  716. package/src/render/backend/webgl2/skinPaletteTexture.ts +70 -0
  717. package/src/render/backend/webgpu/boltPass.ts +205 -0
  718. package/src/render/backend/webgpu/buffers.ts +553 -0
  719. package/src/render/backend/webgpu/causticsPass.ts +174 -0
  720. package/src/render/backend/webgpu/clusterBinner.ts +259 -0
  721. package/src/render/backend/webgpu/depthPass.ts +261 -0
  722. package/src/render/backend/webgpu/device.ts +148 -0
  723. package/src/render/backend/webgpu/drawCommand.ts +79 -0
  724. package/src/render/backend/webgpu/environmentTexels.ts +96 -0
  725. package/src/render/backend/webgpu/filmPass.ts +123 -0
  726. package/src/render/backend/webgpu/flatPass.ts +635 -0
  727. package/src/render/backend/webgpu/flockPass.ts +163 -0
  728. package/src/render/backend/webgpu/gpuTimestamps.ts +255 -0
  729. package/src/render/backend/webgpu/insetPass.ts +123 -0
  730. package/src/render/backend/webgpu/instanced.ts +55 -0
  731. package/src/render/backend/webgpu/lightVolumePass.ts +203 -0
  732. package/src/render/backend/webgpu/linePass.ts +270 -0
  733. package/src/render/backend/webgpu/morphTexture.ts +61 -0
  734. package/src/render/backend/webgpu/panelPass.ts +138 -0
  735. package/src/render/backend/webgpu/particlePass.ts +370 -0
  736. package/src/render/backend/webgpu/pipelineCache.ts +152 -0
  737. package/src/render/backend/webgpu/plumePass.ts +292 -0
  738. package/src/render/backend/webgpu/pointShadowPass.ts +368 -0
  739. package/src/render/backend/webgpu/postPass.ts +470 -0
  740. package/src/render/backend/webgpu/probePass.ts +218 -0
  741. package/src/render/backend/webgpu/reflectionPass.ts +137 -0
  742. package/src/render/backend/webgpu/renderer.ts +13004 -0
  743. package/src/render/backend/webgpu/scatterPass.ts +354 -0
  744. package/src/render/backend/webgpu/sdfTextPass.ts +220 -0
  745. package/src/render/backend/webgpu/shaderModules.ts +49 -0
  746. package/src/render/backend/webgpu/shaders/clusterBin.wgsl.ts +219 -0
  747. package/src/render/backend/webgpu/skinPaletteRing.ts +105 -0
  748. package/src/render/backend/webgpu/skinPaletteTexture.ts +79 -0
  749. package/src/render/backend/webgpu/skyPass.ts +85 -0
  750. package/src/render/backend/webgpu/surfaceTexturePass.ts +257 -0
  751. package/src/render/backend/webgpu/textPass.ts +224 -0
  752. package/src/render/backend/webgpu/uniformRing.ts +228 -0
  753. package/src/render/backend/webgpu/waterPass.ts +211 -0
  754. package/src/render/backend/webgpu/windStreakPass.ts +196 -0
  755. package/src/render/billboard.ts +108 -0
  756. package/src/render/bloomChain.ts +101 -0
  757. package/src/render/bloomPass.ts +256 -0
  758. package/src/render/boltBatch.ts +141 -0
  759. package/src/render/boltPool.ts +360 -0
  760. package/src/render/boom.ts +123 -0
  761. package/src/render/camera.ts +348 -0
  762. package/src/render/causticsRenderer.ts +171 -0
  763. package/src/render/cinematicCamera.ts +278 -0
  764. package/src/render/clusteredLights.ts +598 -0
  765. package/src/render/colourGrade.ts +109 -0
  766. package/src/render/compute.ts +83 -0
  767. package/src/render/contextLoss.ts +50 -0
  768. package/src/render/debugLines.ts +411 -0
  769. package/src/render/decalPass.ts +124 -0
  770. package/src/render/decalProjector.ts +390 -0
  771. package/src/render/decalQueue.ts +110 -0
  772. package/src/render/depthConvention.ts +383 -0
  773. package/src/render/drawingBuffer.ts +89 -0
  774. package/src/render/emptyTexture.ts +130 -0
  775. package/src/render/envProbeArray.ts +201 -0
  776. package/src/render/equirectToCube.ts +160 -0
  777. package/src/render/flockGeometry.ts +53 -0
  778. package/src/render/flockRenderer.ts +111 -0
  779. package/src/render/frame/arena.ts +93 -0
  780. package/src/render/frame/index.ts +29 -0
  781. package/src/render/frame/replay.ts +50 -0
  782. package/src/render/frame/resources.ts +61 -0
  783. package/src/render/frame/schedule.ts +85 -0
  784. package/src/render/frameView.ts +20 -0
  785. package/src/render/gizmo.ts +923 -0
  786. package/src/render/globalMedium.ts +154 -0
  787. package/src/render/globalMediumPass.ts +323 -0
  788. package/src/render/gpuCapability.ts +244 -0
  789. package/src/render/gpuTimer.ts +182 -0
  790. package/src/render/halfFloat.ts +39 -0
  791. package/src/render/handleRegistry.ts +96 -0
  792. package/src/render/iesProfile.ts +215 -0
  793. package/src/render/imageTexels.ts +109 -0
  794. package/src/render/instancedMesh.ts +187 -0
  795. package/src/render/instances.ts +92 -0
  796. package/src/render/lightBudget.ts +655 -0
  797. package/src/render/lightMatrix.ts +69 -0
  798. package/src/render/lightVolumeDraw.ts +216 -0
  799. package/src/render/lineBatch.ts +180 -0
  800. package/src/render/linePoints.ts +61 -0
  801. package/src/render/livePointShadowSet.ts +285 -0
  802. package/src/render/lod.ts +86 -0
  803. package/src/render/mesh.ts +536 -0
  804. package/src/render/occlusion.ts +406 -0
  805. package/src/render/oitPass.ts +230 -0
  806. package/src/render/orderIndependent.ts +136 -0
  807. package/src/render/particleBatch.ts +299 -0
  808. package/src/render/particleMaterial.ts +84 -0
  809. package/src/render/particlePool.ts +291 -0
  810. package/src/render/pass.ts +203 -0
  811. package/src/render/passTarget.ts +225 -0
  812. package/src/render/pickable.ts +222 -0
  813. package/src/render/planarReflection.ts +233 -0
  814. package/src/render/planarReflectionDraw.ts +87 -0
  815. package/src/render/plumeGeometry.ts +75 -0
  816. package/src/render/plumeMaterial.ts +99 -0
  817. package/src/render/plumeRenderer.ts +272 -0
  818. package/src/render/pointLightSelection.ts +447 -0
  819. package/src/render/pointShadowArray.ts +276 -0
  820. package/src/render/pointShadowBudget.ts +305 -0
  821. package/src/render/pointShadowImage.ts +470 -0
  822. package/src/render/pointShadowMap.ts +228 -0
  823. package/src/render/pointShadowSystem.ts +408 -0
  824. package/src/render/prefilterEnvMap.ts +162 -0
  825. package/src/render/prefilterPass.ts +115 -0
  826. package/src/render/probeGrid.ts +248 -0
  827. package/src/render/rainField.ts +240 -0
  828. package/src/render/reflectionProbe.ts +530 -0
  829. package/src/render/renderQuality.ts +1054 -0
  830. package/src/render/rendererHarness.ts +214 -0
  831. package/src/render/resolutionGovernor.ts +189 -0
  832. package/src/render/scatterDeform.ts +72 -0
  833. package/src/render/sceneTarget.ts +1032 -0
  834. package/src/render/screenSpaceReflection.ts +524 -0
  835. package/src/render/sdfFont.ts +157 -0
  836. package/src/render/sdfTextLayout.ts +206 -0
  837. package/src/render/sdfTextRenderer.ts +233 -0
  838. package/src/render/seaState.ts +55 -0
  839. package/src/render/segmentQuads.ts +92 -0
  840. package/src/render/shader.ts +190 -0
  841. package/src/render/shaders/ambientOcclusion.ts +354 -0
  842. package/src/render/shaders/arcane.ts +103 -0
  843. package/src/render/shaders/bloom.ts +232 -0
  844. package/src/render/shaders/bolt.ts +164 -0
  845. package/src/render/shaders/caustics.ts +169 -0
  846. package/src/render/shaders/conditionals.ts +58 -0
  847. package/src/render/shaders/decalProject.ts +127 -0
  848. package/src/render/shaders/depth.ts +131 -0
  849. package/src/render/shaders/depthOfField.ts +141 -0
  850. package/src/render/shaders/film.ts +285 -0
  851. package/src/render/shaders/fire.ts +180 -0
  852. package/src/render/shaders/flat/directionalShadow.ts +196 -0
  853. package/src/render/shaders/flat/index.ts +502 -0
  854. package/src/render/shaders/flat/lobes.ts +399 -0
  855. package/src/render/shaders/flat/main.ts +1631 -0
  856. package/src/render/shaders/flat/pointShadow.ts +323 -0
  857. package/src/render/shaders/flat/preamble.ts +875 -0
  858. package/src/render/shaders/flat/probeGrid.ts +152 -0
  859. package/src/render/shaders/flat/surface.ts +41 -0
  860. package/src/render/shaders/flock.ts +103 -0
  861. package/src/render/shaders/fog.ts +99 -0
  862. package/src/render/shaders/fullscreen.ts +28 -0
  863. package/src/render/shaders/generated/ambientOcclusion.wgsl.ts +74 -0
  864. package/src/render/shaders/generated/arcane.wgsl.ts +98 -0
  865. package/src/render/shaders/generated/bloom.wgsl.ts +79 -0
  866. package/src/render/shaders/generated/bolt.wgsl.ts +127 -0
  867. package/src/render/shaders/generated/caustics.wgsl.ts +127 -0
  868. package/src/render/shaders/generated/decalProject.wgsl.ts +69 -0
  869. package/src/render/shaders/generated/depth.wgsl.ts +142 -0
  870. package/src/render/shaders/generated/film.wgsl.ts +143 -0
  871. package/src/render/shaders/generated/fire.wgsl.ts +137 -0
  872. package/src/render/shaders/generated/flat.wgsl.ts +9195 -0
  873. package/src/render/shaders/generated/flock.wgsl.ts +82 -0
  874. package/src/render/shaders/generated/fullscreen.wgsl.ts +20 -0
  875. package/src/render/shaders/generated/globalMedium.wgsl.ts +139 -0
  876. package/src/render/shaders/generated/lightVolume.wgsl.ts +242 -0
  877. package/src/render/shaders/generated/line.wgsl.ts +137 -0
  878. package/src/render/shaders/generated/octahedralResolve.wgsl.ts +60 -0
  879. package/src/render/shaders/generated/oitResolve.wgsl.ts +31 -0
  880. package/src/render/shaders/generated/panel.wgsl.ts +57 -0
  881. package/src/render/shaders/generated/particle.wgsl.ts +343 -0
  882. package/src/render/shaders/generated/prefilter.wgsl.ts +69 -0
  883. package/src/render/shaders/generated/rush.wgsl.ts +139 -0
  884. package/src/render/shaders/generated/scatter.wgsl.ts +205 -0
  885. package/src/render/shaders/generated/sdfText.wgsl.ts +78 -0
  886. package/src/render/shaders/generated/sky.wgsl.ts +109 -0
  887. package/src/render/shaders/generated/smoke.wgsl.ts +93 -0
  888. package/src/render/shaders/generated/ssrResolve.wgsl.ts +26 -0
  889. package/src/render/shaders/generated/ssrTrace.wgsl.ts +94 -0
  890. package/src/render/shaders/generated/temporalResolve.wgsl.ts +54 -0
  891. package/src/render/shaders/generated/text.wgsl.ts +107 -0
  892. package/src/render/shaders/generated/water.wgsl.ts +256 -0
  893. package/src/render/shaders/generated/windStreaks.wgsl.ts +82 -0
  894. package/src/render/shaders/gerstner.ts +110 -0
  895. package/src/render/shaders/globalMedium.ts +396 -0
  896. package/src/render/shaders/lightVolume.ts +546 -0
  897. package/src/render/shaders/line.ts +125 -0
  898. package/src/render/shaders/morph.ts +62 -0
  899. package/src/render/shaders/octahedral.ts +170 -0
  900. package/src/render/shaders/octahedralResolve.ts +83 -0
  901. package/src/render/shaders/oitResolve.ts +42 -0
  902. package/src/render/shaders/outputTransform.ts +107 -0
  903. package/src/render/shaders/panel.ts +51 -0
  904. package/src/render/shaders/particle.ts +438 -0
  905. package/src/render/shaders/prefilter.ts +278 -0
  906. package/src/render/shaders/rush.ts +357 -0
  907. package/src/render/shaders/scatter.ts +211 -0
  908. package/src/render/shaders/sdfText.ts +68 -0
  909. package/src/render/shaders/skinning.ts +59 -0
  910. package/src/render/shaders/sky.ts +243 -0
  911. package/src/render/shaders/smoke.ts +89 -0
  912. package/src/render/shaders/ssrResolve.ts +28 -0
  913. package/src/render/shaders/ssrTrace.ts +233 -0
  914. package/src/render/shaders/tangentFrame.ts +70 -0
  915. package/src/render/shaders/temporalResolve.ts +151 -0
  916. package/src/render/shaders/text.ts +156 -0
  917. package/src/render/shaders/vertexChannel.ts +71 -0
  918. package/src/render/shaders/water.ts +356 -0
  919. package/src/render/shaders/windStreaks.ts +130 -0
  920. package/src/render/shadowCasters.ts +124 -0
  921. package/src/render/shadowMap.ts +89 -0
  922. package/src/render/shotPlacement.ts +266 -0
  923. package/src/render/skinPalette.ts +157 -0
  924. package/src/render/ssrPass.ts +241 -0
  925. package/src/render/surfaceSheet.ts +158 -0
  926. package/src/render/surfaceTexture.ts +310 -0
  927. package/src/render/temporalAa.ts +221 -0
  928. package/src/render/temporalPass.ts +153 -0
  929. package/src/render/textLayout.ts +239 -0
  930. package/src/render/textRenderer.ts +201 -0
  931. package/src/render/thirdPersonCamera.ts +578 -0
  932. package/src/render/trample.ts +140 -0
  933. package/src/render/translucentQueue.ts +161 -0
  934. package/src/render/uniformVectorBudget.ts +246 -0
  935. package/src/render/uploadStep.ts +14 -0
  936. package/src/render/vertexDefaults.ts +115 -0
  937. package/src/render/visibility.ts +56 -0
  938. package/src/render/waterDraw.ts +167 -0
  939. package/src/render/waterGrid.ts +180 -0
  940. package/src/render/waterRenderer.ts +352 -0
  941. package/src/render/wind.ts +79 -0
  942. package/src/render/windField.ts +50 -0
  943. package/src/render/windStreakDraw.ts +131 -0
  944. package/src/render/windStreakRenderer.ts +130 -0
  945. package/src/scene/node.ts +336 -0
  946. package/src/scene/visit.ts +82 -0
  947. package/src/ui/clipMime.ts +109 -0
  948. package/src/ui/exportTarget.ts +491 -0
  949. package/src/ui/frameOverlay.ts +159 -0
  950. package/src/ui/framePacer.ts +351 -0
  951. package/src/ui/frameRecorder.ts +333 -0
  952. package/src/ui/fullscreen.ts +113 -0
  953. package/src/ui/pixelCursor.ts +99 -0
  954. package/src/ui/splash.ts +347 -0
  955. package/src/ui/stillFrame.ts +44 -0
@@ -0,0 +1,1032 @@
1
+ import { glSceneDepthFormat } from './depthConvention.ts';
2
+ import { AmbientOcclusionPass } from './ambientOcclusionPass.ts';
3
+ import { BloomPass } from './bloomPass.ts';
4
+ import {
5
+ type ColourGradeLut,
6
+ GRADE_PLACEHOLDER_SIZE,
7
+ identityGradeLut,
8
+ validateGradeLut,
9
+ } from './colourGrade.ts';
10
+ import { compileProgram, uniformLocations } from './shader.ts';
11
+ import { TemporalPass } from './temporalPass.ts';
12
+ import { FULLSCREEN_VERT } from './shaders/fullscreen.ts';
13
+ import { RUSH_FRAG } from './shaders/rush.ts';
14
+ import type { Vec3 } from '../math/color.ts';
15
+
16
+ /** No veil, so a caller that omits the argument gets exactly the frame it always got. */
17
+ const NO_VEIL: Vec3 = [0, 0, 0];
18
+
19
+ /**
20
+ * An off-screen colour target for the frame, and the pass that resolves it to the canvas.
21
+ *
22
+ * The renderer drew straight to the canvas, which is the right default and is why this is
23
+ * opt-in: with nothing to sample a finished frame from, no screen-space effect can exist at
24
+ * all. A speed blur faked with a compositor filter over the canvas gets the boundary
25
+ * wrong in both directions: it is too strong, and it cannot leave the HUD alone. The
26
+ * effect belongs to the 3D scene, so the scene needs somewhere to land before it is shown.
27
+ *
28
+ * **It resolves to the canvas, always.** Two consumers depend on that and neither is
29
+ * optional: a frame recorder reads the canvas to build a clip, and a still is a canvas
30
+ * copy. Leaving the scene in a framebuffer would produce a black export while the screen
31
+ * looked correct, which is the worst shape a bug can have.
32
+ *
33
+ * Sized from the drawing buffer and rebuilt when that changes, so a resize, a DPR change
34
+ * and an export lock all land on an exactly-sized target rather than a stretched one. The
35
+ * depth buffer lives here too: a scene drawn into a colour attachment with the canvas's
36
+ * depth buffer would have no depth at all.
37
+ */
38
+ export class SceneTarget {
39
+ private framebuffer: WebGLFramebuffer | null = null;
40
+ private texture: WebGLTexture | null = null;
41
+ /**
42
+ * Depth as a *texture* rather than a renderbuffer, so the composite pass can read it.
43
+ *
44
+ * A renderbuffer is write-only from a shader's point of view, and every screen-space
45
+ * effect worth having needs the depth back: motion blur reconstructs a world position
46
+ * from it to reproject through the previous view, and ambient occlusion is nothing but
47
+ * depth compared against its neighbours. Costing the same memory and being sampleable,
48
+ * there is no reason for it to be anything else.
49
+ */
50
+ private depth: WebGLTexture | null = null;
51
+ /**
52
+ * A copy of the frame's depth taken mid-pass, for anything that must read it while drawing.
53
+ *
54
+ * **Not `depth` itself, and the distinction is the whole reason this exists.** `depth` is the
55
+ * attachment the frame is testing against, and sampling a texture that is attached to the
56
+ * bound framebuffer is undefined in WebGL2 — it draws something plausible on this driver and
57
+ * something else on the next. So a volume of light, which has to know where the opaque scene
58
+ * is in order to stop marching at it, reads this instead.
59
+ *
60
+ * Filled by `snapshotDepth`, on demand, and only in frames that ask.
61
+ */
62
+ private depthCopy: WebGLTexture | null = null;
63
+ private depthCopyFramebuffer: WebGLFramebuffer | null = null;
64
+ /** Whether this frame has filled it. One snapshot serves every volume in a frame. */
65
+ private depthCopyFilled = false;
66
+ /**
67
+ * The colour the frame had already drawn when something first asked for it.
68
+ *
69
+ * **A copy and never the attachment**, which is the difference `colorAttachment` documents from
70
+ * the other side: that one returns null while multisampling, because the frame lives in a
71
+ * renderbuffer until `resolve` blits into it. A blit from a multisampled source to a
72
+ * single-sampled destination *is* a resolve, so this answers in exactly the configuration where
73
+ * reading the attachment cannot.
74
+ *
75
+ * Filled by `snapshotColor`, on demand, and only in frames that ask.
76
+ */
77
+ private colorCopy: WebGLTexture | null = null;
78
+ private colorCopyFramebuffer: WebGLFramebuffer | null = null;
79
+ /** Whether this frame has filled it. One snapshot serves every refracting draw in a frame. */
80
+ private colorCopyFilled = false;
81
+ /**
82
+ * The colour grade, as a 3D texture on unit 4, and the table it was built from.
83
+ *
84
+ * **The source is kept to compare identities, not to read.** A grade is set every frame by a
85
+ * consumer that has one, and re-uploading a 32-lattice table is 131 kilobytes of `texImage3D`
86
+ * sixty times a second for bytes that did not change. Comparing the object is what makes
87
+ * `setColourGrade` free to call from a frame loop — and a consumer crossfading between two
88
+ * grades holds two objects, which compare unequal and upload once each on the swap.
89
+ */
90
+ private gradeTexture: WebGLTexture | null = null;
91
+ private gradeSource: ColourGradeLut | null = null;
92
+ private gradeSize = GRADE_PLACEHOLDER_SIZE;
93
+ private gradeStrength = 0;
94
+ private width = 0;
95
+ private height = 0;
96
+
97
+ /**
98
+ * The multisampled pair, present only when a caller asked for samples.
99
+ *
100
+ * Two framebuffers rather than one, because a multisampled attachment cannot be sampled
101
+ * by a shader: the scene is drawn into `msaaFramebuffer`, blitted down into the ordinary
102
+ * texture, and the post chain reads that exactly as it always has. Everything downstream
103
+ * of the blit is unchanged, which is what keeps this a quality option rather than a
104
+ * second rendering path.
105
+ */
106
+ private msaaFramebuffer: WebGLFramebuffer | null = null;
107
+ private msaaColor: WebGLRenderbuffer | null = null;
108
+ private msaaDepth: WebGLRenderbuffer | null = null;
109
+ /** What was actually allocated, after clamping to what the driver reports. */
110
+ private samples = 1;
111
+ /** Whether anything actually reads the resolved depth. Nothing is copied if not. */
112
+ private depthWanted = false;
113
+ /** Set once if the driver refuses the depth copy, so it is attempted once and not per frame. */
114
+ private depthBlitRefused = false;
115
+
116
+ private readonly program: WebGLProgram;
117
+ private readonly uniforms: Record<string, WebGLUniformLocation | null>;
118
+ private readonly vao: WebGLVertexArrayObject;
119
+ /**
120
+ * Built the first time a caller asks for occlusion, and never for one that does not.
121
+ *
122
+ * Two programs and two full-frame targets is not a thing to allocate on the chance somebody
123
+ * turns the option on later: the option is construction-time, so a renderer that was not
124
+ * asked for it will never be.
125
+ */
126
+ private ao: AmbientOcclusionPass | null = null;
127
+ /** Built the first time a caller asks for bloom, on the same terms as the occlusion pass. */
128
+ private bloom: BloomPass | null = null;
129
+ /** Built on the first frame that asks for it, like `bloom` beside it. */
130
+ private temporal: TemporalPass | null = null;
131
+ /** Whether the colour attachments hold half floats. See the constructor. */
132
+ private floatColor = false;
133
+
134
+ constructor(
135
+ private readonly gl: WebGL2RenderingContext,
136
+ requestedSamples = 1,
137
+ wantsRange = false,
138
+ /**
139
+ * Whether the multisampled buffers may be thrown away once blitted down.
140
+ *
141
+ * True is correct and saves a full attachment write per frame on a tiler. It is a switch
142
+ * because, like WebGPU's `storeOp: 'discard'`, it is invisible on an immediate-mode desktop
143
+ * part and therefore cannot be verified by a screenshot: see
144
+ * `RenderQuality.discardResolvedAttachments`.
145
+ */
146
+ private readonly discardResolved = true,
147
+ ) {
148
+ /*
149
+ * Clamped to MAX_SAMPLES rather than trusted. Asking for more than the part supports
150
+ * produces a framebuffer that never completes, and an incomplete framebuffer is a black
151
+ * frame with no GL error attached to explain it.
152
+ */
153
+ const maximum = gl.getParameter(gl.MAX_SAMPLES) as number;
154
+ this.samples = Math.max(
155
+ 1,
156
+ Math.min(Math.round(requestedSamples), Number.isFinite(maximum) ? maximum : 1),
157
+ );
158
+
159
+ /*
160
+ * A float colour target where the part will render to one, and eight bits where it will not.
161
+ *
162
+ * **The reason it matters is what a composite can still tell apart.** With an eight-bit
163
+ * target the scene has already been squashed into 0 to 1 by the time anything downstream
164
+ * looks at it, so a star at five times white and a sheet of white paper arrive identical and
165
+ * nothing can treat them differently. Half floats keep the difference, which is what makes a
166
+ * bloom threshold mean brightness rather than mean whiteness, and it is why the tone curve
167
+ * moved from the mesh pass to the resolve: a curve applied before the buffer throws away the
168
+ * range the buffer exists to keep.
169
+ *
170
+ * `EXT_color_buffer_float` is required for this in WebGL2 and is absent on some parts, so it
171
+ * is asked for rather than assumed. Without it the target stays eight-bit and everything
172
+ * still draws: values clip where they always clipped.
173
+ */
174
+ this.floatColor = wantsRange && gl.getExtension('EXT_color_buffer_float') !== null;
175
+
176
+ this.program = compileProgram(gl, FULLSCREEN_VERT, RUSH_FRAG, 'rush');
177
+ this.uniforms = uniformLocations(gl, this.program, 'sceneTarget');
178
+ /*
179
+ * A VAO with no attributes: the fullscreen triangle is built from `gl_VertexID`, so
180
+ * there is nothing to bind. WebGL2 still requires *a* vertex array to be bound for a
181
+ * draw, and binding one with no state is cheaper than leaving whatever the previous
182
+ * pass left attached.
183
+ */
184
+ const vao = gl.createVertexArray();
185
+ if (vao === null) throw new Error('SceneTarget: createVertexArray failed');
186
+ this.vao = vao;
187
+ }
188
+
189
+ /** Match the target to the drawing buffer. Cheap when unchanged. */
190
+ private ensureSize(width: number, height: number): void {
191
+ if (this.width === width && this.height === height && this.framebuffer !== null) return;
192
+ const { gl } = this;
193
+ this.width = width;
194
+ this.height = height;
195
+
196
+ if (this.texture === null) this.texture = gl.createTexture();
197
+ gl.bindTexture(gl.TEXTURE_2D, this.texture);
198
+ if (this.floatColor) {
199
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
200
+ } else {
201
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
202
+ }
203
+ // Linear, because the blur samples between texels; clamped, because a tap that
204
+ // wrapped would pull the opposite edge of the screen into the corner.
205
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
206
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
207
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
208
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
209
+
210
+ const sceneDepth = glSceneDepthFormat(gl);
211
+ if (this.depth === null) this.depth = gl.createTexture();
212
+ gl.bindTexture(gl.TEXTURE_2D, this.depth);
213
+ gl.texImage2D(
214
+ gl.TEXTURE_2D,
215
+ 0,
216
+ sceneDepth.internalFormat,
217
+ width,
218
+ height,
219
+ 0,
220
+ gl.DEPTH_COMPONENT,
221
+ sceneDepth.type,
222
+ null,
223
+ );
224
+ /* NEAREST, and not a preference: a depth texture with no compare mode cannot be
225
+ linearly filtered, and asking for it makes the sample come back undefined. */
226
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
227
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
228
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
229
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
230
+
231
+ /* The mid-pass copy, same format as the depth it is blitted from — `blitFramebuffer`
232
+ refuses a depth copy between formats that do not match exactly. See `depthCopy`. */
233
+ if (this.depthCopy === null) this.depthCopy = gl.createTexture();
234
+ gl.bindTexture(gl.TEXTURE_2D, this.depthCopy);
235
+ gl.texImage2D(
236
+ gl.TEXTURE_2D,
237
+ 0,
238
+ sceneDepth.internalFormat,
239
+ width,
240
+ height,
241
+ 0,
242
+ gl.DEPTH_COMPONENT,
243
+ sceneDepth.type,
244
+ null,
245
+ );
246
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
247
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
248
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
249
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
250
+
251
+ /*
252
+ * The colour copy, and its format follows the scene texture exactly.
253
+ *
254
+ * **`blitFramebuffer` refuses a copy between formats that do not match**, which is the same
255
+ * constraint the depth copy above is built under — so an HDR profile copies `RGBA16F` and an
256
+ * LDR one `RGBA8`, chosen by the flag the scene texture itself reads.
257
+ *
258
+ * `LINEAR` filtering, because a refracting draw samples at an offset that lands between
259
+ * texels; `CLAMP_TO_EDGE`, because a sample that wrapped would pull the opposite edge of the
260
+ * screen into a pane at the frame's border, which reads as a tear.
261
+ */
262
+ if (this.colorCopy === null) this.colorCopy = gl.createTexture();
263
+ gl.bindTexture(gl.TEXTURE_2D, this.colorCopy);
264
+ if (this.floatColor) {
265
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
266
+ } else {
267
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
268
+ }
269
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
270
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
271
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
272
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
273
+
274
+ /*
275
+ * Colour only, and no depth attachment at all — the mirror image of the depth copy below,
276
+ * which attaches depth and switches the colour buffers off by name. **They are kept apart
277
+ * deliberately**: this file records a combined colour-and-depth blit losing the colour
278
+ * because the driver disliked the depth, and the depth-only path losing the depth for a
279
+ * missing colour target. One blit, one buffer bit, each time.
280
+ */
281
+ if (this.colorCopyFramebuffer === null) this.colorCopyFramebuffer = gl.createFramebuffer();
282
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.colorCopyFramebuffer);
283
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.colorCopy, 0);
284
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
285
+ /* Loud, once, at allocation. A refracting draw then shades as an ordinary translucent one
286
+ and says why, rather than quietly disagreeing with the other backend. */
287
+ console.warn(
288
+ 'SceneTarget: this driver will not give a colour-only framebuffer, so a refracting ' +
289
+ 'surface cannot read the scene behind it and will draw as ordinary glass.',
290
+ );
291
+ gl.deleteFramebuffer(this.colorCopyFramebuffer);
292
+ this.colorCopyFramebuffer = null;
293
+ }
294
+
295
+ if (this.depthCopyFramebuffer === null) this.depthCopyFramebuffer = gl.createFramebuffer();
296
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.depthCopyFramebuffer);
297
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depthCopy, 0);
298
+ /*
299
+ * **Depth only, and the colour buffers have to be switched off by name.**
300
+ *
301
+ * A framebuffer with a depth attachment and no colour one still advertises
302
+ * `COLOR_ATTACHMENT0` as its draw and read buffer, and a `blitFramebuffer` into it is
303
+ * refused for the missing colour target — taking the depth half of the copy with it, since
304
+ * the call fails whole. `resolve` documents the same trap from the other direction, where a
305
+ * combined colour+depth blit lost the colour because the driver disliked the depth.
306
+ *
307
+ * Without these two lines the copy silently never happened: `snapshotDepth` returned null,
308
+ * `uSceneDepthEnabled` stayed 0, and WebGL2 kept marching through the floor while WebGPU
309
+ * clamped. Two backends doing different things with nothing said about it, which is the
310
+ * 2026-08-13 rule exactly — and it was found from a capture pair whose only disagreement
311
+ * was the band of floor the clamp acts on.
312
+ */
313
+ gl.drawBuffers([gl.NONE]);
314
+ gl.readBuffer(gl.NONE);
315
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
316
+ /* Loud, once, at allocation. A volume then draws unclamped on this driver and says why,
317
+ rather than quietly disagreeing with the other backend. */
318
+ console.warn(
319
+ 'SceneTarget: this driver will not give a depth-only framebuffer, so light volumes ' +
320
+ 'cannot clamp to the scene and will march through it. The frame is unaffected.',
321
+ );
322
+ gl.deleteFramebuffer(this.depthCopyFramebuffer);
323
+ this.depthCopyFramebuffer = null;
324
+ }
325
+
326
+ if (this.framebuffer === null) this.framebuffer = gl.createFramebuffer();
327
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
328
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
329
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.depth, 0);
330
+
331
+ if (this.samples > 1) {
332
+ if (this.msaaColor === null) this.msaaColor = gl.createRenderbuffer();
333
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.msaaColor);
334
+ gl.renderbufferStorageMultisample(
335
+ gl.RENDERBUFFER,
336
+ this.samples,
337
+ this.floatColor ? gl.RGBA16F : gl.RGBA8,
338
+ width,
339
+ height,
340
+ );
341
+
342
+ if (this.msaaDepth === null) this.msaaDepth = gl.createRenderbuffer();
343
+ gl.bindRenderbuffer(gl.RENDERBUFFER, this.msaaDepth);
344
+ /*
345
+ * **Must match the resolve target's format exactly**, or `blitFramebuffer` refuses the depth
346
+ * half of the copy — so it follows the same convention the depth texture does rather than
347
+ * naming a format of its own. It said 24-bit here for as long as the texture was 24-bit;
348
+ * making the texture float and leaving this behind produced
349
+ * `GL_INVALID_OPERATION: glBlitFramebuffer: Depth/stencil buffer format combination not
350
+ * allowed for blit` on every scene with MSAA, which is what the pixel gate reported first.
351
+ */
352
+ gl.renderbufferStorageMultisample(
353
+ gl.RENDERBUFFER,
354
+ this.samples,
355
+ glSceneDepthFormat(gl).internalFormat,
356
+ width,
357
+ height,
358
+ );
359
+
360
+ if (this.msaaFramebuffer === null) this.msaaFramebuffer = gl.createFramebuffer();
361
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.msaaFramebuffer);
362
+ gl.framebufferRenderbuffer(
363
+ gl.FRAMEBUFFER,
364
+ gl.COLOR_ATTACHMENT0,
365
+ gl.RENDERBUFFER,
366
+ this.msaaColor,
367
+ );
368
+ gl.framebufferRenderbuffer(
369
+ gl.FRAMEBUFFER,
370
+ gl.DEPTH_ATTACHMENT,
371
+ gl.RENDERBUFFER,
372
+ this.msaaDepth,
373
+ );
374
+
375
+ /*
376
+ * Checked here rather than discovered as a black frame. A multisampled attachment can
377
+ * be refused for a combination the driver does not support even after the sample count
378
+ * was clamped, and the honest response is to fall back to no multisampling and carry
379
+ * on drawing, rather than to render nothing.
380
+ */
381
+ if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
382
+ this.releaseMultisample();
383
+ this.samples = 1;
384
+ }
385
+ }
386
+
387
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
388
+ gl.bindTexture(gl.TEXTURE_2D, null);
389
+ gl.bindRenderbuffer(gl.RENDERBUFFER, null);
390
+ }
391
+
392
+ private releaseMultisample(): void {
393
+ const { gl } = this;
394
+ if (this.msaaFramebuffer !== null) gl.deleteFramebuffer(this.msaaFramebuffer);
395
+ if (this.msaaColor !== null) gl.deleteRenderbuffer(this.msaaColor);
396
+ if (this.msaaDepth !== null) gl.deleteRenderbuffer(this.msaaDepth);
397
+ this.msaaFramebuffer = null;
398
+ this.msaaColor = null;
399
+ this.msaaDepth = null;
400
+ }
401
+
402
+ /** Bind the off-screen target for a frame. The caller clears as it normally would. */
403
+ begin(width: number, height: number): void {
404
+ this.ensureSize(width, height);
405
+ /* Last frame's snapshot is last frame's scene. See `snapshotDepth`. */
406
+ this.depthCopyFilled = false;
407
+ this.colorCopyFilled = false;
408
+ this.bind();
409
+ }
410
+
411
+ /**
412
+ * Point drawing back at this target, at its own size.
413
+ *
414
+ * Needed because every borrowing pass — the shadow maps, the planar reflection — hands
415
+ * the framebuffer back by binding `null`, which is the *canvas*, not the frame's target.
416
+ * Without somewhere to come back to, everything drawn after a reflection would land on
417
+ * the canvas and then be overwritten by the resolve of a half-empty target: a black
418
+ * frame from a renderer that looked correct in isolation.
419
+ */
420
+ bind(): void {
421
+ const { gl } = this;
422
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.msaaFramebuffer ?? this.framebuffer);
423
+ gl.viewport(0, 0, this.width, this.height);
424
+ }
425
+
426
+ /**
427
+ * Whether this target keeps values above 1, which decides where the tone curve belongs.
428
+ *
429
+ * False on a part without `EXT_color_buffer_float`, where the scene is squashed into 0 to 1 on
430
+ * the way in exactly as it always was.
431
+ */
432
+ get keepsRange(): boolean {
433
+ return this.floatColor;
434
+ }
435
+
436
+ /** How many samples the scene is actually being drawn with. 1 means no multisampling. */
437
+ get sampleCount(): number {
438
+ return this.samples;
439
+ }
440
+
441
+ /** The frame's depth, resolved and sampleable, for screen-space effects that need it. */
442
+ get depthTexture(): WebGLTexture | null {
443
+ return this.depth;
444
+ }
445
+
446
+ /**
447
+ * Copy the depth drawn so far, so something still drawing can read it. Returns what to bind.
448
+ *
449
+ * **Once per frame however many callers ask**, because they all want the same thing: where
450
+ * the opaque scene is. `begin` clears the latch.
451
+ *
452
+ * The blit is from whichever framebuffer the frame is actually rendering into — the
453
+ * multisampled one where there is one — and it restores that binding afterwards, because the
454
+ * caller is in the middle of a pass and expects to carry on drawing into it. Forgetting that
455
+ * is a frame that finishes into the wrong target and comes out empty.
456
+ *
457
+ * Null where the copy could not be made, and the caller must read that as "no clamp" rather
458
+ * than as a texture full of zeros — a depth of zero is the near plane, which would clamp every
459
+ * march to nothing and delete every beam in the scene.
460
+ */
461
+ /**
462
+ * The depth the frame is testing against, for a pass that must test against it too.
463
+ *
464
+ * **Not `snapshotDepth`, and the difference matters.** That returns a *copy*, for a pass that
465
+ * samples depth while the attachment is bound; this is the attachment itself, for a pass that
466
+ * attaches it and depth-tests against it without writing. Order-independent transparency needs
467
+ * the second: its two passes reject a pane behind a wall exactly where the wall is, and both
468
+ * must reject it in the same place or the accumulation and the revealage cover different
469
+ * fragments.
470
+ */
471
+ depthAttachment(): WebGLTexture | null {
472
+ return this.depth;
473
+ }
474
+
475
+ /**
476
+ * The colour the frame has drawn so far, for a pass that reads the picture rather than the depth.
477
+ *
478
+ * **Null while multisampling, and that is the honest answer rather than a missing feature.** With
479
+ * samples above one the frame is drawn into a renderbuffer and this texture holds nothing until
480
+ * `resolve` blits into it — so a pass running mid-frame would read the frame before last. A
481
+ * caller that needs the finished picture in the middle of the frame is asking for something a
482
+ * multisampled attachment cannot give without a resolve of its own.
483
+ */
484
+ colorAttachment(): WebGLTexture | null {
485
+ return this.msaaFramebuffer === null ? this.texture : null;
486
+ }
487
+
488
+ /**
489
+ * The colour the frame has drawn so far, copied so a draw can sample it while still drawing.
490
+ *
491
+ * **A copy and never the attachment.** Sampling a texture attached to the bound framebuffer is
492
+ * undefined in WebGL2 — it draws something plausible on this driver and something else on the
493
+ * next — and `colorAttachment` returns null under multisampling anyway. A blit answers both:
494
+ * it detaches the read, and from a multisampled source it resolves.
495
+ *
496
+ * **Latched, and the latch is the same trap `snapshotDepth` documents.** One copy serves every
497
+ * refracting draw in a frame, so glass does not refract other glass — which is correct, a pane
498
+ * behind a pane should show the room. What it also means is that opaque geometry drawn *after*
499
+ * the first refracting draw is missing from what a pane shows. Draw the world, then the glass;
500
+ * a caller that must have the later geometry asks `afresh` and pays another blit.
501
+ *
502
+ * Null where the copy could not be made, and a caller must read that as "do not refract" rather
503
+ * than as a black texture — refracting against black paints every pane the colour of a hole.
504
+ */
505
+ snapshotColor(afresh = false): WebGLTexture | null {
506
+ if (this.colorCopy === null || this.colorCopyFramebuffer === null) return null;
507
+ if (this.colorCopyFilled && !afresh) return this.colorCopy;
508
+ const { gl } = this;
509
+ const source = this.msaaFramebuffer ?? this.framebuffer;
510
+ if (source === null) return null;
511
+
512
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, source);
513
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.colorCopyFramebuffer);
514
+ /* Drained first, for the reason `resolve` gives at length: `getError` reports whatever is
515
+ pending from anywhere, so a check that does not start clean blames this call for somebody
516
+ else's mistake — and did, once, permanently disabling an effect. */
517
+ while (gl.getError() !== gl.NO_ERROR) {
518
+ /* discard whatever was already pending */
519
+ }
520
+ /* `NEAREST` because the rectangles are the same size, so there is nothing to filter and the
521
+ choice only decides which refusals are possible. */
522
+ gl.blitFramebuffer(
523
+ 0,
524
+ 0,
525
+ this.width,
526
+ this.height,
527
+ 0,
528
+ 0,
529
+ this.width,
530
+ this.height,
531
+ gl.COLOR_BUFFER_BIT,
532
+ gl.NEAREST,
533
+ );
534
+ const refused = gl.getError() !== gl.NO_ERROR;
535
+ /* Back to what the caller was drawing into, whichever that was. */
536
+ gl.bindFramebuffer(gl.FRAMEBUFFER, source);
537
+ if (refused) return null;
538
+ this.colorCopyFilled = true;
539
+ return this.colorCopy;
540
+ }
541
+
542
+ snapshotDepth(
543
+ /**
544
+ * Take the copy again even though one has already been taken this frame.
545
+ *
546
+ * **The latch that makes this cheap is also the trap in it.** A beam asks for the depth in
547
+ * the middle of the frame, so the copy holds the world *as it stood then* — and a pass that
548
+ * runs once every draw is in and reuses that copy marks a scene missing everything drawn
549
+ * after the beam. The symptom is a decal landing on a wall that is no longer the nearest
550
+ * thing, which reads as a depth-test bug rather than as a stale texture.
551
+ *
552
+ * So a caller at the end of the frame asks for it afresh, and pays one more blit on the
553
+ * frames where something had already asked. `begin` clears the latch either way.
554
+ */
555
+ afresh = false,
556
+ ): WebGLTexture | null {
557
+ if (this.depthCopy === null || this.depthCopyFramebuffer === null) return null;
558
+ if (this.depthCopyFilled && !afresh) return this.depthCopy;
559
+ const { gl } = this;
560
+ const source = this.msaaFramebuffer ?? this.framebuffer;
561
+ if (source === null) return null;
562
+
563
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, source);
564
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.depthCopyFramebuffer);
565
+ /* Drained first, for the reason `resolve` gives at length: `getError` reports whatever is
566
+ pending from anywhere, so a check that does not start clean blames this call for
567
+ somebody else's mistake — and did, once, permanently disabling an effect. */
568
+ while (gl.getError() !== gl.NO_ERROR) {
569
+ /* discard whatever was already pending */
570
+ }
571
+ gl.blitFramebuffer(
572
+ 0,
573
+ 0,
574
+ this.width,
575
+ this.height,
576
+ 0,
577
+ 0,
578
+ this.width,
579
+ this.height,
580
+ gl.DEPTH_BUFFER_BIT,
581
+ gl.NEAREST,
582
+ );
583
+ const refused = gl.getError() !== gl.NO_ERROR;
584
+ /* Back to what the caller was drawing into, whichever that was. */
585
+ gl.bindFramebuffer(gl.FRAMEBUFFER, source);
586
+ if (refused) return null;
587
+ this.depthCopyFilled = true;
588
+ return this.depthCopy;
589
+ }
590
+
591
+ /**
592
+ * Resolve the scene to the canvas, blurred by `strength`.
593
+ *
594
+ * Depth and blending are explicitly off for the pass: it is one opaque triangle over the
595
+ * whole viewport, and inheriting a depth test from the last scene draw would let it fail
596
+ * against nothing.
597
+ */
598
+ /**
599
+ * The colour grade this and every later frame applies, until it is set again.
600
+ *
601
+ * **Held rather than passed to `resolve`**, because a lookup table is a *texture* and every
602
+ * other texture this pass reads is owned here. The alternative is a ninth parameter on a call
603
+ * that already takes eight, carrying an object the caller would then have to keep stable
604
+ * anyway.
605
+ *
606
+ * `null`, or a strength at or below zero, is exactly the frame that existed before the effect
607
+ * did: the shader's branch is on a uniform, so no fetch happens at all.
608
+ */
609
+ setColourGrade(lut: ColourGradeLut | null, strength: number): void {
610
+ this.gradeStrength = lut === null ? 0 : Math.max(0, Math.min(1, strength));
611
+ if (lut === null || lut === this.gradeSource) return;
612
+ validateGradeLut(lut);
613
+ this.uploadGrade(lut);
614
+ this.gradeSource = lut;
615
+ }
616
+
617
+ /**
618
+ * Put a table on the device, replacing whatever was there.
619
+ *
620
+ * `RGBA8` with `LINEAR` in every direction and `CLAMP_TO_EDGE` on all three axes. The filtering
621
+ * is the whole point — an unfiltered 32-lattice table bands, which is the one artefact a grade
622
+ * must never introduce — and the clamp is what makes the texel-centre coordinate safe at the
623
+ * ends of the range rather than wrapping black round to white.
624
+ */
625
+ private uploadGrade(lut: ColourGradeLut): void {
626
+ const { gl } = this;
627
+ this.gradeTexture ??= gl.createTexture();
628
+ gl.activeTexture(gl.TEXTURE4);
629
+ gl.bindTexture(gl.TEXTURE_3D, this.gradeTexture);
630
+ gl.texImage3D(
631
+ gl.TEXTURE_3D,
632
+ 0,
633
+ gl.RGBA8,
634
+ lut.size,
635
+ lut.size,
636
+ lut.size,
637
+ 0,
638
+ gl.RGBA,
639
+ gl.UNSIGNED_BYTE,
640
+ lut.data,
641
+ );
642
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
643
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
644
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
645
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
646
+ gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
647
+ gl.activeTexture(gl.TEXTURE0);
648
+ this.gradeSize = lut.size;
649
+ }
650
+
651
+ resolve(
652
+ strength: number,
653
+ reachUv: number,
654
+ /* The grade, applied here because this is the last pass. See RUSH_FRAG's own note. */
655
+ grade: { readonly transform: number; readonly exposure: number } = {
656
+ transform: 0,
657
+ exposure: 1,
658
+ },
659
+ motion?: {
660
+ readonly reprojection: Float32Array;
661
+ readonly strength: number;
662
+ readonly max: number;
663
+ },
664
+ ao?: {
665
+ readonly strength: number;
666
+ readonly radius: number;
667
+ /** The projection's x and y scales, which turn a world radius into a screen one. */
668
+ readonly projScale: Float32Array;
669
+ readonly invProjection: Float32Array;
670
+ },
671
+ bloom?: {
672
+ readonly strength: number;
673
+ /** In scene units, which is why this wants `keepsRange`. See `BloomPass`. */
674
+ readonly threshold: number;
675
+ },
676
+ /*
677
+ * Depth of field, between the camera smear and the occlusion in the shader's own order. Like
678
+ * `motion` and `ao` it needs the depth, and like them it is absent rather than zeroed when the
679
+ * frame has not asked — so a renderer nobody asked for it never resolves a depth buffer to
680
+ * feed it.
681
+ */
682
+ dof?: {
683
+ /** Where the lens is focused, in metres. */
684
+ readonly distance: number;
685
+ /** How many metres either side of that stay sharp. */
686
+ readonly range: number;
687
+ /** How far the blur may reach, as a fraction of the frame's height. */
688
+ readonly strength: number;
689
+ /** `(m[10], m[14], m[11], m[15])` of the inverse projection. See `uDepthToView`. */
690
+ readonly depthToView: Float32Array;
691
+ },
692
+ /*
693
+ * The frame veil, composited last of everything this pass does. See
694
+ * `Renderer.setFrameVeil` for why it sits here rather than upstream or downstream of the
695
+ * grade. Defaulted rather than optional: the shader always reads both uniforms, so a
696
+ * caller that never veils anything uploads the same two numbers it always would have.
697
+ */
698
+ veilColor: Vec3 = NO_VEIL,
699
+ veilAlpha = 0,
700
+ /*
701
+ * The temporal resolve, appended rather than placed beside the other effects because
702
+ * `veilColor` and `veilAlpha` are positional defaults and every existing caller passes them
703
+ * by position.
704
+ */
705
+ temporal?: { readonly reprojection: Float32Array; readonly blend: number },
706
+ ): void {
707
+ const { gl } = this;
708
+ this.depthWanted =
709
+ motion !== undefined || ao !== undefined || dof !== undefined || temporal !== undefined;
710
+ /*
711
+ * Down from the multisampled buffer into the texture first, because a shader cannot
712
+ * sample a multisampled attachment. NEAREST is the only filter `blitFramebuffer` accepts
713
+ * for a same-size resolve, and the two are the same size by construction.
714
+ */
715
+ if (this.msaaFramebuffer !== null) {
716
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.msaaFramebuffer);
717
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.framebuffer);
718
+ /*
719
+ * **Colour on its own, always, and depth as a separate call that is allowed to fail.**
720
+ *
721
+ * These were one blit with both bits set, and that shipped a black game. A driver may
722
+ * refuse a depth copy for a format combination it does not like, and `blitFramebuffer`
723
+ * refuses the *whole* call when it does — so a disagreement about depth took the
724
+ * colour with it and the frame resolved to nothing. The symptom is total and the cause
725
+ * is a flag in a bitmask.
726
+ *
727
+ * Split, the worst case is losing the effect that wanted depth. The frame is never at
728
+ * risk, which is the only acceptable ordering: this method's contract is that the scene
729
+ * reaches the canvas.
730
+ */
731
+ gl.blitFramebuffer(
732
+ 0,
733
+ 0,
734
+ this.width,
735
+ this.height,
736
+ 0,
737
+ 0,
738
+ this.width,
739
+ this.height,
740
+ gl.COLOR_BUFFER_BIT,
741
+ gl.NEAREST,
742
+ );
743
+ if (this.depthWanted && !this.depthBlitRefused) {
744
+ /*
745
+ * Drained first, and this is not defensive tidiness. `getError` returns whatever
746
+ * error is *pending*, from anywhere, and clears it — so a check that does not start
747
+ * from a clean queue attributes somebody else's mistake to this call. That happened
748
+ * here immediately: an unrelated error elsewhere in the frame was read as the driver
749
+ * refusing depth, which switched motion blur off permanently and silently.
750
+ */
751
+ while (gl.getError() !== gl.NO_ERROR) {
752
+ /* discard whatever was already pending */
753
+ }
754
+ gl.blitFramebuffer(
755
+ 0,
756
+ 0,
757
+ this.width,
758
+ this.height,
759
+ 0,
760
+ 0,
761
+ this.width,
762
+ this.height,
763
+ gl.DEPTH_BUFFER_BIT,
764
+ gl.NEAREST,
765
+ );
766
+ /*
767
+ * Asked once rather than every frame: `getError` is a synchronisation point, and a
768
+ * format combination that was refused on the first frame will be refused on every
769
+ * one. After that the effect that wanted depth simply does not run.
770
+ */
771
+ if (gl.getError() !== gl.NO_ERROR) {
772
+ this.depthBlitRefused = true;
773
+ console.warn(
774
+ 'SceneTarget: this driver will not resolve multisampled depth, so effects that ' +
775
+ 'read it are off. The frame itself is unaffected.',
776
+ );
777
+ }
778
+ }
779
+ /*
780
+ * **Thrown away the moment they have been blitted down, which is WebGL2's half of the
781
+ * same statement `storeOp: 'discard'` makes on the other backend.**
782
+ *
783
+ * The blit above is the resolve, and on its own it is only half of one: the multisampled
784
+ * renderbuffers still hold contents the driver has no reason to believe are finished
785
+ * with, so a tile-based GPU dutifully writes all four samples out to memory at the end of
786
+ * the pass. Nothing can ever read them — a multisampled renderbuffer cannot be sampled by
787
+ * a shader at all, which is the entire reason this blit exists — so the write buys
788
+ * nothing and costs a full attachment.
789
+ *
790
+ * Measured on the WebGPU side of the same frame at 824x1830 with four samples: 23 MB per
791
+ * attachment, and the game keeps two of them. On a desktop part it is invisible, which is
792
+ * why it survived; on a phone it is a share of the memory bandwidth the frame has.
793
+ *
794
+ * **Before the unbind, deliberately.** `invalidateFramebuffer` acts on whatever is bound
795
+ * to the target it is given, so moving these two lines below the ones that follow would
796
+ * discard the default framebuffer instead — which is the frame.
797
+ */
798
+ if (this.discardResolved) {
799
+ gl.invalidateFramebuffer(gl.READ_FRAMEBUFFER, [gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT]);
800
+ }
801
+ gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
802
+ gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
803
+ }
804
+ /*
805
+ * Occlusion before the composite, because the composite consumes it, and after the
806
+ * resolve above, because it reads the depth that resolve produced. It leaves the
807
+ * framebuffer unbound and the viewport its own, both of which the composite sets again
808
+ * below.
809
+ */
810
+ let aoTexture: WebGLTexture | null = null;
811
+ if (ao !== undefined && !this.depthBlitRefused && this.depth !== null) {
812
+ this.ao ??= new AmbientOcclusionPass(gl);
813
+ aoTexture = this.ao.run(
814
+ this.depth,
815
+ this.width,
816
+ this.height,
817
+ ao.radius,
818
+ ao.projScale,
819
+ ao.invProjection,
820
+ );
821
+ }
822
+
823
+ /*
824
+ * Bloom beside occlusion rather than after the composite, because the composite is what
825
+ * consumes it. It reads the resolved colour rather than the depth, so it is independent of
826
+ * the blit above having produced anything, and it leaves the framebuffer unbound and the
827
+ * viewport its own — both of which the composite sets again below.
828
+ */
829
+ /*
830
+ * **The temporal resolve happens before all of it**, and what it returns is what everything
831
+ * below must treat as the scene. Bloom, occlusion and the grade each read the scene texture,
832
+ * and reading the unresolved one would put the crawl the resolve just removed back on screen
833
+ * through the bloom — a stable picture lit by an unstable one.
834
+ */
835
+ let scene = this.texture;
836
+ if (temporal !== undefined && this.texture !== null && this.depth !== null) {
837
+ this.temporal ??= new TemporalPass(gl, this.floatColor);
838
+ scene = this.temporal.temporalResolve(
839
+ this.texture,
840
+ this.depth,
841
+ temporal.reprojection,
842
+ this.width,
843
+ this.height,
844
+ temporal.blend,
845
+ );
846
+ }
847
+
848
+ let bloomTexture: WebGLTexture | null = null;
849
+ if (bloom !== undefined && scene !== null) {
850
+ this.bloom ??= new BloomPass(gl);
851
+ bloomTexture = this.bloom.run(scene, this.width, this.height, bloom.threshold);
852
+ }
853
+
854
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
855
+ gl.viewport(0, 0, this.width, this.height);
856
+ gl.disable(gl.DEPTH_TEST);
857
+ gl.disable(gl.BLEND);
858
+ gl.disable(gl.CULL_FACE);
859
+ gl.depthMask(false);
860
+
861
+ gl.useProgram(this.program);
862
+ gl.activeTexture(gl.TEXTURE0);
863
+ gl.bindTexture(gl.TEXTURE_2D, scene);
864
+ gl.uniform1i(this.uniforms['uScene'] ?? null, 0);
865
+ gl.uniform1f(this.uniforms['uStrength'] ?? null, strength);
866
+ gl.uniform1f(this.uniforms['uReach'] ?? null, reachUv);
867
+ gl.uniform1i(this.uniforms['uOutputTransform'] ?? null, grade.transform);
868
+ gl.uniform1f(this.uniforms['uOutputExposure'] ?? null, grade.exposure);
869
+
870
+ /*
871
+ * Depth on its own unit, and the reprojection with it. Bound every frame rather than
872
+ * once, because a texture unit is context state and any pass between two frames is free
873
+ * to have left something else there.
874
+ */
875
+ gl.activeTexture(gl.TEXTURE1);
876
+ gl.bindTexture(gl.TEXTURE_2D, this.depth);
877
+ gl.uniform1i(this.uniforms['uDepth'] ?? null, 1);
878
+ /* Off if the driver would not give the depth back, so the shader never samples a
879
+ texture that holds whatever was in it before. */
880
+ const motionUsable = motion !== undefined && !this.depthBlitRefused;
881
+ gl.uniform1f(this.uniforms['uMotionStrength'] ?? null, motionUsable ? motion.strength : 0);
882
+ gl.uniform1f(this.uniforms['uMotionMax'] ?? null, motion?.max ?? 0);
883
+ if (motionUsable) {
884
+ gl.uniformMatrix4fv(this.uniforms['uReprojection'] ?? null, false, motion.reprojection);
885
+ }
886
+ /*
887
+ * Depth of field, on the depth unit bound just above and gated on the same refusal: a driver
888
+ * that would not give the depth back leaves that texture holding a previous frame, and a
889
+ * circle of confusion computed from it defocuses the wrong half of the picture.
890
+ */
891
+ const dofUsable = dof !== undefined && !this.depthBlitRefused;
892
+ gl.uniform1f(this.uniforms['uDofStrength'] ?? null, dofUsable ? dof.strength : 0);
893
+ if (dofUsable) {
894
+ gl.uniform1f(this.uniforms['uFocusDistance'] ?? null, dof.distance);
895
+ gl.uniform1f(this.uniforms['uFocusRange'] ?? null, dof.range);
896
+ /* Height over width, so a radius in fractions of the height is a circle on screen. */
897
+ gl.uniform2f(this.uniforms['uDofAspect'] ?? null, this.height / this.width, 1);
898
+ gl.uniform4fv(this.uniforms['uDepthToView'] ?? null, dof.depthToView);
899
+ }
900
+
901
+ /*
902
+ * Ambient occlusion on its own unit, gated on the same fact as the blur and for the same
903
+ * reason: a refused depth resolve leaves that texture holding whatever a previous frame
904
+ * put there, and occlusion measured from it is not a degraded picture but a pattern of
905
+ * dirt with no relationship to the scene. The pass may also decline for itself, which
906
+ * arrives here as a null texture. Either way the strength goes to zero, which is exactly
907
+ * the frame that existed before the effect did.
908
+ *
909
+ * The placeholder rather than an unbound unit when it is off: an incomplete texture is
910
+ * something a driver may fetch the descriptor for before it evaluates the branch that
911
+ * would have skipped the read.
912
+ */
913
+ gl.activeTexture(gl.TEXTURE2);
914
+ gl.bindTexture(gl.TEXTURE_2D, aoTexture ?? scene);
915
+ gl.uniform1i(this.uniforms['uAo'] ?? null, 2);
916
+ gl.uniform1f(
917
+ this.uniforms['uAoStrength'] ?? null,
918
+ aoTexture === null ? 0 : (ao?.strength ?? 0),
919
+ );
920
+
921
+ /* Bloom on its own unit, and the placeholder for the same reason as the one above: a
922
+ driver may fetch a texture's descriptor before it evaluates the branch that skips the
923
+ read, and an incomplete texture is not a thing to hand it. */
924
+ gl.activeTexture(gl.TEXTURE3);
925
+ gl.bindTexture(gl.TEXTURE_2D, bloomTexture ?? scene);
926
+ gl.uniform1i(this.uniforms['uBloom'] ?? null, 3);
927
+ gl.uniform1f(
928
+ this.uniforms['uBloomStrength'] ?? null,
929
+ bloomTexture === null ? 0 : (bloom?.strength ?? 0),
930
+ );
931
+
932
+ /*
933
+ * The grade on unit 4, and the placeholder built here rather than at construction: a frame
934
+ * that never grades anything should not carry a texture, and a sampler declared in the
935
+ * program must still have a complete one bound whether or not the branch reads it — the
936
+ * argument the occlusion and bloom placeholders above make, one dimension up.
937
+ *
938
+ * The placeholder is an **identity** table at two lattice points, which is exact: identity
939
+ * is linear and a trilinear fetch through corners holding their own coordinates reproduces a
940
+ * linear function precisely. So it is the right answer if anything ever samples it rather
941
+ * than an inert stand-in that happens not to be read.
942
+ */
943
+ if (this.gradeTexture === null) this.uploadGrade(identityGradeLut(GRADE_PLACEHOLDER_SIZE));
944
+ gl.activeTexture(gl.TEXTURE4);
945
+ gl.bindTexture(gl.TEXTURE_3D, this.gradeTexture);
946
+ gl.uniform1i(this.uniforms['uGradeLut'] ?? null, 4);
947
+ gl.uniform1f(this.uniforms['uGradeStrength'] ?? null, this.gradeStrength);
948
+ gl.uniform1f(this.uniforms['uGradeSize'] ?? null, this.gradeSize);
949
+ gl.activeTexture(gl.TEXTURE0);
950
+
951
+ /* No unit and no texture: a flat colour, not a sample. Uploaded unconditionally — two
952
+ floats and a triplet cost nothing next to the triangle this pass already draws — and it
953
+ is `withVeil` in the shader, not a branch here, that keeps a veil-less frame free of the
954
+ mix it does not need. */
955
+ gl.uniform3fv(this.uniforms['uVeilColor'] ?? null, veilColor);
956
+ gl.uniform1f(this.uniforms['uVeilAlpha'] ?? null, veilAlpha);
957
+
958
+ gl.bindVertexArray(this.vao);
959
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
960
+ gl.bindVertexArray(null);
961
+
962
+ /*
963
+ * **The units this pass used are released, and that is not tidiness.**
964
+ *
965
+ * Unit 1 holds `depth` — an attachment of this very target — and a binding survives the frame
966
+ * it was made in. Anything that later *attaches* that texture while it is still bound to a
967
+ * sampler the active program declares forms a feedback loop, which WebGL2 reports as
968
+ * `GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture` and then
969
+ * draws something undefined. Order-independent transparency attaches exactly this depth to its
970
+ * own framebuffers on the next frame, and that is how this was found: 120 pixels of a frame
971
+ * that should have been identical, and a warning per draw explaining why.
972
+ */
973
+ for (let unit = 0; unit <= 4; unit++) {
974
+ gl.activeTexture(gl.TEXTURE0 + unit);
975
+ gl.bindTexture(gl.TEXTURE_2D, null);
976
+ }
977
+ gl.activeTexture(gl.TEXTURE0);
978
+
979
+ // Handed back the way the rest of the renderer expects to find it.
980
+ gl.depthMask(true);
981
+ gl.enable(gl.DEPTH_TEST);
982
+ /*
983
+ * **And culling, which this pass switched off and the next frame's world is drawn with.**
984
+ *
985
+ * It was the one borrowed state never returned. `resolve` runs at `endFrame`, so from the
986
+ * second frame onwards every `drawMesh` in every scene ran with `CULL_FACE` disabled — the
987
+ * world drawn double-sided on the backend this engine is most often looked at, against a
988
+ * renderer that enables culling once at setup and documents it as "on for the life of the
989
+ * renderer because the world is solid".
990
+ *
991
+ * Invisible wherever geometry is wound correctly, which is every scene here, so nothing
992
+ * caught it. What caught it was a scene whose geometry was wound *backwards*: it looked
993
+ * perfect on WebGL2 and lost its entire ground on WebGPU, where culling is pipeline state
994
+ * that no pass can leak. The defect read as a WebGPU bug for a fortnight and was this line.
995
+ */
996
+ gl.enable(gl.CULL_FACE);
997
+ }
998
+
999
+ dispose(): void {
1000
+ const { gl } = this;
1001
+ this.ao?.dispose();
1002
+ this.ao = null;
1003
+ this.bloom?.dispose();
1004
+ this.bloom = null;
1005
+ if (this.framebuffer !== null) gl.deleteFramebuffer(this.framebuffer);
1006
+ if (this.texture !== null) gl.deleteTexture(this.texture);
1007
+ if (this.depth !== null) gl.deleteTexture(this.depth);
1008
+ /*
1009
+ * The two snapshots and their framebuffers, which this method did not release before the
1010
+ * colour one was added. **The depth pair is the same leak and is freed here for the same
1011
+ * reason**: they are allocated in `ensureSize` beside everything above, so releasing some of
1012
+ * what that allocates and not the rest is a distinction nothing here intends.
1013
+ */
1014
+ if (this.colorCopy !== null) gl.deleteTexture(this.colorCopy);
1015
+ if (this.colorCopyFramebuffer !== null) gl.deleteFramebuffer(this.colorCopyFramebuffer);
1016
+ if (this.depthCopy !== null) gl.deleteTexture(this.depthCopy);
1017
+ if (this.depthCopyFramebuffer !== null) gl.deleteFramebuffer(this.depthCopyFramebuffer);
1018
+ if (this.gradeTexture !== null) gl.deleteTexture(this.gradeTexture);
1019
+ this.gradeTexture = null;
1020
+ this.gradeSource = null;
1021
+ this.releaseMultisample();
1022
+ gl.deleteProgram(this.program);
1023
+ gl.deleteVertexArray(this.vao);
1024
+ this.framebuffer = null;
1025
+ this.texture = null;
1026
+ this.depth = null;
1027
+ this.colorCopy = null;
1028
+ this.colorCopyFramebuffer = null;
1029
+ this.depthCopy = null;
1030
+ this.depthCopyFramebuffer = null;
1031
+ }
1032
+ }