@cueframe/kernel 0.2.2 → 0.2.3

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 (332) hide show
  1. package/dist/_members/animate/index.d.ts +8 -2
  2. package/dist/_members/animate/layout/FlexLayout.d.ts +69 -0
  3. package/dist/_members/animate/layout/fit.d.ts +44 -0
  4. package/dist/_members/animate/layout/index.d.ts +3 -0
  5. package/dist/_members/animate/layout/solveFlex.d.ts +70 -0
  6. package/dist/_members/animate/media/MediaTileScene.d.ts +65 -0
  7. package/dist/_members/animate/media/recipes.d.ts +61 -0
  8. package/dist/_members/animate/scene/FocusPass.d.ts +76 -0
  9. package/dist/_members/animate/scene/UnlitPlane.d.ts +45 -0
  10. package/dist/_members/animate/scene/__oracle__/cssProjection.d.ts +24 -0
  11. package/dist/_members/animate/scene/assets.d.ts +21 -0
  12. package/dist/_members/animate/scene/backdrop.d.ts +7 -0
  13. package/dist/_members/animate/scene/coordinates.d.ts +58 -0
  14. package/dist/_members/animate/scene/deviceOpacity.d.ts +18 -0
  15. package/dist/_members/animate/scene/errors.d.ts +14 -0
  16. package/dist/_members/animate/scene/finishing.d.ts +69 -0
  17. package/dist/_members/animate/scene/finishingMath.d.ts +60 -0
  18. package/dist/_members/animate/scene/finishingPass.d.ts +35 -0
  19. package/dist/_members/animate/scene/focusBlur.d.ts +56 -0
  20. package/dist/_members/animate/scene/focusResources.d.ts +190 -0
  21. package/dist/_members/animate/scene/focusShaders.d.ts +68 -0
  22. package/dist/_members/animate/scene/fontReadiness.d.ts +27 -0
  23. package/dist/_members/animate/scene/grainNoise.d.ts +118 -0
  24. package/dist/_members/animate/scene/index.d.ts +19 -0
  25. package/dist/_members/animate/scene/internal.d.ts +29 -0
  26. package/dist/_members/animate/scene/planeFit.d.ts +46 -0
  27. package/dist/_members/animate/scene/preparedWorldText.d.ts +25 -0
  28. package/dist/_members/animate/scene/rasterCache.d.ts +30 -0
  29. package/dist/_members/animate/scene/rasterReadiness.d.ts +33 -0
  30. package/dist/_members/animate/scene/readiness.d.ts +69 -0
  31. package/dist/_members/animate/scene/redraw.d.ts +10 -0
  32. package/dist/_members/animate/scene/render.d.ts +9 -0
  33. package/dist/_members/animate/scene/scaling.d.ts +13 -0
  34. package/dist/_members/animate/scene/text.d.ts +40 -0
  35. package/dist/_members/animate/scene/textLayout.d.ts +78 -0
  36. package/dist/_members/animate/scene/textureImageSize.d.ts +4 -0
  37. package/dist/_members/animate/scene/useSceneImageTexture.d.ts +21 -0
  38. package/dist/_members/animate/scene/useWorldTextTexture.d.ts +21 -0
  39. package/dist/_members/animate/scene/v2/MeasuredPlaneGeometry.d.ts +7 -0
  40. package/dist/_members/animate/scene/v2/PhotographicStudioRig.d.ts +11 -0
  41. package/dist/_members/animate/scene/v2/PreparedSceneShotV1.d.ts +12 -0
  42. package/dist/_members/animate/scene/v2/SceneShotV2.d.ts +59 -0
  43. package/dist/_members/animate/scene/v2/builders.d.ts +170 -0
  44. package/dist/_members/animate/scene/v2/finishes.d.ts +152 -0
  45. package/dist/_members/animate/scene/v2/lighting.d.ts +119 -0
  46. package/dist/_members/animate/scene/v2/observePmremTargets.d.ts +4 -0
  47. package/dist/_members/animate/scene/v2/preparationFacts.d.ts +32 -0
  48. package/dist/_members/animate/scene/v2/preparedSurface.d.ts +17 -0
  49. package/dist/_members/animate/scene/v2/projectedResolution.d.ts +2 -0
  50. package/dist/_members/animate/scene/v2/renderTargetObserver.d.ts +5 -0
  51. package/dist/_members/animate/scene/v2/runtimeAllocations.d.ts +55 -0
  52. package/dist/_members/animate/scene/v2/shadow.d.ts +23 -0
  53. package/dist/_members/animate/scene/v2/slabGeometry.d.ts +134 -0
  54. package/dist/_members/animate/scene/v2/slots.d.ts +73 -0
  55. package/dist/_members/animate/scene/v2/videoBinding.d.ts +39 -0
  56. package/dist/_members/animate/scene/worldBounds.d.ts +19 -0
  57. package/dist/_members/animate/scene/worldTextRaster.d.ts +87 -0
  58. package/dist/_members/animate/scene/worldTextTexture.d.ts +32 -0
  59. package/dist/_members/animate/stage/PerspectiveStage.d.ts +73 -0
  60. package/dist/_members/animate/stage/camera.d.ts +143 -0
  61. package/dist/_members/animate/stage/dof.d.ts +9 -0
  62. package/dist/_members/animate/stage/index.d.ts +6 -0
  63. package/dist/_members/animate/stage/presets.d.ts +17 -0
  64. package/dist/_members/animate/three/DeviceMesh.d.ts +256 -0
  65. package/dist/_members/animate/three/SceneCameraRig.d.ts +12 -0
  66. package/dist/_members/animate/three/StageCameraRig.d.ts +7 -0
  67. package/dist/_members/animate/three/StudioRig.d.ts +228 -0
  68. package/dist/_members/animate/three/ThreeCanvas.d.ts +22 -0
  69. package/dist/_members/animate/three/defaultScreen.d.ts +23 -0
  70. package/dist/_members/animate/three/index.d.ts +7 -1
  71. package/dist/_members/animate/three/textureLifecycle.d.ts +29 -0
  72. package/dist/_members/animate/three/toneMapping.d.ts +113 -0
  73. package/dist/_members/animate/three/useImageTexture.d.ts +17 -0
  74. package/dist/_members/authoring/index.d.ts +2 -0
  75. package/dist/_members/authoring/scene/index.d.ts +6 -0
  76. package/dist/_members/authoring/scene/materialize.d.ts +47 -0
  77. package/dist/_members/authoring/scene/validate.d.ts +80 -0
  78. package/dist/_members/authoring/scene/wrapper.d.ts +41 -0
  79. package/dist/_members/component-runtime/allowedImports.d.ts +3 -0
  80. package/dist/_members/component-runtime/allowedImports.d.ts.map +1 -0
  81. package/dist/_members/component-runtime/bake.d.ts +8 -0
  82. package/dist/_members/component-runtime/bake.d.ts.map +1 -1
  83. package/dist/_members/component-runtime/browserFirewall.d.ts +7 -1
  84. package/dist/_members/component-runtime/browserFirewall.d.ts.map +1 -1
  85. package/dist/_members/component-runtime/browserOptions.d.ts +59 -3
  86. package/dist/_members/component-runtime/browserOptions.d.ts.map +1 -1
  87. package/dist/_members/component-runtime/canonicalIdentity.d.ts +14 -0
  88. package/dist/_members/component-runtime/canonicalIdentity.d.ts.map +1 -1
  89. package/dist/_members/component-runtime/contracts.d.ts +341 -1
  90. package/dist/_members/component-runtime/contracts.d.ts.map +1 -1
  91. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts +5 -0
  92. package/dist/_members/component-runtime/fixtures/imageTileDriftWall.d.ts.map +1 -0
  93. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts +5 -0
  94. package/dist/_members/component-runtime/fixtures/mediaTileMixed.d.ts.map +1 -0
  95. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts +8 -0
  96. package/dist/_members/component-runtime/fixtures/mediaTileVideo.d.ts.map +1 -0
  97. package/dist/_members/component-runtime/importPolicy.d.ts +3 -2
  98. package/dist/_members/component-runtime/importPolicy.d.ts.map +1 -1
  99. package/dist/_members/component-runtime/index.d.ts +3 -0
  100. package/dist/_members/component-runtime/index.d.ts.map +1 -1
  101. package/dist/_members/component-runtime/livePreviewProxy.d.ts +7 -0
  102. package/dist/_members/component-runtime/livePreviewProxy.d.ts.map +1 -0
  103. package/dist/_members/component-runtime/localRoot.d.ts +37 -0
  104. package/dist/_members/component-runtime/localRoot.d.ts.map +1 -0
  105. package/dist/_members/component-runtime/mediaResolution.d.ts +25 -0
  106. package/dist/_members/component-runtime/mediaResolution.d.ts.map +1 -0
  107. package/dist/_members/component-runtime/render.d.ts +151 -13
  108. package/dist/_members/component-runtime/render.d.ts.map +1 -1
  109. package/dist/_members/component-runtime/renderDiagnostics.d.ts +14 -0
  110. package/dist/_members/component-runtime/renderDiagnostics.d.ts.map +1 -0
  111. package/dist/_members/component-runtime/sceneAdmission.d.ts +47 -0
  112. package/dist/_members/component-runtime/sceneAdmission.d.ts.map +1 -0
  113. package/dist/_members/component-runtime/sourceWorkspace.d.ts +8 -0
  114. package/dist/_members/component-runtime/sourceWorkspace.d.ts.map +1 -1
  115. package/dist/_members/component-runtime/webglProbe.d.ts +191 -0
  116. package/dist/_members/component-runtime/webglProbe.d.ts.map +1 -0
  117. package/dist/_members/composition/fonts/bundledFaces.d.ts +150 -0
  118. package/dist/_members/composition/fonts/captionFaces.d.ts +268 -0
  119. package/dist/_members/composition/fonts.d.ts +11 -4
  120. package/dist/_members/composition/graphics-plan/schemas.d.ts +4 -4
  121. package/dist/_members/composition/ops/types.d.ts +1 -1
  122. package/dist/_members/composition/primitive-catalog/types.d.ts +1 -0
  123. package/dist/_members/composition/projection/behind-readiness.d.ts +3 -0
  124. package/dist/_members/composition/projection/brandKit.d.ts +6 -0
  125. package/dist/_members/composition/projection/composition-floor.d.ts +2 -1
  126. package/dist/_members/composition/scene/animation.d.ts +25 -0
  127. package/dist/_members/composition/scene/budget.d.ts +29 -0
  128. package/dist/_members/composition/scene/budgetPolicy.d.mts +13 -0
  129. package/dist/_members/composition/scene/clipRules.d.ts +119 -0
  130. package/dist/_members/composition/scene/constraints.d.ts +61 -0
  131. package/dist/_members/composition/scene/device.d.ts +21 -0
  132. package/dist/_members/composition/scene/examples.d.ts +11 -0
  133. package/dist/_members/composition/scene/index.d.ts +11 -0
  134. package/dist/_members/composition/scene/photographicRig.d.ts +242 -0
  135. package/dist/_members/composition/scene/preparedRender.d.ts +239 -0
  136. package/dist/_members/composition/scene/resolution.d.ts +178 -0
  137. package/dist/_members/composition/scene/schema.d.ts +351 -0
  138. package/dist/_members/composition/scene/videoSchedule.d.ts +43 -0
  139. package/dist/_members/composition/validators/brandKit.d.ts +1 -0
  140. package/dist/_members/composition/validators/render.d.ts +2 -0
  141. package/dist/_members/composition-ops/index.d.ts +45 -0
  142. package/dist/_members/composition-ops/opRecorder.d.ts +1 -1
  143. package/dist/_members/core/render/compositionRender.d.ts +41 -9
  144. package/dist/_members/core/render/index.d.ts +9 -2
  145. package/dist/_members/core/render/sceneCaptureIdentity.d.ts +14 -0
  146. package/dist/_members/core/render/sceneShotPlan.d.ts +142 -0
  147. package/dist/_members/core/render/sceneShotPreparation.d.ts +57 -0
  148. package/dist/_members/core/render/slabDescriptor.d.ts +21 -0
  149. package/dist/_members/core/render/trackProjection.d.ts +33 -0
  150. package/dist/_members/core/render/types.d.ts +142 -0
  151. package/dist/_members/errors/registry.d.ts +6 -0
  152. package/dist/_members/mcp/adapter.d.ts +5 -0
  153. package/dist/_members/mcp/generated/sceneContract.d.ts +155 -0
  154. package/dist/_members/mcp/sceneShot.d.ts +38 -0
  155. package/dist/_members/mcp/sceneShotExample.d.ts +22 -0
  156. package/dist/_members/media-model/api.d.ts +1 -0
  157. package/dist/_members/media-model/media-kind.d.ts +1 -1
  158. package/dist/_members/media-model/testing/mediaStoreContract.d.ts +1 -1
  159. package/dist/_members/primitives/effects/index.d.ts +1 -0
  160. package/dist/_members/primitives/effects/stage-camera/config.d.ts +50 -0
  161. package/dist/_members/primitives/effects/stage-camera/index.d.ts +31 -0
  162. package/dist/_members/primitives/layouts/flex-layout/config.d.ts +73 -0
  163. package/dist/_members/primitives/layouts/flex-layout/index.d.ts +4 -0
  164. package/dist/_members/primitives/layouts/index.d.ts +1 -0
  165. package/dist/_members/primitives/layouts/picture-in-picture/config.d.ts +1 -1
  166. package/dist/_members/primitives/lib/frameScale.d.ts +4 -0
  167. package/dist/_members/primitives/lib/index.d.ts +1 -0
  168. package/dist/_members/primitives/lib/palette.d.ts +30 -30
  169. package/dist/_members/primitives/lib/text/contrast.d.ts +2 -1
  170. package/dist/_members/primitives/lib/text/spec.d.ts +0 -8
  171. package/dist/_members/primitives/lib/types.d.ts +2 -0
  172. package/dist/_members/primitives/scenes/device-showcase/config.d.ts +41 -0
  173. package/dist/_members/primitives/scenes/device-showcase/index.d.ts +36 -0
  174. package/dist/_members/primitives/scenes/hero-device-assemble/config.d.ts +1 -0
  175. package/dist/_members/primitives/scenes/hero-device-assemble/index.d.ts +2 -1
  176. package/dist/_members/primitives/scenes/index.d.ts +1 -0
  177. package/dist/_members/primitives/ui-blocks/badge-pop/config.d.ts +1 -1
  178. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/config.d.ts +1 -0
  179. package/dist/_members/primitives/ui-blocks/device-mockup-zoom/index.d.ts +2 -1
  180. package/dist/_members/primitives/ui-blocks/terminal-simulator/config.d.ts +1 -1
  181. package/dist/_members/primitives/ui-blocks/toast-notification/config.d.ts +1 -1
  182. package/dist/_members/render-harness/cardAssetAdmission.d.ts.map +1 -1
  183. package/dist/_members/render-harness/cardRender.d.ts.map +1 -1
  184. package/dist/_members/render-harness/css-tree-subpaths.d.ts +11 -0
  185. package/dist/_members/render-harness/extractSegments.d.ts +1 -0
  186. package/dist/_members/render-harness/extractSegments.d.ts.map +1 -1
  187. package/dist/_members/render-harness/imageHeader.d.ts +14 -0
  188. package/dist/_members/render-harness/imageHeader.d.ts.map +1 -0
  189. package/dist/_members/render-harness/index.d.ts +6 -0
  190. package/dist/_members/render-harness/index.d.ts.map +1 -1
  191. package/dist/_members/render-harness/materializeSources.d.ts +46 -2
  192. package/dist/_members/render-harness/materializeSources.d.ts.map +1 -1
  193. package/dist/_members/render-harness/nodeScenePreparation.d.ts +97 -0
  194. package/dist/_members/render-harness/nodeScenePreparation.d.ts.map +1 -0
  195. package/dist/_members/render-harness/remotion-runtime.d.ts +16 -2
  196. package/dist/_members/render-harness/renderInputAssets.d.ts +1 -1
  197. package/dist/_members/render-harness/renderInputAssets.d.ts.map +1 -1
  198. package/dist/_members/render-harness/resolveAssets.d.ts +2 -2
  199. package/dist/_members/render-harness/resolveAssets.d.ts.map +1 -1
  200. package/dist/_members/render-harness/sceneShotAssets.d.ts +17 -0
  201. package/dist/_members/render-harness/sceneShotAssets.d.ts.map +1 -0
  202. package/dist/animate/preparation-facts.d.ts +1 -0
  203. package/dist/animate/preparation-facts.js +22 -0
  204. package/dist/animate.js +336 -1005
  205. package/dist/authoring/build-tools.js +7 -6
  206. package/dist/authoring/context.js +5 -4
  207. package/dist/authoring/prompts.js +1 -1
  208. package/dist/authoring/scene.d.ts +1 -0
  209. package/dist/authoring/scene.js +50 -0
  210. package/dist/authoring/tools.js +6 -5
  211. package/dist/authoring.js +49 -29
  212. package/dist/chunk-2L7PYYJK.js +23 -0
  213. package/dist/{chunk-ZN6P3KOJ.js → chunk-32TH76H3.js} +2 -2
  214. package/dist/chunk-5DJ3IEJR.js +4424 -0
  215. package/dist/chunk-6BVVCRRD.js +26488 -0
  216. package/dist/{chunk-DQKSCHFC.js → chunk-6EWRIAZA.js} +187 -66
  217. package/dist/{chunk-YQ7FFW3G.js → chunk-6VWICHOZ.js} +26 -5
  218. package/dist/{chunk-RETQFTGY.js → chunk-A74FZCPY.js} +42 -5
  219. package/dist/{chunk-C5SEPOWD.js → chunk-AS5EXBNS.js} +1792 -707
  220. package/dist/{chunk-U5LBYS3N.js → chunk-B3GSTQLR.js} +339 -272
  221. package/dist/chunk-BVA3537Z.js +63 -0
  222. package/dist/{chunk-DHKQ47Q6.js → chunk-DAARYRNT.js} +6 -1
  223. package/dist/chunk-DQLYWNLC.js +2063 -0
  224. package/dist/chunk-E6WHXIDF.js +3619 -0
  225. package/dist/{chunk-HXKTZPRH.js → chunk-E7GIZEPS.js} +1 -1
  226. package/dist/{chunk-M2TLRXEO.js → chunk-EXY4JJPH.js} +1 -1
  227. package/dist/{chunk-GEGRJKKO.js → chunk-F2DJL7P7.js} +1 -1
  228. package/dist/{chunk-AWT3P5ZN.js → chunk-FVDFPJHT.js} +1 -1
  229. package/dist/{chunk-EMGFZ3PR.js → chunk-FWSJLHSV.js} +5 -1
  230. package/dist/{chunk-TMIBBD5E.js → chunk-I5QWBM3M.js} +280 -113
  231. package/dist/{chunk-IBMJ33EL.js → chunk-I5RX2QZT.js} +1 -1
  232. package/dist/{chunk-4FOOBSEE.js → chunk-J3DIUG24.js} +1 -0
  233. package/dist/{chunk-AD5HWBCE.js → chunk-JX53CVJV.js} +14 -5
  234. package/dist/{chunk-LNBVTDFR.js → chunk-L2AHS3AW.js} +1 -1
  235. package/dist/{chunk-BDMTUEEZ.js → chunk-LT4PWSR2.js} +2 -2
  236. package/dist/chunk-MH3UPKWR.js +3415 -0
  237. package/dist/{chunk-RFXR7ATW.js → chunk-NUKDEOK6.js} +13 -1
  238. package/dist/{chunk-IJ7PVJTK.js → chunk-ODUWCQI3.js} +3 -2
  239. package/dist/chunk-QAGGJHAF.js +16 -0
  240. package/dist/chunk-QS36DMFG.js +332 -0
  241. package/dist/{chunk-G5BFI32U.js → chunk-RAXHCRVV.js} +1 -1
  242. package/dist/{chunk-BIBYZJL3.js → chunk-RL5SO653.js} +3 -3
  243. package/dist/{chunk-ZSZABOE5.js → chunk-S5H6GH6M.js} +1 -1
  244. package/dist/{chunk-EEXCDFY5.js → chunk-SD25VQDE.js} +1 -1
  245. package/dist/{chunk-7REW2MW3.js → chunk-SX523NDS.js} +10 -10
  246. package/dist/chunk-TARKDVP6.js +430 -0
  247. package/dist/{chunk-IHFREGFA.js → chunk-TCHPRGC5.js} +18 -2
  248. package/dist/{chunk-ZCAQHNPI.js → chunk-UKGNHZS4.js} +1 -1
  249. package/dist/{chunk-WQSGVRFU.js → chunk-UY77TMKD.js} +31 -44
  250. package/dist/chunk-VKATKWWR.js +1462 -0
  251. package/dist/{chunk-CX2IIQ4R.js → chunk-W2245F6G.js} +29 -29
  252. package/dist/{chunk-XHUYWVYK.js → chunk-WBNFSG6T.js} +1 -1
  253. package/dist/chunk-WIHXXF3X.js +221 -0
  254. package/dist/{chunk-XVBOSPZI.js → chunk-X74EEFXV.js} +6 -6
  255. package/dist/{chunk-7KEUL3FI.js → chunk-XF2QMKRG.js} +9 -1
  256. package/dist/{chunk-HFC3MKXA.js → chunk-Y4HPN4BC.js} +1 -0
  257. package/dist/{chunk-D43J23QX.js → chunk-YFSBFCXO.js} +1018 -42
  258. package/dist/{chunk-6ID2J64H.js → chunk-YHC3RXS7.js} +162 -25
  259. package/dist/{chunk-KKEY5MIW.js → chunk-ZS3A3QUM.js} +16 -16
  260. package/dist/{chunk-LQUWKBST.js → chunk-ZVG446DJ.js} +139 -10
  261. package/dist/component-runtime/browserOptions.js +14 -3
  262. package/dist/component-runtime/contracts.js +35 -3
  263. package/dist/component-runtime/identity/browser.js +1 -1
  264. package/dist/component-runtime/identity.js +2 -2
  265. package/dist/component-runtime/importPolicy.js +2 -2
  266. package/dist/component-runtime/mediaResolution.d.ts +1 -0
  267. package/dist/component-runtime/mediaResolution.js +11 -0
  268. package/dist/component-runtime/render.js +38 -5
  269. package/dist/component-runtime.js +118 -14
  270. package/dist/compose.js +26 -20
  271. package/dist/composition/fonts.js +64 -67
  272. package/dist/composition/graphics-plan.js +3 -2
  273. package/dist/composition/ops.js +4 -3
  274. package/dist/composition/primitive-catalog.js +1 -1
  275. package/dist/composition/projection.js +10 -3
  276. package/dist/composition/scene/budget-policy.d.ts +1 -0
  277. package/dist/composition/scene/budget-policy.js +17 -0
  278. package/dist/composition/scene/schema.json +2757 -0
  279. package/dist/composition/scene.d.ts +1 -0
  280. package/dist/composition/scene.js +275 -0
  281. package/dist/composition/validators.js +3 -2
  282. package/dist/composition-ops.js +103 -13
  283. package/dist/composition.js +12 -5
  284. package/dist/{context-4GSDBFT3.js → context-IUPQ54V4.js} +5 -4
  285. package/dist/core/render.js +54 -3
  286. package/dist/core/select.js +2 -2
  287. package/dist/core.js +6 -3
  288. package/dist/director/ai-sdk.js +3 -3
  289. package/dist/director/domain.js +2 -2
  290. package/dist/director.js +3 -3
  291. package/dist/errors.js +1 -1
  292. package/dist/mcp/adapter.js +4 -4
  293. package/dist/mcp/core.js +1 -1
  294. package/dist/mcp/curation.js +1 -1
  295. package/dist/mcp/server.js +4 -4
  296. package/dist/mcp.js +4 -4
  297. package/dist/media-model/media-kind.js +2 -0
  298. package/dist/media-model/testing.js +16 -11
  299. package/dist/media-model.js +1 -1
  300. package/dist/nle-export.js +26 -20
  301. package/dist/primitives/backgrounds.js +2 -2
  302. package/dist/primitives/captions.js +21 -11
  303. package/dist/primitives/effects.js +14 -4
  304. package/dist/primitives/graphics.json +3 -0
  305. package/dist/primitives/hero-text.js +4 -3
  306. package/dist/primitives/layouts.js +9 -2
  307. package/dist/primitives/lib/frameScale.d.ts +1 -0
  308. package/dist/primitives/lib/frameScale.js +11 -0
  309. package/dist/primitives/lib/index.js +18 -10
  310. package/dist/primitives/lib/palette.js +1 -1
  311. package/dist/primitives/lib/text/contrast.js +2 -1
  312. package/dist/primitives/lib/text/typeface.js +1 -1
  313. package/dist/primitives/lib.js +18 -10
  314. package/dist/primitives/params-required.json +3 -0
  315. package/dist/primitives/scenes.js +12 -3
  316. package/dist/primitives/text.js +5 -5
  317. package/dist/primitives/transitions.js +2 -2
  318. package/dist/primitives/ui-blocks.js +6 -5
  319. package/dist/primitives/version-map.json +5 -2
  320. package/dist/primitives.js +20 -13
  321. package/dist/render-harness/cardAssetAdmission.js +2 -2
  322. package/dist/render-harness/renderInputAssets.js +2 -2
  323. package/dist/render-harness.js +874 -124
  324. package/package.json +49 -15
  325. package/dist/_members/animate/three/drei.d.ts +0 -6
  326. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts +0 -9
  327. package/dist/_members/component-runtime/fixtures/webgpuTiledRefraction.d.ts.map +0 -1
  328. package/dist/chunk-5OTQ7M43.js +0 -718
  329. package/dist/chunk-CGHTMZNC.js +0 -6
  330. package/dist/chunk-KVMVYRXX.js +0 -9527
  331. package/dist/chunk-WYQX4QIK.js +0 -544
  332. /package/dist/{chunk-H5LMJKZU.js → chunk-JVDUSOYG.js} +0 -0
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import type { SceneFrameSize } from './scaling.js';
3
+ export interface ScenePostTreatment {
4
+ grain: number;
5
+ vignette: number;
6
+ }
7
+ /** FNV-1a over UTF-16 code units: a small, dependency-free, deterministic 32-bit hash. */
8
+ export declare function hashSeed(seed: string): number;
9
+ /** The `feTurbulence` seed for one frame of one shot: a function of the render seed and the local frame only. */
10
+ export declare function grainSeed(seed: string, frame: number): number;
11
+ /** A document-unique filter id derived from the render seed, so two shots on screen at once cannot share one. */
12
+ export declare function postFilterId(seed: string): string;
13
+ export type PostStage = 'grain' | 'vignette';
14
+ /** Which treatments are on; zero explicitly disables one. Grain is applied first, vignette darkens it. */
15
+ export declare function postFilterStages(post: ScenePostTreatment): PostStage[];
16
+ /** The CSS that routes the composed shot through the filter, or nothing when finishing is off. */
17
+ export declare function postFilterStyle(id: string, post: ScenePostTreatment): React.CSSProperties;
18
+ export interface PostFilterProps {
19
+ id: string;
20
+ post: ScenePostTreatment;
21
+ seed: string;
22
+ frame: number;
23
+ /** Output size in px; the vignette is laid out in the element's own pixel space. */
24
+ size: SceneFrameSize;
25
+ /** Reference scale (output width / reference width); the grain frequency divides by it. */
26
+ scale: number;
27
+ }
28
+ /** Grain frequency in cycles per reference pixel; divided by the reference scale at render. */
29
+ export declare const GRAIN_BASE_FREQUENCY = 0.85;
30
+ /** `feTurbulence` base frequency for a shot rendered at `scale`: the grain keeps its reference-pixel size. */
31
+ export declare function grainFrequency(scale: number): number;
32
+ /**
33
+ * The shot-level finishing filter, applied to the shot's DOM layers — the CSS backdrop and the
34
+ * screen text — with `filter: url(#id)`. Every stage is an opaque treatment blended over the layer,
35
+ * and the last primitive cuts the result back to the layer's own alpha with `feComposite in`, so a
36
+ * transparent backdrop stays transparent and antialiased glyph edges keep their coverage. Only
37
+ * synchronous primitives are used: nothing here fetches an image, so readiness cannot race the
38
+ * filter.
39
+ *
40
+ * It is NOT applied to the world. The world is a WebGL canvas, and a `filter` over a layer holding
41
+ * one is what let Chromium rasterize a whole shot once at 756x413 and tile that raster across six
42
+ * frames of a 390-frame render (defect D4). The world's grain and vignette are the same arithmetic,
43
+ * run in the focus pass's output stage instead (`focusShaders.ts`), against the same
44
+ * `grainSeed(seed, frame)` and the same `sceneVignetteFactor`. Both layers here and the world are
45
+ * finished independently and composited by the browser afterwards, which is exact for the vignette
46
+ * (a per-pixel scalar multiply distributes over `over`) and exact for the grain wherever the two
47
+ * colours sit on the same side of the overlay's half.
48
+ *
49
+ * The first primitive puts the layer's colour on an opaque carrier. `feBlend` works on
50
+ * premultiplied colour, so blending an opaque treatment over a partly covered pixel and then
51
+ * cutting back to that coverage leaves the treatment weighted by the coverage twice over — a dark
52
+ * fringe on every antialiased glyph edge, and a bright one under a multiply. `feColorMatrix` works
53
+ * unpremultiplied, so lifting the alpha to one first makes the blends operate on the colour alone
54
+ * and the closing `feComposite in` restore the coverage exactly once. On an opaque layer it is the
55
+ * identity, so it changes no pixel of an opaque backdrop.
56
+ *
57
+ * Grain: fractal noise seeded from `grainSeed`, greyed, pulled toward mid-grey by `1 - grain`
58
+ * (overlay with 0.5 is the identity), overlay-blended. Vignette: a white core flooded over the
59
+ * middle of the frame and blurred outward; its coverage becomes a brightness factor
60
+ * `1 - vignette × (1 - coverage)`, multiply-blended. The blur and the colour matrix carry the
61
+ * full frame as an explicit subregion: a primitive with none inherits the union of its inputs'
62
+ * regions, which for these two is the flood's core rectangle — outside it the factor would be
63
+ * transparent, the multiply a no-op, and the darkening confined to the middle of the frame (the
64
+ * defect Stage 0c measured). Both run in sRGB so they read like the CSS
65
+ * overlays they replace. `feTurbulence` works in output pixels, so its base frequency is divided
66
+ * by the reference scale to keep the grain the size the author saw; the vignette's core and blur
67
+ * are proportional to the frame and need no scale. Both are therefore resolution-independent.
68
+ */
69
+ export declare function PostFilter({ id, post, seed, frame, size, scale }: PostFilterProps): React.JSX.Element | null;
@@ -0,0 +1,60 @@
1
+ import type { SceneFrameSize } from './scaling.js';
2
+ /**
3
+ * The arithmetic of the shot's finishing, in one place, because it is now applied twice.
4
+ *
5
+ * The backdrop and the screen text are DOM and are finished by the SVG filter in `finishing.tsx`;
6
+ * the world is WebGL and is finished inside the focus pass's output stage, where no filter can
7
+ * reach it. Both halves must therefore agree at every pixel, so the geometry that builds the
8
+ * filter's primitives and the geometry the shader evaluates are the same functions, stated here
9
+ * once. `finishing.tsx` builds `feFlood`/`feGaussianBlur`/`feColorMatrix` out of these; the
10
+ * composite shader mirrors `sceneVignetteFactor` and `sceneGrainLevel` line for line.
11
+ */
12
+ /** The vignette's white core, as a fraction of the frame: the middle 70 %. */
13
+ export declare const VIGNETTE_CORE_INSET = 0.15;
14
+ /** The core's blur, as a fraction of each axis. Proportional, so the vignette is resolution-free. */
15
+ export declare const VIGNETTE_SIGMA = 0.16;
16
+ export interface VignetteGeometry {
17
+ /** The core rectangle in frame pixels: left, top, right, bottom. */
18
+ readonly x0: number;
19
+ readonly y0: number;
20
+ readonly x1: number;
21
+ readonly y1: number;
22
+ readonly sigmaX: number;
23
+ readonly sigmaY: number;
24
+ }
25
+ /** The core rectangle and the blur radii for one frame size, in that frame's own pixels. */
26
+ export declare function vignetteGeometry(size: SceneFrameSize): VignetteGeometry;
27
+ /**
28
+ * Abramowitz–Stegun 7.1.26; |error| < 1.5e-7, and the same series the shader evaluates.
29
+ *
30
+ * `Math.sign`, matching GLSL's `sign`, so that both halves return exactly zero at zero — the series
31
+ * itself leaves 1.46e-9 there, and zero is where the vignette core's own edge lands.
32
+ */
33
+ export declare function erf(x: number): number;
34
+ /** A Gaussian-blurred half-plane pair: the blurred coverage of `[a, b]` at `p` with deviation `s`. */
35
+ export declare function blurredCoverage(a: number, b: number, sigma: number, p: number): number;
36
+ /**
37
+ * The brightness the vignette multiplies a pixel by, at a point in frame pixels (y down).
38
+ *
39
+ * The filter floods the core white, blurs it over the whole frame and turns the coverage into
40
+ * `1 - vignette x (1 - coverage)`; a Gaussian blur of an axis-aligned rectangle is separable and
41
+ * its coverage is the product of two error-function differences, which is what this evaluates. The
42
+ * blur is the *ideal* Gaussian: Skia approximates it with box passes, and the two differ by a
43
+ * measured mean of 0.649 and a worst 2.89 parts in 255 of the factor (worst at the frame centre,
44
+ * where the factor is near one), so the world's vignette and the backdrop's differ by that
45
+ * fraction of each pixel's own value — 0.03 of a code on this suite's backdrop.
46
+ */
47
+ export declare function sceneVignetteFactor(vignette: number, size: SceneFrameSize, x: number, y: number): number;
48
+ /**
49
+ * The filter's `feComponentTransfer` on the greyed noise: `slope x noise + (1 - slope) / 2`, which
50
+ * pulls the field toward the mid-grey that makes an overlay blend the identity, so `grain` is the
51
+ * fraction of the full-strength field that survives.
52
+ */
53
+ export declare function sceneGrainLevel(grain: number, noise: number): number;
54
+ /**
55
+ * `feBlend mode="overlay"` for one channel: the CSS compositing definition, `HardLight` with its
56
+ * arguments swapped. Both branches are affine in the backdrop, which is why applying it to the
57
+ * world and to the backdrop separately and compositing the two is the same picture as applying it
58
+ * once to the composed pair — for as long as both are on the same side of the half.
59
+ */
60
+ export declare function sceneOverlay(backdrop: number, source: number): number;
@@ -0,0 +1,35 @@
1
+ import { type ScenePostTreatment } from './finishing.js';
2
+ import type { SceneFrameSize } from './scaling.js';
3
+ /**
4
+ * What the composite shader needs to put one frame's finishing on the world.
5
+ *
6
+ * Every field is the filter's own number: the frequency `finishing.tsx` writes into
7
+ * `feTurbulence`'s `baseFrequency`, the stitch that attribute's `stitchTiles="stitch"` implies for
8
+ * a tile the size of the frame, the seed `grainSeed` hands the filter, and the core and deviations
9
+ * `vignetteGeometry` gives `feFlood` and `feGaussianBlur`. Nothing is a shader-side approximation
10
+ * of an authored value; the two halves are given the same numbers.
11
+ */
12
+ export interface SceneFinishingUniforms {
13
+ readonly grain: number;
14
+ readonly vignette: number;
15
+ readonly frame: readonly [number, number];
16
+ /** The `feTurbulence` seed for this frame; the lattice is a function of it alone. */
17
+ readonly seed: number;
18
+ readonly grainBase: readonly [number, number];
19
+ /** Lattice period in x and y, then the wrap point in x and y. */
20
+ readonly grainStitch: readonly [number, number, number, number];
21
+ /** The core rectangle: left, top, right, bottom, in frame pixels. */
22
+ readonly vignetteCore: readonly [number, number, number, number];
23
+ readonly vignetteSigma: readonly [number, number];
24
+ /** This seed's lattice packed for the shader, or `null` when grain is off and none is sampled. */
25
+ readonly lattice: Float32Array | null;
26
+ }
27
+ /**
28
+ * The finishing of one frame of one shot, in the units the pass works in.
29
+ *
30
+ * Grain off and vignette off are spelled as zeros, which is what the shader branches on, so a shot
31
+ * with no finishing runs the composite it ran before this stage existed. The lattice is rebuilt
32
+ * per frame because the seed is: `grainSeed(seed, frame)` re-seeds every frame, which is what makes
33
+ * the grain move, and rebuilding it is two thousand steps of a Lehmer stream.
34
+ */
35
+ export declare function sceneFinishingUniforms(post: ScenePostTreatment, seed: string, frame: number, size: SceneFrameSize, scale: number): SceneFinishingUniforms;
@@ -0,0 +1,56 @@
1
+ import type { SceneFocusV2 } from '../../composition/scene/index.js';
2
+ import type { SceneFrameSize } from './scaling.js';
3
+ /**
4
+ * Taps per side of each separable pass. Seventeen samples across a diameter is enough that the
5
+ * widest circle of confusion this renderer allows does not band, and it is a compile-time constant
6
+ * so the loop bound is legal in GLSL ES 1.00 and the cost is the same on every frame.
7
+ */
8
+ export declare const FOCUS_TAPS = 8;
9
+ /**
10
+ * The circle of confusion at a camera-space distance, in output pixels.
11
+ *
12
+ * The contract's own definition: how far the point is from the focus distance, as a fraction of
13
+ * the focus range, clamped at one, times the maximum blur. Everything is in world units, which are
14
+ * output pixels — the same space the blur's radius is measured in, so the scaling that takes a
15
+ * shot from 1080p to 4K carries the focus with it and needs no second rule.
16
+ */
17
+ export declare function focusBlurRadius(distance: number, focus: SceneFocusV2): number;
18
+ /** Everything the focus shader needs for one frame, in output pixels and camera-space units. */
19
+ export interface FocusPassUniforms {
20
+ distance: number;
21
+ range: number;
22
+ maxBlur: number;
23
+ near: number;
24
+ far: number;
25
+ texel: [number, number];
26
+ }
27
+ /**
28
+ * The focus a shot that declares none renders through: a maximum blur of zero.
29
+ *
30
+ * `absent focus disables focus` is the contract, and this is that sentence in the units the pass
31
+ * works in. Zero maximum blur makes every circle of confusion exactly zero (`focusBlurRadius`
32
+ * multiplies by it), which makes the gather the identity — every tap lands on the centre texel.
33
+ * The plane and the range are then multiplied by zero and cannot reach the picture; they are one
34
+ * only because they must be finite and the range must not be zero, and `focusUniforms` scales
35
+ * them like any other. Nothing here is a stand-in for an authored value: a shot with no
36
+ * `post.focus` renders through the same pass, with the same resources, differing from a shot that
37
+ * authors `maxBlur: 0` in nothing at all.
38
+ */
39
+ export declare const FOCUS_OFF: SceneFocusV2;
40
+ /**
41
+ * The evaluated focus of one frame in the units the pass works in: reference pixels times the
42
+ * reference scale for the three focus numbers, the camera's own near/far for reconstructing
43
+ * camera-space distance from the depth buffer, and the texel size of the frame.
44
+ *
45
+ * `null` is a shot with no authored focus, which is `FOCUS_OFF` — the pass runs either way.
46
+ */
47
+ export declare function focusUniforms(focus: SceneFocusV2 | null, scale: number, camera: {
48
+ near: number;
49
+ far: number;
50
+ }, frame: SceneFrameSize): FocusPassUniforms;
51
+ /**
52
+ * Camera-space distance from a depth-buffer value, the way Three's own
53
+ * `perspectiveDepthToViewZ` does it, mirrored here so the shader's arithmetic can be checked
54
+ * without a GPU. Positive in front of the camera.
55
+ */
56
+ export declare function viewDistanceFromDepth(depth: number, near: number, far: number): number;
@@ -0,0 +1,190 @@
1
+ import { DataTexture, OrthographicCamera, Scene, ShaderMaterial, WebGLRenderTarget } from 'three';
2
+ import type { SceneFinishingUniforms } from './finishingPass.js';
3
+ import { type FocusPassUniforms } from './focusBlur.js';
4
+ import { type SceneActualResourceRegistrarV1 } from './v2/runtimeAllocations.js';
5
+ /** The WebGL extension registry three exposes as `renderer.extensions`; a test supplies a double. */
6
+ export interface FocusRendererExtensions {
7
+ has(name: string): boolean;
8
+ }
9
+ /** The slice of the WebGL context the pass reads: the sample count of the bound framebuffer. */
10
+ export interface FocusRendererContext {
11
+ readonly SAMPLES: number;
12
+ getParameter(name: number): unknown;
13
+ }
14
+ /** The renderer surface the pass drives; a node test supplies a recording double. */
15
+ export interface FocusRenderer {
16
+ extensions: FocusRendererExtensions;
17
+ /**
18
+ * The renderer's tone-mapping constant. Read only to be asserted constant: every lit material in
19
+ * a scene shot applies this curve ITSELF (`three/toneMapping.ts`), and three bakes the chosen
20
+ * function into the compiled program on first compile, so a renderer whose curve changed
21
+ * mid-scene would keep drawing the old one out of the program cache with nothing to say so.
22
+ */
23
+ toneMapping: number;
24
+ getContext(): FocusRendererContext;
25
+ getRenderTarget(): unknown;
26
+ setRenderTarget(target: unknown): void;
27
+ render(scene: unknown, camera: unknown): void;
28
+ }
29
+ /**
30
+ * The two extensions that make a half-float colour attachment renderable. Either is enough, and
31
+ * this is the same pair three itself tests before choosing `HalfFloatType` for its own
32
+ * intermediates (`WebGLRenderer`, three 0.183.2) — asking the question the way the renderer asks it
33
+ * is what keeps the answer true of the target it will actually allocate.
34
+ *
35
+ * The same pair is asked for before capture, on the page-level WebGL2 context, by
36
+ * `@cueframe/component-runtime`'s `webglProbe.ts` (`HALF_FLOAT_COLOR_TARGET_EXTENSIONS`), which
37
+ * refuses the browser typed `component_graphics_unavailable` and names the extensions. That is
38
+ * where a host without them is turned away; this stays as the second gate, for a host whose
39
+ * page-level answer and whose render-time answer disagree. The list is stated in both places
40
+ * because neither package can import the other — that one is bundled for the plain-Node script
41
+ * lane and must stay cheap to bundle, and this one is not among its dependencies — so neither copy
42
+ * may change alone.
43
+ */
44
+ export declare const HALF_FLOAT_TARGET_EXTENSIONS: readonly ["EXT_color_buffer_half_float", "EXT_color_buffer_float"];
45
+ /**
46
+ * What a refusal from this pass is about.
47
+ *
48
+ * `post`, not `post.focus`: every scene shot's world is composed through this pass, whether or not
49
+ * the shot authors focus, so a host that cannot allocate its targets refuses the shot's whole
50
+ * finishing section rather than an optional key the author may never have written.
51
+ */
52
+ export declare const FOCUS_SPEC_PATH = "post";
53
+ /**
54
+ * Refuse a host that cannot render into half-float colour.
55
+ *
56
+ * The pass round-trips the whole frame through its intermediates, so their precision is the
57
+ * precision of every scene shot, in focus or not. Eight-bit linear is not a near-enough substitute:
58
+ * stored as `round(L * 255)` it collapses sRGB codes 16-24 onto one or two levels, which is exactly
59
+ * where a dark product-UI gradient lives. Dropping to it silently would put a quietly posterized
60
+ * frame in front of an author who never learned the host could not give it — the substitution the
61
+ * spec's admission rules forbid. So this is a refusal, not a fallback.
62
+ */
63
+ export declare function assertHalfFloatColorTargets(gl: FocusRenderer, path: string): void;
64
+ /**
65
+ * The multisample count of the surface this pass replaces.
66
+ *
67
+ * The world used to be drawn straight onto the canvas, whose framebuffer fiber creates with
68
+ * `antialias: true`; now it is drawn into this pass's target, and a target allocated at one sample
69
+ * would hand every scene shot a hard-edged silhouette where it had a resolved one. So the target
70
+ * is allocated at the canvas's own count, read from the canvas's own framebuffer.
71
+ *
72
+ * `SAMPLES` is a property of whatever framebuffer is bound, so this is only the canvas's count
73
+ * while the canvas is bound. It is read once, during the pass's construction, which happens while
74
+ * the component renders and before any frame callback has bound anything — and the binding is
75
+ * checked rather than assumed, because a wrong answer here is not an error anywhere, only a frame
76
+ * that is quietly rougher or costlier than the one before it.
77
+ */
78
+ export declare function canvasSampleCount(gl: FocusRenderer, path: string): number;
79
+ /**
80
+ * One shot instance's world resources: two colour targets, the depth the world was drawn with, the
81
+ * two full-screen materials and the private quad they are drawn on.
82
+ *
83
+ * Owned per instance, never shared: two shots on screen at once each render their own world into
84
+ * their own targets, so neither can read the other's depth or half-blurred colour. Only the
85
+ * immutable shader source is common to them.
86
+ *
87
+ * The colour targets are half-float in the working (linear) colour space, which is what Three
88
+ * writes when a render target is bound; the composite pass is the one place the frame is encoded
89
+ * for output. Linear is the reason the precision matters: an 8-bit linear intermediate spends most
90
+ * of its codes above mid-grey and leaves the dark end of a colour-managed screenshot with almost
91
+ * none, so the round trip alone would band the gradients the shot exists to show. The host is
92
+ * asked for the capability once, here, and refused if it has not got it.
93
+ *
94
+ * The world target carries the canvas's own multisample count (`canvasSampleCount`), because it
95
+ * stands in for the canvas: every scene shot's geometry is rasterized here, and three resolves the
96
+ * colour and the depth into the attached textures when the target is unbound. `gathered` is
97
+ * written by a full-screen quad with no edges in it, so it is allocated single-sampled.
98
+ */
99
+ export declare class FocusResources {
100
+ private readonly registerActual;
101
+ /**
102
+ * The renderer these resources were built for and measured against.
103
+ *
104
+ * Kept so the pass can check it is still being driven by that renderer. The targets, their
105
+ * textures and their framebuffers belong to one GL context, and `samples` was read from that
106
+ * context's canvas; handing them to a different renderer would draw through objects it has never
107
+ * uploaded. Fiber builds one renderer per canvas and never swaps it, so this is a guard against a
108
+ * future change rather than a case anyone can reach today — but the symptom would be a blank or
109
+ * wrong frame with no error, which is exactly the kind of thing that has to be asserted.
110
+ */
111
+ readonly renderer: FocusRenderer;
112
+ readonly world: WebGLRenderTarget;
113
+ readonly gathered: WebGLRenderTarget;
114
+ readonly blur: ShaderMaterial;
115
+ readonly composite: ShaderMaterial;
116
+ readonly quadScene: Scene;
117
+ readonly quadCamera: OrthographicCamera;
118
+ /** The canvas's multisample count, read once at construction and kept across resizes. */
119
+ readonly samples: number;
120
+ /**
121
+ * The renderer's tone-mapping curve when these resources were built.
122
+ *
123
+ * Kept for the same reason `renderer` is, and checked the same way. Every lit material this
124
+ * package draws carries its own copy of the curve, injected by `onBeforeCompile` from
125
+ * `renderer.toneMapping` — and three calls that ONCE PER PROGRAM, then serves the compiled
126
+ * program out of its cache. `customProgramCacheKey` cannot repair that: three computes the cache
127
+ * key before the material has ever seen a renderer, so the key could only ever carry the curve
128
+ * of a PREVIOUS compile, and a genuine change would still hit the stale program. So the curve is
129
+ * asserted constant instead of keyed — which is the truth of this renderer anyway, since fiber
130
+ * sets it from `flat` at canvas construction and nothing in this package writes it afterwards.
131
+ */
132
+ readonly toneMapping: number;
133
+ /**
134
+ * One frame's grain lattice, as a float texture the composite samples.
135
+ *
136
+ * Owned per instance like everything else here, and refreshed only when the frame's seed changes
137
+ * — which is every frame a shot with grain renders, since `grainSeed` re-seeds per frame, and
138
+ * never for a shot without it.
139
+ */
140
+ readonly grainLattice: DataTexture;
141
+ private grainLatticeSeed;
142
+ private readonly geometry;
143
+ private readonly mesh;
144
+ private releaseMeasurement;
145
+ constructor(gl: FocusRenderer, width: number, height: number, registerActual?: SceneActualResourceRegistrarV1);
146
+ get size(): {
147
+ width: number;
148
+ height: number;
149
+ };
150
+ /**
151
+ * Follow the frame. `WebGLRenderTarget.setSize` resizes its colour textures but not the depth
152
+ * texture attached to it, which would leave the depth attachment at the old size and the
153
+ * framebuffer incomplete — so the depth texture is resized here and dropped, and Three rebuilds
154
+ * both from the new sizes on the next draw.
155
+ */
156
+ resize(width: number, height: number): void;
157
+ /** Point the quad at one of the two materials; the pass draws the same geometry twice. */
158
+ use(material: ShaderMaterial): void;
159
+ /** Write one frame's focus into both materials. Uniform writes only: no program is rebuilt. */
160
+ apply(uniforms: FocusPassUniforms): void;
161
+ /**
162
+ * Write one frame's finishing into the composite material.
163
+ *
164
+ * Uniform writes and, when the seed moved, one 25 KB texture upload; no program is rebuilt. The
165
+ * lattice is skipped when grain is off, because nothing samples it then.
166
+ */
167
+ applyFinishing(finishing: SceneFinishingUniforms): void;
168
+ dispose(): void;
169
+ }
170
+ /**
171
+ * Draw one frame of the world, in place of the renderer's ordinary draw.
172
+ *
173
+ * The world is drawn once, into a colour target with the depth it was drawn with; the gather runs
174
+ * horizontally into the second target and then vertically into whatever target was bound when the
175
+ * pass began — the frame, ordinarily. Screen text never enters this: it is DOM above the canvas,
176
+ * so it cannot be softened by the pass, which is what the contract requires of it.
177
+ *
178
+ * This is the only way a scene shot's world reaches the frame. A shot with focus and a shot
179
+ * without run exactly these three draws with exactly these targets; the authored focus reaches the
180
+ * picture through `uniforms` alone, and a maximum blur of zero makes the two gathers the identity.
181
+ * That is what makes `post.focus` a blur and only a blur: the alternative — the world straight onto
182
+ * the canvas when no focus is authored — composites in a different space (clamped 8-bit sRGB with
183
+ * the renderer's tone curve, resolved by the canvas's own multisample) and so changed the colour
184
+ * of in-focus pixels the moment focus was turned on.
185
+ *
186
+ * The third draw also finishes the world: the shot's grain and vignette are the composite's last
187
+ * stage, because the world cannot be routed through the SVG filter that finishes the shot's DOM
188
+ * layers without putting the WebGL canvas inside a filtered layer — which is what defect D4 was.
189
+ */
190
+ export declare function renderFocusPass(gl: FocusRenderer, scene: unknown, camera: unknown, resources: FocusResources, uniforms: FocusPassUniforms, finishing: SceneFinishingUniforms): void;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The GLSL for the depth-aware focus pass, kept in one small module so the two materials share one
3
+ * gather and the node tests can assert what the pass declares without a GPU.
4
+ *
5
+ * There is no shader package here and none is needed: two `ShaderMaterial` full-screen quads.
6
+ */
7
+ /** A full-screen quad in clip space; the geometry is already `[-1,1]`, so no matrices are needed. */
8
+ export declare const FOCUS_VERTEX_SHADER = "\nvarying vec2 vUv;\nvoid main() {\n vUv = uv;\n gl_Position = vec4(position.xy, 0.0, 1.0);\n}\n";
9
+ /**
10
+ * The shared half of both fragment shaders: reconstruct camera-space distance from the depth
11
+ * buffer, turn it into a circle of confusion, and gather along one axis.
12
+ *
13
+ * Depth-aware in both directions. The gather reaches out to the centre pixel's own circle of
14
+ * confusion, so an out-of-focus surface is softened by exactly its own radius and an in-focus one
15
+ * is left alone — at radius zero every tap lands on the centre pixel and the result is the centre
16
+ * pixel. A tap NEARER than the centre contributes only if its own circle of confusion reaches the
17
+ * centre, which is what keeps a sharp foreground from smearing across a blurred background; a tap
18
+ * at or beyond the centre's depth is inside the centre's own circle by construction and always
19
+ * contributes.
20
+ *
21
+ * The known limit of a two-pass gather: a blurred foreground softens inside its silhouette but
22
+ * does not spill past it onto an in-focus background, because nothing outside the centre's own
23
+ * radius is ever sampled. A scattering pass is the fix if a fixture ever needs that spill.
24
+ *
25
+ * Alpha: the colour target holds premultiplied RGBA — Three's normal blending accumulates
26
+ * `src.rgb * src.a` and `src.a` into a target cleared to zero — and a weighted average of
27
+ * premultiplied samples is itself premultiplied. Blurring here therefore cannot pull colour out of
28
+ * a transparent texel, which is exactly the dark fringe a straight-alpha blur would produce around
29
+ * a shot with a transparent backdrop.
30
+ */
31
+ export declare const FOCUS_GATHER_CHUNK = "\nuniform sampler2D tColor;\nuniform sampler2D tDepth;\nuniform vec2 uTexel;\nuniform vec2 uDirection;\nuniform float uNear;\nuniform float uFar;\nuniform float uFocusDistance;\nuniform float uFocusRange;\nuniform float uMaxBlur;\nvarying vec2 vUv;\n\nfloat focusViewDistance(vec2 uv) {\n float depth = texture2D(tDepth, uv).x;\n return -((uNear * uFar) / ((uFar - uNear) * depth - uFar));\n}\n\nfloat focusCircleOfConfusion(float distance) {\n return min(1.0, abs(distance - uFocusDistance) / uFocusRange) * uMaxBlur;\n}\n\nvoid focusTap(vec2 offset, float radius, float weight, float centreDistance, inout vec4 sum, inout float total) {\n vec2 uv = vUv + offset;\n float tapDistance = focusViewDistance(uv);\n float allow = tapDistance < centreDistance ? step(radius, focusCircleOfConfusion(tapDistance)) : 1.0;\n float w = weight * allow;\n sum += texture2D(tColor, uv) * w;\n total += w;\n}\n\nvec4 focusGather() {\n float centreDistance = focusViewDistance(vUv);\n float centreRadius = focusCircleOfConfusion(centreDistance);\n vec4 sum = texture2D(tColor, vUv);\n float total = 1.0;\n for (int i = 1; i <= FOCUS_TAPS; i++) {\n float t = float(i) / float(FOCUS_TAPS);\n float weight = exp(-2.0 * t * t);\n float radius = t * centreRadius;\n vec2 offset = uDirection * uTexel * radius;\n focusTap(offset, radius, weight, centreDistance, sum, total);\n focusTap(-offset, radius, weight, centreDistance, sum, total);\n }\n return sum / total;\n}\n";
32
+ /** The first pass: gather along one axis, target to target, both in the working colour space. */
33
+ export declare const FOCUS_BLUR_FRAGMENT_SHADER = "\nuniform sampler2D tColor;\nuniform sampler2D tDepth;\nuniform vec2 uTexel;\nuniform vec2 uDirection;\nuniform float uNear;\nuniform float uFar;\nuniform float uFocusDistance;\nuniform float uFocusRange;\nuniform float uMaxBlur;\nvarying vec2 vUv;\n\nfloat focusViewDistance(vec2 uv) {\n float depth = texture2D(tDepth, uv).x;\n return -((uNear * uFar) / ((uFar - uNear) * depth - uFar));\n}\n\nfloat focusCircleOfConfusion(float distance) {\n return min(1.0, abs(distance - uFocusDistance) / uFocusRange) * uMaxBlur;\n}\n\nvoid focusTap(vec2 offset, float radius, float weight, float centreDistance, inout vec4 sum, inout float total) {\n vec2 uv = vUv + offset;\n float tapDistance = focusViewDistance(uv);\n float allow = tapDistance < centreDistance ? step(radius, focusCircleOfConfusion(tapDistance)) : 1.0;\n float w = weight * allow;\n sum += texture2D(tColor, uv) * w;\n total += w;\n}\n\nvec4 focusGather() {\n float centreDistance = focusViewDistance(vUv);\n float centreRadius = focusCircleOfConfusion(centreDistance);\n vec4 sum = texture2D(tColor, vUv);\n float total = 1.0;\n for (int i = 1; i <= FOCUS_TAPS; i++) {\n float t = float(i) / float(FOCUS_TAPS);\n float weight = exp(-2.0 * t * t);\n float radius = t * centreRadius;\n vec2 offset = uDirection * uTexel * radius;\n focusTap(offset, radius, weight, centreDistance, sum, total);\n focusTap(-offset, radius, weight, centreDistance, sum, total);\n }\n return sum / total;\n}\n\nvoid main() {\n gl_FragColor = focusGather();\n}\n";
34
+ /**
35
+ * The shot's finishing, for the world only: the same grain and the same vignette the SVG filter
36
+ * puts on the DOM layers (`finishing.tsx`), evaluated per pixel here because a `filter` over a
37
+ * layer holding a WebGL canvas is what let Chromium tile one raster of a shot across six frames
38
+ * (defect D4). Nothing about the treatment changes; only who applies it to the world.
39
+ *
40
+ * Everything is in the frame's own pixels with y down, so the two halves are laid out in one
41
+ * coordinate system. The grain is `grainNoise.ts`'s port of the `feTurbulence` generator, seeded by
42
+ * the same `grainSeed(seed, frame)` integer, greyed and levelled exactly as the filter's
43
+ * `feColorMatrix`/`feComponentTransfer` pair does, then overlay-blended; the vignette is
44
+ * `finishingMath.ts`'s Gaussian coverage of the same flooded core, multiplied in. The lattice for
45
+ * one frame's seed arrives as a float texture rather than a uniform array: 514 selectors and three
46
+ * channels of gradients do not fit in a fragment shader's uniform budget on every host.
47
+ *
48
+ * The stage runs on the ENCODED colour, after `colorspace_fragment`, because that is the space the
49
+ * filter runs in (`color-interpolation-filters="sRGB"`), and on the colour alone rather than the
50
+ * colour times its coverage, because the filter's closing `feComposite in` restores coverage after
51
+ * the treatment. It clamps first for the same reason: the filter's source is an 8-bit layer.
52
+ */
53
+ export declare const FOCUS_FINISHING_CHUNK = "\nuniform float uGrain;\nuniform float uVignette;\nuniform vec2 uFrameSize;\n/** The stitched base frequency, per axis: cycles per output pixel. */\nuniform vec2 uGrainBase;\n/** The stitch: lattice period in x and y, then the wrap point in x and y. */\nuniform vec4 uGrainStitch;\n/** The vignette core rectangle: left, top, right, bottom, in frame pixels. */\nuniform vec4 uVignetteCore;\nuniform vec2 uVignetteSigma;\nuniform sampler2D tGrainLattice;\n\nconst float SCENE_SQRT2 = 1.4142135623730951;\n\n/** Abramowitz\u2013Stegun 7.1.26, the series finishingMath.ts evaluates, sign and all. */\nfloat sceneErf(float x) {\n float s = sign(x);\n float a = abs(x);\n float t = 1.0 / (1.0 + 0.3275911 * a);\n float y = 1.0 - (((((1.061405429 * t - 1.453152027) * t) + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * exp(-a * a);\n return s * y;\n}\n\nfloat sceneBlurredCoverage(float a, float b, float sigma, float p) {\n return 0.5 * (sceneErf((b - p) / (sigma * SCENE_SQRT2)) - sceneErf((a - p) / (sigma * SCENE_SQRT2)));\n}\n\nfloat sceneVignetteFactor(vec2 point) {\n float coverage = sceneBlurredCoverage(uVignetteCore.x, uVignetteCore.z, uVignetteSigma.x, point.x)\n * sceneBlurredCoverage(uVignetteCore.y, uVignetteCore.w, uVignetteSigma.y, point.y);\n return uVignette * coverage + (1.0 - uVignette);\n}\n\nfloat sceneGrainSelector(float index) {\n return texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 0.5 / float(GRAIN_TABLE_HEIGHT))).r;\n}\n\n/** One lattice corner's gradient dotted with (rx, ry), for the three channels the grey averages. */\nvec3 sceneGrainCorner(float index, float rx, float ry) {\n vec4 ab = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 1.5 / float(GRAIN_TABLE_HEIGHT)));\n vec2 c = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 2.5 / float(GRAIN_TABLE_HEIGHT))).rg;\n return vec3(rx * ab.x + ry * ab.y, rx * ab.z + ry * ab.w, rx * c.x + ry * c.y);\n}\n\n/** The spec's noise2 for three channels at once, with the stitch wrap already folded. */\nvec3 sceneGrainNoise(vec2 v, vec4 stitch) {\n float bx0 = floor(v.x), bx1 = bx0 + 1.0;\n float rx0 = v.x - bx0, rx1 = rx0 - 1.0;\n float by0 = floor(v.y), by1 = by0 + 1.0;\n float ry0 = v.y - by0, ry1 = ry0 - 1.0;\n if (bx0 >= stitch.z) bx0 -= stitch.x;\n if (bx1 >= stitch.z) bx1 -= stitch.x;\n if (by0 >= stitch.w) by0 -= stitch.y;\n if (by1 >= stitch.w) by1 -= stitch.y;\n bx0 = mod(bx0, float(GRAIN_LATTICE));\n bx1 = mod(bx1, float(GRAIN_LATTICE));\n by0 = mod(by0, float(GRAIN_LATTICE));\n by1 = mod(by1, float(GRAIN_LATTICE));\n float i = sceneGrainSelector(bx0);\n float j = sceneGrainSelector(bx1);\n float sx = rx0 * rx0 * (3.0 - 2.0 * rx0);\n float sy = ry0 * ry0 * (3.0 - 2.0 * ry0);\n vec3 a = mix(sceneGrainCorner(sceneGrainSelector(i + by0), rx0, ry0), sceneGrainCorner(sceneGrainSelector(j + by0), rx1, ry0), sx);\n vec3 b = mix(sceneGrainCorner(sceneGrainSelector(i + by1), rx0, ry1), sceneGrainCorner(sceneGrainSelector(j + by1), rx1, ry1), sx);\n return mix(a, b, sy);\n}\n\n/** type=\"fractalNoise\" over two octaves, greyed by the filter's own 0.3333 coefficient. */\nfloat sceneGrainField(vec2 point) {\n vec2 v = point * uGrainBase;\n vec4 stitch = uGrainStitch;\n vec3 sum = vec3(0.0);\n float ratio = 1.0;\n for (int octave = 0; octave < GRAIN_OCTAVES; octave++) {\n sum += sceneGrainNoise(v, stitch) / ratio;\n v *= 2.0;\n ratio *= 2.0;\n stitch *= 2.0;\n }\n vec3 fractal = (sum + 1.0) * 0.5;\n return clamp((fractal.x + fractal.y + fractal.z) * GRAIN_GREY_COEFFICIENT, 0.0, 1.0);\n}\n\n/** feBlend mode=\"overlay\": the CSS blend formula, switching on the backdrop. */\nvec3 sceneOverlay(vec3 backdrop, float source) {\n vec3 lo = 2.0 * backdrop * source;\n vec3 hi = 1.0 - 2.0 * (1.0 - backdrop) * (1.0 - source);\n return mix(hi, lo, step(backdrop, vec3(0.5)));\n}\n\nvec3 sceneFinishing(vec3 color) {\n if (uGrain <= 0.0 && uVignette <= 0.0) return color;\n // The pixel's top-left corner in the frame's own pixels, y down: the space both halves share.\n vec2 pixel = vec2(gl_FragCoord.x - 0.5, uFrameSize.y - gl_FragCoord.y - 0.5);\n vec3 finished = clamp(color, 0.0, 1.0);\n if (uGrain > 0.0) {\n float level = uGrain * sceneGrainField(pixel + float(GRAIN_SAMPLE_OFFSET)) + (1.0 - uGrain) * 0.5;\n finished = sceneOverlay(finished, level);\n }\n if (uVignette > 0.0) {\n finished *= sceneVignetteFactor(pixel + 0.5);\n }\n return finished;\n}\n";
54
+ /**
55
+ * The second pass: gather along the other axis, finish the world, and write the frame.
56
+ *
57
+ * The colour arrives premultiplied and linear and has to leave premultiplied and encoded, and the
58
+ * transfer function belongs on the colour, not on the colour times its coverage — so the alpha is
59
+ * divided out, `colorspace_fragment` encodes into the renderer's output colour space, the shot's
60
+ * grain and vignette are applied to that encoded colour, and the coverage is put back. The canvas
61
+ * is a premultiplied surface, so that is what it wants; a transparent shot keeps the coverage it
62
+ * had, with no colour pulled toward black at its edges and none acquired from the finishing.
63
+ *
64
+ * Finishing last and coverage after it is the same order the filter states: treat, then
65
+ * `feComposite in` back to the source's own alpha. With both treatments off, `sceneFinishing`
66
+ * returns before it touches the colour and this is the pass it was before.
67
+ */
68
+ export declare const FOCUS_COMPOSITE_FRAGMENT_SHADER = "\nuniform sampler2D tColor;\nuniform sampler2D tDepth;\nuniform vec2 uTexel;\nuniform vec2 uDirection;\nuniform float uNear;\nuniform float uFar;\nuniform float uFocusDistance;\nuniform float uFocusRange;\nuniform float uMaxBlur;\nvarying vec2 vUv;\n\nfloat focusViewDistance(vec2 uv) {\n float depth = texture2D(tDepth, uv).x;\n return -((uNear * uFar) / ((uFar - uNear) * depth - uFar));\n}\n\nfloat focusCircleOfConfusion(float distance) {\n return min(1.0, abs(distance - uFocusDistance) / uFocusRange) * uMaxBlur;\n}\n\nvoid focusTap(vec2 offset, float radius, float weight, float centreDistance, inout vec4 sum, inout float total) {\n vec2 uv = vUv + offset;\n float tapDistance = focusViewDistance(uv);\n float allow = tapDistance < centreDistance ? step(radius, focusCircleOfConfusion(tapDistance)) : 1.0;\n float w = weight * allow;\n sum += texture2D(tColor, uv) * w;\n total += w;\n}\n\nvec4 focusGather() {\n float centreDistance = focusViewDistance(vUv);\n float centreRadius = focusCircleOfConfusion(centreDistance);\n vec4 sum = texture2D(tColor, vUv);\n float total = 1.0;\n for (int i = 1; i <= FOCUS_TAPS; i++) {\n float t = float(i) / float(FOCUS_TAPS);\n float weight = exp(-2.0 * t * t);\n float radius = t * centreRadius;\n vec2 offset = uDirection * uTexel * radius;\n focusTap(offset, radius, weight, centreDistance, sum, total);\n focusTap(-offset, radius, weight, centreDistance, sum, total);\n }\n return sum / total;\n}\n\n\nuniform float uGrain;\nuniform float uVignette;\nuniform vec2 uFrameSize;\n/** The stitched base frequency, per axis: cycles per output pixel. */\nuniform vec2 uGrainBase;\n/** The stitch: lattice period in x and y, then the wrap point in x and y. */\nuniform vec4 uGrainStitch;\n/** The vignette core rectangle: left, top, right, bottom, in frame pixels. */\nuniform vec4 uVignetteCore;\nuniform vec2 uVignetteSigma;\nuniform sampler2D tGrainLattice;\n\nconst float SCENE_SQRT2 = 1.4142135623730951;\n\n/** Abramowitz\u2013Stegun 7.1.26, the series finishingMath.ts evaluates, sign and all. */\nfloat sceneErf(float x) {\n float s = sign(x);\n float a = abs(x);\n float t = 1.0 / (1.0 + 0.3275911 * a);\n float y = 1.0 - (((((1.061405429 * t - 1.453152027) * t) + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * exp(-a * a);\n return s * y;\n}\n\nfloat sceneBlurredCoverage(float a, float b, float sigma, float p) {\n return 0.5 * (sceneErf((b - p) / (sigma * SCENE_SQRT2)) - sceneErf((a - p) / (sigma * SCENE_SQRT2)));\n}\n\nfloat sceneVignetteFactor(vec2 point) {\n float coverage = sceneBlurredCoverage(uVignetteCore.x, uVignetteCore.z, uVignetteSigma.x, point.x)\n * sceneBlurredCoverage(uVignetteCore.y, uVignetteCore.w, uVignetteSigma.y, point.y);\n return uVignette * coverage + (1.0 - uVignette);\n}\n\nfloat sceneGrainSelector(float index) {\n return texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 0.5 / float(GRAIN_TABLE_HEIGHT))).r;\n}\n\n/** One lattice corner's gradient dotted with (rx, ry), for the three channels the grey averages. */\nvec3 sceneGrainCorner(float index, float rx, float ry) {\n vec4 ab = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 1.5 / float(GRAIN_TABLE_HEIGHT)));\n vec2 c = texture2D(tGrainLattice, vec2((index + 0.5) / float(GRAIN_TABLE_WIDTH), 2.5 / float(GRAIN_TABLE_HEIGHT))).rg;\n return vec3(rx * ab.x + ry * ab.y, rx * ab.z + ry * ab.w, rx * c.x + ry * c.y);\n}\n\n/** The spec's noise2 for three channels at once, with the stitch wrap already folded. */\nvec3 sceneGrainNoise(vec2 v, vec4 stitch) {\n float bx0 = floor(v.x), bx1 = bx0 + 1.0;\n float rx0 = v.x - bx0, rx1 = rx0 - 1.0;\n float by0 = floor(v.y), by1 = by0 + 1.0;\n float ry0 = v.y - by0, ry1 = ry0 - 1.0;\n if (bx0 >= stitch.z) bx0 -= stitch.x;\n if (bx1 >= stitch.z) bx1 -= stitch.x;\n if (by0 >= stitch.w) by0 -= stitch.y;\n if (by1 >= stitch.w) by1 -= stitch.y;\n bx0 = mod(bx0, float(GRAIN_LATTICE));\n bx1 = mod(bx1, float(GRAIN_LATTICE));\n by0 = mod(by0, float(GRAIN_LATTICE));\n by1 = mod(by1, float(GRAIN_LATTICE));\n float i = sceneGrainSelector(bx0);\n float j = sceneGrainSelector(bx1);\n float sx = rx0 * rx0 * (3.0 - 2.0 * rx0);\n float sy = ry0 * ry0 * (3.0 - 2.0 * ry0);\n vec3 a = mix(sceneGrainCorner(sceneGrainSelector(i + by0), rx0, ry0), sceneGrainCorner(sceneGrainSelector(j + by0), rx1, ry0), sx);\n vec3 b = mix(sceneGrainCorner(sceneGrainSelector(i + by1), rx0, ry1), sceneGrainCorner(sceneGrainSelector(j + by1), rx1, ry1), sx);\n return mix(a, b, sy);\n}\n\n/** type=\"fractalNoise\" over two octaves, greyed by the filter's own 0.3333 coefficient. */\nfloat sceneGrainField(vec2 point) {\n vec2 v = point * uGrainBase;\n vec4 stitch = uGrainStitch;\n vec3 sum = vec3(0.0);\n float ratio = 1.0;\n for (int octave = 0; octave < GRAIN_OCTAVES; octave++) {\n sum += sceneGrainNoise(v, stitch) / ratio;\n v *= 2.0;\n ratio *= 2.0;\n stitch *= 2.0;\n }\n vec3 fractal = (sum + 1.0) * 0.5;\n return clamp((fractal.x + fractal.y + fractal.z) * GRAIN_GREY_COEFFICIENT, 0.0, 1.0);\n}\n\n/** feBlend mode=\"overlay\": the CSS blend formula, switching on the backdrop. */\nvec3 sceneOverlay(vec3 backdrop, float source) {\n vec3 lo = 2.0 * backdrop * source;\n vec3 hi = 1.0 - 2.0 * (1.0 - backdrop) * (1.0 - source);\n return mix(hi, lo, step(backdrop, vec3(0.5)));\n}\n\nvec3 sceneFinishing(vec3 color) {\n if (uGrain <= 0.0 && uVignette <= 0.0) return color;\n // The pixel's top-left corner in the frame's own pixels, y down: the space both halves share.\n vec2 pixel = vec2(gl_FragCoord.x - 0.5, uFrameSize.y - gl_FragCoord.y - 0.5);\n vec3 finished = clamp(color, 0.0, 1.0);\n if (uGrain > 0.0) {\n float level = uGrain * sceneGrainField(pixel + float(GRAIN_SAMPLE_OFFSET)) + (1.0 - uGrain) * 0.5;\n finished = sceneOverlay(finished, level);\n }\n if (uVignette > 0.0) {\n finished *= sceneVignetteFactor(pixel + 0.5);\n }\n return finished;\n}\n\nvoid main() {\n vec4 gathered = focusGather();\n float coverage = gathered.a;\n gl_FragColor = vec4(coverage > 0.0 ? gathered.rgb / coverage : gathered.rgb, coverage);\n #include <colorspace_fragment>\n gl_FragColor.rgb = sceneFinishing(gl_FragColor.rgb);\n gl_FragColor.rgb *= coverage;\n}\n";
@@ -0,0 +1,27 @@
1
+ /** The subset of `document.fonts` this renderer uses; a test supplies a double. */
2
+ export interface FontSource {
3
+ load(font: string, text?: string): Promise<unknown>;
4
+ check(font: string, text?: string): boolean;
5
+ ready: Promise<unknown>;
6
+ }
7
+ /** `document.fonts`, or null where there is no document (server rendering, node tests). */
8
+ export declare function documentFonts(): FontSource | null;
9
+ /**
10
+ * Resolve once the face named by a CSS `font` shorthand can be drawn with.
11
+ *
12
+ * Deterministic and event-driven: `load` for the exact face and sample text, then the source's own
13
+ * `ready`, which settles when nothing is still loading. No timer and no polling — a timeout would
14
+ * make the frame's content depend on how fast the machine was.
15
+ *
16
+ * A rejected load is the author's problem and is reported as one: a face the shot names but the
17
+ * runtime cannot produce would otherwise be silently replaced by a fallback and captured. So is a
18
+ * host with no font source at all: the raster would then be drawn with whatever face the canvas
19
+ * happened to fall back to, which is the same silent substitution arriving by a different route.
20
+ * The world-text path only runs where a canvas is mounted, so a null source means the host is not
21
+ * one this renderer can draw text on, not that the check may be skipped.
22
+ *
23
+ * Note the limit: `check` returns true for a family with no registered face (the browser treats it
24
+ * as a system font), so this cannot by itself prove the authored face is the one that drew. Sealing
25
+ * the font set is the preparation stage's job; this is the render-time gate.
26
+ */
27
+ export declare function whenFontReady(fonts: FontSource | null, shorthand: string, sample: string, path: string): Promise<void>;