@babylonjs/lite 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/{_mat4-storage-f64-Bvh5TymE.js → _mat4-storage-f64-CjDoht2w.js} +3 -2
  2. package/_mat4-storage-f64-CjDoht2w.js.map +1 -0
  3. package/{alpha-test-fragment-BCChpzaV.js → alpha-test-fragment-B7DjSnF7.js} +2 -2
  4. package/{alpha-test-fragment-BCChpzaV.js.map → alpha-test-fragment-B7DjSnF7.js.map} +1 -1
  5. package/assets/splat-sort-worker-DT3eybMZ.js.map +1 -0
  6. package/{background-dds-skybox-ZjrSIxrT.js → background-dds-skybox-BEX309u3.js} +13 -13
  7. package/background-dds-skybox-BEX309u3.js.map +1 -0
  8. package/{background-ground-B2Mie-MI.js → background-ground-BU0HOcM4.js} +19 -19
  9. package/background-ground-BU0HOcM4.js.map +1 -0
  10. package/{background-hdr-skybox-DDRJYuT2.js → background-hdr-skybox--RRRic_K.js} +10 -10
  11. package/background-hdr-skybox--RRRic_K.js.map +1 -0
  12. package/{background-solid-skybox-fjXlnWaD.js → background-solid-skybox-BrH2fXSu.js} +11 -12
  13. package/background-solid-skybox-BrH2fXSu.js.map +1 -0
  14. package/{billboard-renderable-DKmlOgbM.js → billboard-renderable-BHWryAeC.js} +46 -10
  15. package/billboard-renderable-BHWryAeC.js.map +1 -0
  16. package/{clamp-block-CxRBPlUq.js → clamp-block-DqbwnQGW.js} +2 -2
  17. package/{clamp-block-CxRBPlUq.js.map → clamp-block-DqbwnQGW.js.map} +1 -1
  18. package/{clearcoat-fragment-KbZAa0TA.js → clearcoat-fragment-D6FSCie1.js} +2 -2
  19. package/{clearcoat-fragment-KbZAa0TA.js.map → clearcoat-fragment-D6FSCie1.js.map} +1 -1
  20. package/{create-skeleton-BBI5urcj.js → create-skeleton-D_uplboC.js} +9 -9
  21. package/create-skeleton-D_uplboC.js.map +1 -0
  22. package/{cubemap-skybox-material-DvW81drX.js → cubemap-skybox-material-DQcMMdf-.js} +6 -7
  23. package/cubemap-skybox-material-DQcMMdf-.js.map +1 -0
  24. package/{curve-block-Dh_xdUj-.js → curve-block-21rT0JjG.js} +2 -2
  25. package/{curve-block-Dh_xdUj-.js.map → curve-block-21rT0JjG.js.map} +1 -1
  26. package/{emissive-fragment-DD8cvHyx.js → emissive-fragment-C5FtBs3y.js} +3 -3
  27. package/emissive-fragment-C5FtBs3y.js.map +1 -0
  28. package/{esm-shadow-view-DYAc62Kl.js → esm-shadow-view-Cl3rPGof.js} +2 -2
  29. package/{esm-shadow-view-DYAc62Kl.js.map → esm-shadow-view-Cl3rPGof.js.map} +1 -1
  30. package/{esm-shadow-view-DHVS9r7H.js → esm-shadow-view-Gtd1LWRP.js} +2 -2
  31. package/{esm-shadow-view-DHVS9r7H.js.map → esm-shadow-view-Gtd1LWRP.js.map} +1 -1
  32. package/{esm-shadow-view-15S4JK6p.js → esm-shadow-view-c5YV4Eg9.js} +2 -2
  33. package/{esm-shadow-view-15S4JK6p.js.map → esm-shadow-view-c5YV4Eg9.js.map} +1 -1
  34. package/{gaussian-splatting-pipeline-sh-BvkUhA9V.js → gaussian-splatting-pipeline-sh-7J31V23x.js} +19 -19
  35. package/gaussian-splatting-pipeline-sh-7J31V23x.js.map +1 -0
  36. package/geometry-texture-output-dXk4E9uu.js +41 -0
  37. package/geometry-texture-output-dXk4E9uu.js.map +1 -0
  38. package/geometry-view-BsFJpBJa.js +404 -0
  39. package/geometry-view-BsFJpBJa.js.map +1 -0
  40. package/{gltf-animation-KnPzeOIY.js → gltf-animation-K_zZxj_d.js} +6 -6
  41. package/gltf-animation-K_zZxj_d.js.map +1 -0
  42. package/{gltf-ext-basisu-kmth3UWX.js → gltf-ext-basisu-CDbPclzZ.js} +48 -16
  43. package/gltf-ext-basisu-CDbPclzZ.js.map +1 -0
  44. package/{gltf-ext-node-visibility-BjRRd6si.js → gltf-ext-node-visibility-DXCJEYr6.js} +2 -2
  45. package/{gltf-ext-node-visibility-BjRRd6si.js.map → gltf-ext-node-visibility-DXCJEYr6.js.map} +1 -1
  46. package/{gltf-ext-quantization-CpZyLDIz.js → gltf-ext-quantization-CvHI_0Vg.js} +4 -3
  47. package/gltf-ext-quantization-CvHI_0Vg.js.map +1 -0
  48. package/{gltf-ext-uv-transform-MHmR-YyM.js → gltf-ext-uv-transform-DgYazJBs.js} +2 -2
  49. package/{gltf-ext-uv-transform-MHmR-YyM.js.map → gltf-ext-uv-transform-DgYazJBs.js.map} +1 -1
  50. package/{gltf-feature-animation-pointer-rFqLfbO_.js → gltf-feature-animation-pointer-D1RJRFBw.js} +9 -9
  51. package/gltf-feature-animation-pointer-D1RJRFBw.js.map +1 -0
  52. package/{gltf-feature-animations-DikONdzi.js → gltf-feature-animations-Cmc1uoIu.js} +2 -2
  53. package/{gltf-feature-animations-DikONdzi.js.map → gltf-feature-animations-Cmc1uoIu.js.map} +1 -1
  54. package/{gltf-feature-draco-yGSMGTE3.js → gltf-feature-draco-CKKzT5E3.js} +6 -5
  55. package/gltf-feature-draco-CKKzT5E3.js.map +1 -0
  56. package/{gltf-feature-gpu-instancing-Cj1XjmM6.js → gltf-feature-gpu-instancing-n87SO6Vh.js} +4 -4
  57. package/gltf-feature-gpu-instancing-n87SO6Vh.js.map +1 -0
  58. package/{gltf-feature-lights-punctual-C-0SlGmD.js → gltf-feature-lights-punctual-Ckm3ciL8.js} +5 -5
  59. package/{gltf-feature-lights-punctual-C-0SlGmD.js.map → gltf-feature-lights-punctual-Ckm3ciL8.js.map} +1 -1
  60. package/{gltf-feature-meshopt-Des96YFI.js → gltf-feature-meshopt-DLC4SF1E.js} +7 -6
  61. package/gltf-feature-meshopt-DLC4SF1E.js.map +1 -0
  62. package/{gltf-feature-morph-BAcY14XU.js → gltf-feature-morph-Cjtu7hYa.js} +4 -4
  63. package/gltf-feature-morph-Cjtu7hYa.js.map +1 -0
  64. package/{gltf-feature-registry-97sY_x5O.js → gltf-feature-registry-C63Hjp9w.js} +15 -15
  65. package/{gltf-feature-registry-97sY_x5O.js.map → gltf-feature-registry-C63Hjp9w.js.map} +1 -1
  66. package/{gltf-feature-skeleton-lVjkDfIU.js → gltf-feature-skeleton-DKbOGidp.js} +3 -3
  67. package/{gltf-feature-skeleton-lVjkDfIU.js.map → gltf-feature-skeleton-DKbOGidp.js.map} +1 -1
  68. package/{gltf-feature-variants-BphF4JmV.js → gltf-feature-variants-Cmzu0O0e.js} +2 -2
  69. package/{gltf-feature-variants-BphF4JmV.js.map → gltf-feature-variants-Cmzu0O0e.js.map} +1 -1
  70. package/{gltf-glb-parser-D6UZWFuC.js → gltf-glb-parser-Cj5MHS-v.js} +5 -4
  71. package/gltf-glb-parser-Cj5MHS-v.js.map +1 -0
  72. package/{gltf-interleave-C9eBqH_F.js → gltf-interleave-gHf9_t0i.js} +14 -14
  73. package/gltf-interleave-gHf9_t0i.js.map +1 -0
  74. package/{gltf-pbr-builder-ext-DPC0zg_u.js → gltf-pbr-builder-ext-edNcjwPf.js} +5 -5
  75. package/gltf-pbr-builder-ext-edNcjwPf.js.map +1 -0
  76. package/{gltf-variants-CnBEZr0o.js → gltf-variants-CPxNdtP4.js} +4 -4
  77. package/{gltf-variants-CnBEZr0o.js.map → gltf-variants-CPxNdtP4.js.map} +1 -1
  78. package/{gs-picking-pipeline-Bx8LTav6.js → gs-picking-pipeline-DYaW_Lg3.js} +14 -14
  79. package/gs-picking-pipeline-DYaW_Lg3.js.map +1 -0
  80. package/havok-floating-origin-Dr-18Nds.js +198 -0
  81. package/havok-floating-origin-Dr-18Nds.js.map +1 -0
  82. package/index-CLElg2Bo.js +39209 -0
  83. package/index-CLElg2Bo.js.map +1 -0
  84. package/index-CYZDclhF.js +918 -0
  85. package/index-CYZDclhF.js.map +1 -0
  86. package/index-SMJ67XwT.js +3330 -0
  87. package/index-SMJ67XwT.js.map +1 -0
  88. package/index.d.ts +2007 -105
  89. package/index.js +446 -322
  90. package/{input-block-Coi_aZwl.js → input-block-DqEedWF2.js} +2 -2
  91. package/{input-block-Coi_aZwl.js.map → input-block-DqEedWF2.js.map} +1 -1
  92. package/{iridescence-fragment-DwZcCTdD.js → iridescence-fragment-BHU59-gQ.js} +2 -2
  93. package/{iridescence-fragment-DwZcCTdD.js.map → iridescence-fragment-BHU59-gQ.js.map} +1 -1
  94. package/{light-block-Np_h5gPI.js → light-block-Bv37V8vl.js} +2 -2
  95. package/{light-block-Np_h5gPI.js.map → light-block-Bv37V8vl.js.map} +1 -1
  96. package/{loop-block-BFkLFYGm.js → loop-block-qTg8vb99.js} +2 -2
  97. package/{loop-block-BFkLFYGm.js.map → loop-block-qTg8vb99.js.map} +1 -1
  98. package/{morph-fragment-DqH-w61u.js → morph-fragment-BRCUr2wQ.js} +2 -2
  99. package/{morph-fragment-DqH-w61u.js.map → morph-fragment-BRCUr2wQ.js.map} +1 -1
  100. package/{multilight-wgsl-B9Mf9d-q.js → multilight-wgsl-DMeppAdZ.js} +2 -2
  101. package/{multilight-wgsl-B9Mf9d-q.js.map → multilight-wgsl-DMeppAdZ.js.map} +1 -1
  102. package/{node-env-BPZXZzBf.js → node-env-Bc559GmY.js} +6 -5
  103. package/node-env-Bc559GmY.js.map +1 -0
  104. package/node-geometry-view-COmWsRXK.js +291 -0
  105. package/node-geometry-view-COmWsRXK.js.map +1 -0
  106. package/{node-registry-extra-compat-Ch7ApZHF.js → node-registry-extra-compat-dWrv7gpS.js} +2 -2
  107. package/{node-registry-extra-compat-Ch7ApZHF.js.map → node-registry-extra-compat-dWrv7gpS.js.map} +1 -1
  108. package/{node-registry-extra-math-6ezzTkPj.js → node-registry-extra-math-Bn854sX9.js} +2 -2
  109. package/{node-registry-extra-math-6ezzTkPj.js.map → node-registry-extra-math-Bn854sX9.js.map} +1 -1
  110. package/{node-renderable-CS0CmsSp.js → node-renderable-B5G8WcdH.js} +15 -13
  111. package/node-renderable-B5G8WcdH.js.map +1 -0
  112. package/{node-shadow-CpnrdvtJ.js → node-shadow-CVIUlNf0.js} +7 -7
  113. package/node-shadow-CVIUlNf0.js.map +1 -0
  114. package/{normal-map-fragment-DradEMl-.js → normal-map-fragment-CQSxhjCy.js} +2 -2
  115. package/{normal-map-fragment-DradEMl-.js.map → normal-map-fragment-CQSxhjCy.js.map} +1 -1
  116. package/package.json +3 -10
  117. package/{parse-camera-CgV4bWc0.js → parse-camera-pBRT_6i5.js} +2 -2
  118. package/{parse-camera-CgV4bWc0.js.map → parse-camera-pBRT_6i5.js.map} +1 -1
  119. package/pbr-geometry-view-NiZY_juX.js +491 -0
  120. package/pbr-geometry-view-NiZY_juX.js.map +1 -0
  121. package/{pbr-metallic-roughness-block-BFwZj2Nw.js → pbr-metallic-roughness-block-JBSi-tQN.js} +2 -2
  122. package/{pbr-metallic-roughness-block-BFwZj2Nw.js.map → pbr-metallic-roughness-block-JBSi-tQN.js.map} +1 -1
  123. package/{pbr-metallic-roughness-block-full-5t0HT3xl.js → pbr-metallic-roughness-block-full-Ta9lR2cz.js} +2 -2
  124. package/{pbr-metallic-roughness-block-full-5t0HT3xl.js.map → pbr-metallic-roughness-block-full-Ta9lR2cz.js.map} +1 -1
  125. package/{pbr-mr-helper-core-R5tOZ8Ap.js → pbr-mr-helper-core-BVWNR08D.js} +2 -2
  126. package/{pbr-mr-helper-core-R5tOZ8Ap.js.map → pbr-mr-helper-core-BVWNR08D.js.map} +1 -1
  127. package/{pbr-refraction-Dd11HnaI.js → pbr-refraction-C9FvFmAp.js} +2 -2
  128. package/{pbr-refraction-Dd11HnaI.js.map → pbr-refraction-C9FvFmAp.js.map} +1 -1
  129. package/{pbr-renderable-BHAdF5Vw.js → pbr-renderable-DzUF2QIk.js} +60 -42
  130. package/pbr-renderable-DzUF2QIk.js.map +1 -0
  131. package/{pbr-shadow-fragment-BxUrFJYZ.js → pbr-shadow-fragment-CnqnbGYS.js} +2 -2
  132. package/{pbr-shadow-fragment-BxUrFJYZ.js.map → pbr-shadow-fragment-CnqnbGYS.js.map} +1 -1
  133. package/{pbr-tracking-D6i3yPb7.js → pbr-tracking-3tU1kqea.js} +2 -2
  134. package/{pbr-tracking-D6i3yPb7.js.map → pbr-tracking-3tU1kqea.js.map} +1 -1
  135. package/{pbr-transmission-ext-Dll8EYwE.js → pbr-transmission-ext-BcLjRxfB.js} +2 -2
  136. package/{pbr-transmission-ext-Dll8EYwE.js.map → pbr-transmission-ext-BcLjRxfB.js.map} +1 -1
  137. package/recast-navigation.wasm-DG_0AFuk.js +8706 -0
  138. package/recast-navigation.wasm-DG_0AFuk.js.map +1 -0
  139. package/recast-navigation.wasm-compat-C-Bf2ylB.js +8692 -0
  140. package/recast-navigation.wasm-compat-C-Bf2ylB.js.map +1 -0
  141. package/{reflectance-fragment-ejMJ4O1o.js → reflectance-fragment-Dbpgw3Jt.js} +2 -2
  142. package/{reflectance-fragment-ejMJ4O1o.js.map → reflectance-fragment-Dbpgw3Jt.js.map} +1 -1
  143. package/{rgbd-decode-DCvzUYeI.js → rgbd-decode-DoyUquy3.js} +7 -6
  144. package/rgbd-decode-DoyUquy3.js.map +1 -0
  145. package/{scene-material-swap-C2ykv55W.js → scene-material-swap-nNUH4nGn.js} +11 -4
  146. package/scene-material-swap-nNUH4nGn.js.map +1 -0
  147. package/screenshot-readback-D0Sj9qq3.js +92 -0
  148. package/screenshot-readback-D0Sj9qq3.js.map +1 -0
  149. package/{mesh-features-BAJpbMog.js → shader-composer-BUD_pSX4.js} +3 -54
  150. package/shader-composer-BUD_pSX4.js.map +1 -0
  151. package/{shader-renderable-BMf_vvO0.js → shader-renderable-D7-RyVxa.js} +25 -19
  152. package/shader-renderable-D7-RyVxa.js.map +1 -0
  153. package/{shader-thin-instance-5_WUfi3m.js → shader-thin-instance-DuBotxDO.js} +4 -4
  154. package/shader-thin-instance-DuBotxDO.js.map +1 -0
  155. package/{sheen-fragment-CS6z29Fs.js → sheen-fragment-1MkEMcbc.js} +2 -2
  156. package/{sheen-fragment-CS6z29Fs.js.map → sheen-fragment-1MkEMcbc.js.map} +1 -1
  157. package/{singlelight-directional-wgsl-4MIgZMeC.js → singlelight-directional-wgsl-BsV8G456.js} +2 -2
  158. package/{singlelight-directional-wgsl-4MIgZMeC.js.map → singlelight-directional-wgsl-BsV8G456.js.map} +1 -1
  159. package/{singlelight-hemispheric-wgsl-CK-GUYWe.js → singlelight-hemispheric-wgsl-Bo0jKlW5.js} +2 -2
  160. package/{singlelight-hemispheric-wgsl-CK-GUYWe.js.map → singlelight-hemispheric-wgsl-Bo0jKlW5.js.map} +1 -1
  161. package/{singlelight-point-wgsl-CYtzqCbP.js → singlelight-point-wgsl-DV39UP5Y.js} +2 -2
  162. package/{singlelight-point-wgsl-CYtzqCbP.js.map → singlelight-point-wgsl-DV39UP5Y.js.map} +1 -1
  163. package/{singlelight-spot-wgsl-DVbaVufF.js → singlelight-spot-wgsl-yg3od6vL.js} +2 -2
  164. package/{singlelight-spot-wgsl-DVbaVufF.js.map → singlelight-spot-wgsl-yg3od6vL.js.map} +1 -1
  165. package/{skeleton-fragment-BOVmc8YS.js → skeleton-fragment-DdxYG6kv.js} +2 -2
  166. package/{skeleton-fragment-BOVmc8YS.js.map → skeleton-fragment-DdxYG6kv.js.map} +1 -1
  167. package/{skybox-renderable-DDcCPSly.js → skybox-renderable-CJD4XmX5.js} +7 -8
  168. package/skybox-renderable-CJD4XmX5.js.map +1 -0
  169. package/{splat-ply-compressed-BahdBG1r.js → splat-ply-compressed-DHjyiVmI.js} +9 -8
  170. package/splat-ply-compressed-DHjyiVmI.js.map +1 -0
  171. package/{standard-renderable-D1bhoF0K.js → standard-pipeline-XTbHL7MY.js} +11 -202
  172. package/standard-pipeline-XTbHL7MY.js.map +1 -0
  173. package/standard-renderable-CREWLNHI.js +191 -0
  174. package/standard-renderable-CREWLNHI.js.map +1 -0
  175. package/{std-ambient-fragment-C6WNm8dQ.js → std-ambient-fragment-Bjx3VFrr.js} +2 -2
  176. package/{std-ambient-fragment-C6WNm8dQ.js.map → std-ambient-fragment-Bjx3VFrr.js.map} +1 -1
  177. package/{std-cube-reflection-fragment-Bqutpy2q.js → std-cube-reflection-fragment-y9WWdXUt.js} +2 -2
  178. package/{std-cube-reflection-fragment-Bqutpy2q.js.map → std-cube-reflection-fragment-y9WWdXUt.js.map} +1 -1
  179. package/{std-emissive-fragment-B-A83rqX.js → std-emissive-fragment-C8Lnmojh.js} +2 -2
  180. package/{std-emissive-fragment-B-A83rqX.js.map → std-emissive-fragment-C8Lnmojh.js.map} +1 -1
  181. package/{std-lightmap-fragment-Df7KJezh.js → std-lightmap-fragment-DFxGcoA5.js} +2 -2
  182. package/{std-lightmap-fragment-Df7KJezh.js.map → std-lightmap-fragment-DFxGcoA5.js.map} +1 -1
  183. package/{std-opacity-fragment-D9et2jip.js → std-opacity-fragment-EXzFWiSp.js} +2 -2
  184. package/{std-opacity-fragment-D9et2jip.js.map → std-opacity-fragment-EXzFWiSp.js.map} +1 -1
  185. package/{std-reflection-fragment-DBJeT-yg.js → std-reflection-fragment-BoJORqpG.js} +2 -2
  186. package/{std-reflection-fragment-DBJeT-yg.js.map → std-reflection-fragment-BoJORqpG.js.map} +1 -1
  187. package/{std-shadow-fragment-C6fD8rW-.js → std-shadow-fragment-Bq-Wc8UJ.js} +2 -2
  188. package/{std-shadow-fragment-C6fD8rW-.js.map → std-shadow-fragment-Bq-Wc8UJ.js.map} +1 -1
  189. package/{std-specular-fragment-C2ZOss-t.js → std-specular-fragment-CM5R5j2g.js} +2 -2
  190. package/{std-specular-fragment-C2ZOss-t.js.map → std-specular-fragment-CM5R5j2g.js.map} +1 -1
  191. package/{std-tracking-C4L4nQGc.js → std-tracking-Cif_wXeT.js} +2 -2
  192. package/{std-tracking-C4L4nQGc.js.map → std-tracking-Cif_wXeT.js.map} +1 -1
  193. package/{subsurface-fragment-C1H4ytqK.js → subsurface-fragment-BEaAXYXz.js} +2 -2
  194. package/{subsurface-fragment-C1H4ytqK.js.map → subsurface-fragment-BEaAXYXz.js.map} +1 -1
  195. package/swapchain-overlay-UCLilhbq.js +37 -0
  196. package/swapchain-overlay-UCLilhbq.js.map +1 -0
  197. package/{thin-instance-cull-binding-CCxrPNO6.js → thin-instance-cull-binding-DWKUt5ZN.js} +12 -12
  198. package/thin-instance-cull-binding-DWKUt5ZN.js.map +1 -0
  199. package/{thin-instance-gpu-E8DBd8XL.js → thin-instance-gpu-BDdRcNAh.js} +15 -7
  200. package/thin-instance-gpu-BDdRcNAh.js.map +1 -0
  201. package/{tracking-primitives-w4BVV9p9.js → tracking-primitives-CglRNTlX.js} +2 -2
  202. package/{tracking-primitives-w4BVV9p9.js.map → tracking-primitives-CglRNTlX.js.map} +1 -1
  203. package/{unlit-fragment-DU9_mhzZ.js → unlit-fragment-kxfZWlnp.js} +2 -2
  204. package/{unlit-fragment-DU9_mhzZ.js.map → unlit-fragment-kxfZWlnp.js.map} +1 -1
  205. package/_mat4-storage-f64-Bvh5TymE.js.map +0 -1
  206. package/assets/splat-sort-worker-Crg3CaCc.js.map +0 -1
  207. package/background-dds-skybox-ZjrSIxrT.js.map +0 -1
  208. package/background-ground-B2Mie-MI.js.map +0 -1
  209. package/background-hdr-skybox-DDRJYuT2.js.map +0 -1
  210. package/background-solid-skybox-fjXlnWaD.js.map +0 -1
  211. package/billboard-renderable-DKmlOgbM.js.map +0 -1
  212. package/create-skeleton-BBI5urcj.js.map +0 -1
  213. package/cubemap-skybox-material-DvW81drX.js.map +0 -1
  214. package/emissive-fragment-DD8cvHyx.js.map +0 -1
  215. package/gaussian-splatting-pipeline-sh-BvkUhA9V.js.map +0 -1
  216. package/gltf-animation-KnPzeOIY.js.map +0 -1
  217. package/gltf-ext-basisu-kmth3UWX.js.map +0 -1
  218. package/gltf-ext-quantization-CpZyLDIz.js.map +0 -1
  219. package/gltf-feature-animation-pointer-rFqLfbO_.js.map +0 -1
  220. package/gltf-feature-draco-yGSMGTE3.js.map +0 -1
  221. package/gltf-feature-gpu-instancing-Cj1XjmM6.js.map +0 -1
  222. package/gltf-feature-meshopt-Des96YFI.js.map +0 -1
  223. package/gltf-feature-morph-BAcY14XU.js.map +0 -1
  224. package/gltf-glb-parser-D6UZWFuC.js.map +0 -1
  225. package/gltf-interleave-C9eBqH_F.js.map +0 -1
  226. package/gltf-pbr-builder-ext-DPC0zg_u.js.map +0 -1
  227. package/gs-picking-pipeline-Bx8LTav6.js.map +0 -1
  228. package/index-B7Qhw0xL.js +0 -21232
  229. package/index-B7Qhw0xL.js.map +0 -1
  230. package/mesh-features-BAJpbMog.js.map +0 -1
  231. package/no-color-view-DsyLSL-W.js +0 -8
  232. package/no-color-view-DsyLSL-W.js.map +0 -1
  233. package/node-env-BPZXZzBf.js.map +0 -1
  234. package/node-registry-Bd-AlrgC.js +0 -190
  235. package/node-registry-Bd-AlrgC.js.map +0 -1
  236. package/node-renderable-CS0CmsSp.js.map +0 -1
  237. package/node-shadow-CpnrdvtJ.js.map +0 -1
  238. package/pbr-renderable-BHAdF5Vw.js.map +0 -1
  239. package/rgbd-decode-DCvzUYeI.js.map +0 -1
  240. package/scene-material-swap-C2ykv55W.js.map +0 -1
  241. package/shader-renderable-BMf_vvO0.js.map +0 -1
  242. package/shader-thin-instance-5_WUfi3m.js.map +0 -1
  243. package/skybox-renderable-DDcCPSly.js.map +0 -1
  244. package/splat-ply-compressed-BahdBG1r.js.map +0 -1
  245. package/standard-renderable-D1bhoF0K.js.map +0 -1
  246. package/swapchain-overlay-DcCSFDp7.js +0 -35
  247. package/swapchain-overlay-DcCSFDp7.js.map +0 -1
  248. package/thin-instance-cull-binding-CCxrPNO6.js.map +0 -1
  249. package/thin-instance-gpu-E8DBd8XL.js.map +0 -1
package/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ /** Increment ref count on a Texture2D. First acquire sets count to 1. */
2
+ export declare function acquireTexture(tex: Texture2D): void;
3
+
1
4
  /** Add an agent to the crowd. Returns the agent index. */
2
5
  export declare function addAgent(crowd: NavCrowd, position: Vec3, params: AgentParameters): number;
3
6
 
@@ -129,6 +132,11 @@ export declare function addTaskAtStart(target: FrameGraph | SceneContext, task:
129
132
  /** Insert a task BEFORE another task in execute order. Accepts a FrameGraph or a SceneContext. */
130
133
  export declare function addTaskBefore(target: FrameGraph | SceneContext, task: Task, before: Task): void;
131
134
 
135
+ /** Attach a `TextRenderable` to a scene. Uses the scene's deferred-renderables hook. */
136
+ export declare function addTextRenderable(scene: SceneContext, renderable: TextRenderable): void;
137
+
138
+ export declare function addTextRendererLayer(tr: TextRenderer, layer: TextLayer): void;
139
+
132
140
  /** Add one instance. Returns its index. Grows capacity as needed. */
133
141
  export declare function addThinInstance(mesh: Mesh, matrix: Mat4): number;
134
142
 
@@ -319,6 +327,36 @@ export declare interface AnisotropyProps {
319
327
 
320
328
  declare type AnyMaterial = StandardMaterialProps | PbrMaterialProps;
321
329
 
330
+ /**
331
+ * Append `sources` into the remaining free space of an atlas previously built by
332
+ * `createSpriteAtlasFromFrames`. The existing `GPUTexture` (and any bind group already
333
+ * referencing it) stays valid — each new frame is uploaded with a single
334
+ * `queue.writeTexture` and the UV slots of the *existing* frames are not touched, so
335
+ * sprite instances already drawing from this atlas remain correct.
336
+ *
337
+ * Returns the integer indices of the newly-appended frames in `atlas.frames`, in input
338
+ * order. Sources are validated and placed before any texel is written, so a thrown
339
+ * "atlas full" error leaves the atlas state untouched (all-or-nothing semantics).
340
+ *
341
+ * Throws when:
342
+ * - The atlas was built by `createGridSpriteAtlas` / `loadSpriteAtlas` (no packer state).
343
+ * - Any source has invalid size / sub-rect / pixel buffer length.
344
+ * - A source wider than `maxWidthPx` is supplied (cannot fit any shelf).
345
+ * - The packed sources would overflow the atlas height. Pre-size the atlas via
346
+ * `createSpriteAtlasFromFrames(engine, [...], { capacityPx: [w, h] })` to reserve room.
347
+ */
348
+ export declare function appendSpriteAtlasFrames(engine: EngineContext, atlas: SpriteAtlas, sources: readonly SpriteAtlasFrameSource[]): number[];
349
+
350
+ /**
351
+ * Apply a one-shot linear impulse (kg·m/s) to a body at a world `point` (defaults to the body's
352
+ * current position / centre of mass), waking it if asleep. Used to shoot, throw, or shove a prop.
353
+ * @param world - The physics world.
354
+ * @param body - The body to push.
355
+ * @param impulse - World-space impulse vector (kg·m/s).
356
+ * @param point - World point of application; defaults to the body's current position.
357
+ */
358
+ export declare function applyPhysicsImpulse(world: PhysicsWorld, body: PhysicsBody, impulse: Vec3, point?: Vec3): void;
359
+
322
360
  /** ArcRotateCamera — orbits around a target point.
323
361
  * Uses Babylon.js convention: left-handed, alpha=rotation around Y, beta=elevation.
324
362
  * Plain data + methods. Does NOT know about the scene.
@@ -408,6 +446,16 @@ export declare interface AssetContainer {
408
446
  };
409
447
  }
410
448
 
449
+ /** Bind the gizmo to a node — the gizmo follows the node's world translation
450
+ * and applies drag deltas to its `position`. */
451
+ export declare function attachAxisDragGizmoToNode(gizmo: AxisDragGizmo, node: SceneNode | null): void;
452
+
453
+ export declare function attachAxisScaleGizmoToNode(gizmo: AxisScaleGizmo, node: SceneNode | null): void;
454
+
455
+ export declare function attachBoundingBoxGizmoToNode(gizmo: BoundingBoxGizmo, node: SceneNode | null): void;
456
+
457
+ export declare function attachCameraGizmoToCamera(gizmo: CameraGizmo, camera: Camera | null): void;
458
+
411
459
  /**
412
460
  * Attach orbit/zoom/pan controls to an ArcRotateCamera.
413
461
  * Matches Babylon.js ArcRotateCameraPointersInput behavior with inertia:
@@ -426,7 +474,34 @@ export declare interface AssetContainer {
426
474
  * Camera stays plain data — this function reads/writes its properties.
427
475
  * Returns a cleanup function to remove all listeners and the beforeRender hook.
428
476
  */
429
- export declare function attachControl(camera: ArcRotateCamera, canvas: HTMLCanvasElement, scene?: SceneContext): () => void;
477
+ export declare function attachControl(camera: ArcRotateCamera, canvas: HTMLCanvasElement, scene?: SceneContext, options?: AttachControlOptions): () => void;
478
+
479
+ /**
480
+ * Optional hooks that let an {@link attachControl} caller defer pointer
481
+ * gestures to an external interactor (typically a gizmo pointer-drag
482
+ * dispatcher) so the camera doesn't orbit when the user is interacting with
483
+ * something else on top of it. All fields are optional; omit them to keep
484
+ * the default behavior (the camera always handles its own pointer input).
485
+ */
486
+ export declare interface AttachControlOptions {
487
+ /** Optional predicate consulted on every pointer-down. When it returns
488
+ * false the camera ignores that gesture (no rotate / pan). Used to defer
489
+ * to gizmo interaction so pressing or dragging a gizmo doesn't also orbit
490
+ * the camera. */
491
+ shouldHandlePointerDown?: (event: PointerEvent) => boolean;
492
+ /** Optional predicate consulted on pointer-move while a camera drag is in
493
+ * progress. When it returns true the camera ABORTS the current drag.
494
+ * Because gizmo picking is async, a press on a gizmo may not be known at
495
+ * pointer-down time (so the camera optimistically starts orbiting); once
496
+ * the gizmo drag is recognised a frame later this lets the gizmo reclaim
497
+ * the gesture and undo the (not-yet-applied) orbit. */
498
+ isExternalDragActive?: () => boolean;
499
+ /** Optional predicate consulted on pointer-move. While it returns true the
500
+ * camera DEFERS its orbit (consumes the move without applying it) — used
501
+ * to wait out an in-flight async gizmo pick so a press that lands on a
502
+ * gizmo never produces a stray orbit, regardless of pick latency. */
503
+ isExternalPickPending?: () => boolean;
504
+ }
430
505
 
431
506
  /**
432
507
  * Attach keyboard + mouse controls to a FreeCamera.
@@ -442,6 +517,36 @@ export declare function attachControl(camera: ArcRotateCamera, canvas: HTMLCanva
442
517
  */
443
518
  export declare function attachFreeControl(camera: FreeCamera, canvas: HTMLCanvasElement, scene?: SceneContext): () => void;
444
519
 
520
+ /**
521
+ * Attach orbit / pan / zoom controls to a {@link GeospatialCamera}, matching
522
+ * Babylon.js `GeospatialCamera` interactions:
523
+ * - Left-drag: pan (the cursor stays anchored to the globe surface).
524
+ * - Middle/right-drag: rotate (yaw + pitch / tilt).
525
+ * - Wheel: zoom (toward the cursor by default).
526
+ * - Keyboard: arrows = tilt, W/A/S/D = pan, +/- = zoom.
527
+ *
528
+ * Movement uses Babylon.js's framerate-independent physics model (velocity +
529
+ * inertial decay). Globe picking is analytic ray-sphere against the planet
530
+ * sphere (origin-centred, radius = `limits.planetRadius`) — no mesh picking
531
+ * subsystem is required. Inertia is integrated once per frame from the scene's
532
+ * render loop (`scene._beforeRender`).
533
+ *
534
+ * Returns a disposer that removes all listeners and the per-frame hook.
535
+ */
536
+ export declare function attachGeospatialControls(camera: GeospatialCamera, canvas: HTMLCanvasElement, scene: SceneContext, options?: GeospatialControlOptions): () => void;
537
+
538
+ export declare function attachLightGizmoToLight(gizmo: LightGizmo, light: LightBase | null): void;
539
+
540
+ export declare function attachPlaneDragGizmoToNode(gizmo: PlaneDragGizmo, node: SceneNode | null): void;
541
+
542
+ export declare function attachPlaneRotationGizmoToNode(gizmo: PlaneRotationGizmo, node: SceneNode | null): void;
543
+
544
+ export declare function attachPositionGizmoToNode(gizmo: PositionGizmo, node: SceneNode | null): void;
545
+
546
+ export declare function attachRotationGizmoToNode(gizmo: RotationGizmo, node: SceneNode | null): void;
547
+
548
+ export declare function attachScaleGizmoToNode(gizmo: ScaleGizmo, node: SceneNode | null): void;
549
+
445
550
  /**
446
551
  * Attaches a manager to a sprite renderer's update hooks so its animations advance each frame.
447
552
  * @param renderer - Sprite renderer whose update loop drives the manager.
@@ -460,9 +565,76 @@ export declare function attachSpriteAnimationsToRenderer(renderer: SpriteRendere
460
565
  */
461
566
  export declare function attachSpriteAnimationsToScene(scene: SceneContext, manager: SpriteAnimationManager): SpriteAnimationBinding;
462
567
 
568
+ /**
569
+ * Attach a baked VAT to a mesh: builds the settings UBO, sets `mesh.vat` (reusing the skeleton's
570
+ * joints/weights vertex buffers), and DROPS the live skeleton so it's no longer CPU-updated. Returns a
571
+ * handle that advances the animation clock.
572
+ *
573
+ * @param engine - Engine context.
574
+ * @param mesh - The mesh that was baked (still has `mesh.skeleton`).
575
+ * @param baked - The result of `bakeVat`.
576
+ * @param clip - Initial clip name to play (defaults to the first baked clip).
577
+ */
578
+ export declare function attachVat(engine: EngineContext, mesh: Mesh, baked: VatBakeResult, clip?: string): VatHandle;
579
+
580
+ export declare interface AxisDragGizmo {
581
+ /** The root node — gizmo follows its `attachedNode` by copying world translation. */
582
+ readonly root: SceneNode;
583
+ /** Drag behaviour driving the pointer interaction. */
584
+ readonly drag: PointerDrag;
585
+ /** Fired whenever a drag delta is applied to the attached node. */
586
+ readonly onPositionChanged: GizmoObservable<Vec3>;
587
+ /** Currently attached node — set via `attachAxisDragGizmoToNode`. */
588
+ attachedNode: SceneNode | null;
589
+ /** When true, the gizmo's drag axis is rotated each frame by the attached
590
+ * node's world rotation (local-coord mode). When false (default), the
591
+ * drag axis stays world-aligned. Mirrors BJS
592
+ * `updateGizmoRotationToMatchAttachedMesh`. */
593
+ useLocalCoordinates: boolean;
594
+ /** Material triplet (colored / hover / disabled). Hover state is updated
595
+ * automatically during pointer-down on the collider. */
596
+ readonly materials: GizmoMaterialSet;
597
+
598
+ export declare interface AxisDragGizmoOptions {
599
+ /** World-space drag axis (unit vector). */
600
+ dragAxis: Vec3;
601
+ /** Material color of the rendered arrow. Defaults to grey. */
602
+ color?: [number, number, number];
603
+ /** Hover material colour (defaults to yellow). */
604
+ hoverColor?: [number, number, number];
605
+ /** Disabled-state material colour (defaults to grey, alpha 0.4). */
606
+ disableColor?: [number, number, number];
607
+ /** Multiplier applied to the rendered arrow's tube/cone thickness. */
608
+ thickness?: number;
609
+ }
610
+
463
611
  /** A billboard sprite system that rotates only around a fixed world axis. */
464
612
  export declare type AxisLockedBillboardSpriteSystem = BillboardSpriteSystem<"axis-locked">;
465
613
 
614
+ export declare interface AxisScaleGizmo {
615
+ readonly root: SceneNode;
616
+ readonly drag: PointerDrag;
617
+ readonly onScaleChanged: GizmoObservable<Vec3>;
618
+ attachedNode: SceneNode | null;
619
+ /** Local-coord mode: drag axis rotates with the attached node. */
620
+ useLocalCoordinates: boolean;
621
+ readonly materials: GizmoMaterialSet;
622
+
623
+ export declare interface AxisScaleGizmoOptions {
624
+ /** World-space drag axis (unit vector). Scaling is applied to the attached
625
+ * node's local `scaling` components proportional to each axis component. */
626
+ dragAxis: Vec3;
627
+ color?: [number, number, number];
628
+ hoverColor?: [number, number, number];
629
+ disableColor?: [number, number, number];
630
+ /** Tube thickness multiplier (visible only; collider gets +4). */
631
+ thickness?: number;
632
+ /** Optional multiplier on the per-frame drag strength. Default 1. */
633
+ sensitivity?: number;
634
+ /** When true, scale uniformly on all 3 axes (matches BJS uniformScaling). */
635
+ uniformScaling?: boolean;
636
+ }
637
+
466
638
  /**
467
639
  * Bakes the mesh's current world matrix into its splat vertices, then resets the mesh's
468
640
  * position, rotation, and scaling to identity so the visual result is unchanged.
@@ -478,6 +650,17 @@ export declare function bakeCurrentTransformIntoVertices(mesh: GaussianSplatting
478
650
  */
479
651
  export declare function bakeTransformIntoVertices(mesh: GaussianSplattingMesh, transform: Mat4): void;
480
652
 
653
+ /**
654
+ * Bake the given animation clips of a skinned mesh into a VAT texture. The clips are laid out as
655
+ * contiguous row blocks (clip 0 first), one texture row per frame. The mesh must still have its live
656
+ * `skeleton` at bake time (the bone matrices are read from it as each frame is evaluated).
657
+ *
658
+ * @param engine - Engine context.
659
+ * @param mesh - The skinned source mesh (must have `mesh.skeleton`).
660
+ * @param groups - The animation clips to bake (e.g. a creature's gait clips).
661
+ */
662
+ export declare function bakeVat(engine: EngineContext, mesh: Mesh, groups: AnimationGroup[]): VatBakeResult;
663
+
481
664
  /**
482
665
  * Additive blending for world-space billboards. The billboard's RGB, scaled by its own alpha, is
483
666
  * added to the framebuffer (no depth write, like the other transparent modes), so overlapping
@@ -637,6 +820,27 @@ export declare interface BlurPostProcessTaskConfig extends Omit<PostProcessTaskC
637
820
  kernel?: number;
638
821
  }
639
822
 
823
+ export declare interface BoundingBoxGizmo {
824
+ readonly root: SceneNode;
825
+ /** Currently attached node — set via `attachBoundingBoxGizmoToNode`. */
826
+ attachedNode: SceneNode | null;
827
+ /** Fires when any drag (scale / rotate / translate) updates the attached node. */
828
+ readonly onChanged: GizmoObservable<void>;
829
+ /** Material used to render all gizmo geometry. */
830
+ readonly material: StandardMaterialProps;
831
+
832
+ export declare interface BoundingBoxGizmoOptions {
833
+ /** RGB colour for the wireframe + handle materials. Defaults to grey. */
834
+ color?: [number, number, number];
835
+ /** Edge wireframe thickness (world units before scaling). Default 0.06. */
836
+ edgeThickness?: number;
837
+ /** Side length of the 8 corner scale boxes (world units). Default 0.18. */
838
+ scaleBoxSize?: number;
839
+ /** Length of the 12 elongated edge rotation anchors (world units). Default
840
+ * 0.16; thickness is length/4 (BJS 1.6:0.4 ratio). */
841
+ rotationAnchorSize?: number;
842
+ }
843
+
640
844
  /** Minimal camera contract — any camera that can provide view/projection matrices.
641
845
  * Both ArcRotateCamera and FreeCamera implement this interface.
642
846
  * Pure state, no scene knowledge (pillar 4b).
@@ -655,6 +859,30 @@ export declare interface Camera {
655
859
  readonly worldMatrix: Mat4;
656
860
  readonly worldMatrixVersion: number;
657
861
 
862
+ export declare interface CameraGizmo {
863
+ /** Root node — the gizmo follows the attached camera's world translation
864
+ * and orientation each frame. */
865
+ readonly root: SceneNode;
866
+ /** Material shared by the body + frustum. Mutate `diffuseColor` to recolor. */
867
+ readonly material: StandardMaterialProps;
868
+ /** Alias of `material` — kept for backward compatibility with callers
869
+ * that mutated `frustumMaterial` against the older variant. */
870
+ readonly frustumMaterial: StandardMaterialProps;
871
+ /** Currently attached camera — set via `attachCameraGizmoToCamera`. */
872
+ attachedCamera: Camera | null;
873
+
874
+ export declare interface CameraGizmoOptions {
875
+ /** RGB color for the camera body + frustum material. Defaults to grey. */
876
+ color?: [number, number, number];
877
+ /** RGB color for the frustum wireframe edges (alias of `color` kept for
878
+ * backward compatibility with the previous tube-body variant). */
879
+ frustumColor?: [number, number, number];
880
+ /** Set to false to omit the frustum wireframe. Defaults to true. */
881
+ displayFrustum?: boolean;
882
+ /** Set to false to omit the camera body mesh (box + cylinders). Default true. */
883
+ displayBody?: boolean;
884
+ }
885
+
658
886
  /** Cap mode: close both ends of the tube/extrusion. */
659
887
  export declare const CAP_ALL = 3;
660
888
 
@@ -667,6 +895,32 @@ export declare const CAP_NONE = 0;
667
895
  /** Cap mode: close only the start of the tube/extrusion. */
668
896
  export declare const CAP_START = 1;
669
897
 
898
+ /**
899
+ * Capture the current canvas backbuffer of a {@link SurfaceContext} — the final presented
900
+ * frame (post-processing and all) with NO HTML/DOM overlay, since those are never drawn
901
+ * into the canvas.
902
+ *
903
+ * Pass `engine` to capture the engine's primary surface (the canvas given to `createEngine`),
904
+ * or pass an auxiliary surface returned by `createSurface` to capture that canvas. Each
905
+ * surface owns its own capture queue and COPY_SRC swapchain state, so surfaces that never
906
+ * capture stay compression-friendly even when another surface on the same engine is being
907
+ * captured every frame.
908
+ *
909
+ * The read is scheduled on a rendered frame: the copy is recorded into that frame's command
910
+ * encoder (so it reads a valid, just-rendered swapchain texture), then the staging buffer is
911
+ * mapped after submit and the pixels are unpacked. Requires a running render loop
912
+ * (`startEngine`); the returned promise resolves once the readback completes.
913
+ *
914
+ * Multiple calls queued on the same surface before the next serviced frame share a single
915
+ * GPU copy and all resolve with the same image.
916
+ *
917
+ * The readback implementation is loaded lazily on the first call, so engines whose surfaces
918
+ * never capture a screenshot ship none of it. The surface's swapchain stays a plain,
919
+ * compression-friendly RENDER_ATTACHMENT surface until the first capture is queued, at which
920
+ * point `renderFrame` reconfigures it once with COPY_SRC (before acquiring that frame's texture).
921
+ */
922
+ export declare function captureScreenshot(surface: SurfaceContext): Promise<Screenshot>;
923
+
670
924
  /** A post-process task that offsets the red/green/blue channels to simulate lens chromatic aberration. */
671
925
  export declare interface ChromaticAberrationPostProcessTask extends PostProcessTask {
672
926
  aberrationAmount: number;
@@ -683,6 +937,57 @@ export declare interface ChromaticAberrationPostProcessTaskConfig extends Omit<P
683
937
  centerPosition?: PostProcessVec2_2;
684
938
  }
685
939
 
940
+ /** A post-process task that writes the per-pixel circle-of-confusion (grayscale)
941
+ * derived from scene depth and the lens focus parameters. */
942
+ export declare interface CircleOfConfusionPostProcessTask extends PostProcessTask {
943
+ lensSize: number;
944
+ fStop: number;
945
+ focusDistance: number;
946
+ focalLength: number;
947
+ }
948
+
949
+ /**
950
+ * Configuration for `createCircleOfConfusionPostProcessTask`.
951
+ *
952
+ * Models Babylon.js's `FrameGraphCircleOfConfusionTask` +
953
+ * `ThinCircleOfConfusionPostProcess`.
954
+ */
955
+ export declare interface CircleOfConfusionPostProcessTaskConfig extends Omit<PostProcessTaskConfig, "_shader"> {
956
+ /** Depth texture supplying per-pixel scene depth. With `depthNotNormalized`
957
+ * it must store **camera-space (view) depth** (the geometry renderer's
958
+ * VIEW_DEPTH attachment); otherwise it stores normalized [0,1] view depth. */
959
+ depthTexture: RenderTarget;
960
+ /** Camera used to read minZ/maxZ when the depth is normalized. */
961
+ camera: Camera;
962
+ /** Max lens size in scene units / 1000 (e.g. mm). Standard cameras are 50mm. Default 50. */
963
+ lensSize?: number;
964
+ /** F-Stop of the camera. Aperture diameter = lensSize / fStop. Default 1.4. */
965
+ fStop?: number;
966
+ /** Distance from the camera to focus on, in scene units / 1000. Default 2000. */
967
+ focusDistance?: number;
968
+ /** Focal length of the camera in scene units / 1000. Default 50. */
969
+ focalLength?: number;
970
+ /** When true the depth texture stores camera-space depth (0..maxZ) rather
971
+ * than normalized [0,1] depth, skipping the `cameraMinMaxZ` reconstruction. */
972
+ depthNotNormalized?: boolean;
973
+ }
974
+
975
+ /**
976
+ * Clamp the camera centre away from the geographic poles (in place), so the
977
+ * tangent basis stays well-defined. Mirrors Babylon.js `ClampCenterFromPolesInPlace`.
978
+ */
979
+ export declare function clampCenterFromPoles(center: Vec3): Vec3;
980
+
981
+ /**
982
+ * Clamps a requested zoom distance so it respects the radius limits.
983
+ * @param limits - The geospatial limits.
984
+ * @param zoomDistance - Requested zoom (positive = zoom in, negative = zoom out).
985
+ * @param currentRadius - Current camera radius.
986
+ * @param distanceToTarget - Optional distance to the zoom target point (used for zoom-in clamping).
987
+ * @returns The clamped zoom distance.
988
+ */
989
+ export declare function clampZoomDistance(limits: GeospatialLimits, zoomDistance: number, currentRadius: number, distanceToTarget?: number): number;
990
+
686
991
  /** Removes and disposes every task attached to `manager`. */
687
992
  export declare function clearAnimationManager(manager: AnimationManager): void;
688
993
 
@@ -717,6 +1022,9 @@ export declare interface ClearCoatProps {
717
1022
  useF0Remap?: boolean;
718
1023
  }
719
1024
 
1025
+ /** Clear sampler cache for a device. */
1026
+ export declare function clearSamplerCache(engine: EngineContext): void;
1027
+
720
1028
  /** Clear all sprites from a layer while preserving allocated capacity. */
721
1029
  export declare function clearSprite2DLayer(layer: Sprite2DLayer): void;
722
1030
 
@@ -798,9 +1106,80 @@ export declare interface ClusteredPointLightOptions {
798
1106
  intensity?: number;
799
1107
  }
800
1108
 
1109
+ /**
1110
+ * Build the east/north/up orthonormal basis at a point on the globe (left-handed
1111
+ * convention). `up` is the geocentric normal (normalized position); `east` and
1112
+ * `north` complete a right-handed-looking tangent frame given the LH world.
1113
+ * Writes into the provided result objects and returns nothing.
1114
+ */
1115
+ export declare function computeLocalBasis(worldPos: Vec3, refEast: Vec3, refNorth: Vec3, refUp: Vec3): void;
1116
+
1117
+ /**
1118
+ * Compute the lookAt direction from yaw/pitch at a centre point (forward formula).
1119
+ * Writes the normalized direction into `result`.
1120
+ */
1121
+ export declare function computeLookAtFromYawPitch(yaw: number, pitch: number, center: Vec3, result: Vec3): Vec3;
1122
+
801
1123
  /** Compute a path between two world positions, snapped to the navmesh. */
802
1124
  export declare function computePath(plugin: NavigationPlugin, start: Vec3, end: Vec3): Vec3[];
803
1125
 
1126
+ /**
1127
+ * Inverse of {@link computeLookAtFromYawPitch}: given a lookAt direction and centre,
1128
+ * recover the yaw/pitch that would produce it. Writes `[yaw, pitch]` into `result`.
1129
+ * `currentYaw` is used as a fallback when looking straight down/up (yaw undefined).
1130
+ */
1131
+ export declare function computeYawPitchFromLookAt(lookAt: Vec3, center: Vec3, currentYaw: number, result: {
1132
+ x: number;
1133
+ y: number;
1134
+ }): {
1135
+ x: number;
1136
+ y: number;
1137
+ };
1138
+
1139
+ export declare interface CopyToTextureTask extends Task {
1140
+ readonly name: string;
1141
+ sourceTexture: RenderTarget;
1142
+ targetTexture: RenderTarget | undefined;
1143
+ resolveTexture: RenderTarget | undefined;
1144
+ viewport: NormalizedViewport | null | undefined;
1145
+ lodLevel: number;
1146
+ /** `resolveTexture` if set, otherwise `targetTexture`. Kept for API parity
1147
+ * with BJS `FrameGraphCopyToTextureTask.outputTexture`. */
1148
+ readonly outputTexture: RenderTarget;
1149
+ }
1150
+
1151
+ export declare interface CopyToTextureTaskConfig {
1152
+ name?: string;
1153
+ sourceTexture: RenderTarget;
1154
+ /** Target attachment that receives the blit. Required UNLESS `resolveTexture`
1155
+ * is set, in which case the task does a resolve-only operation and writes
1156
+ * directly into `resolveTexture`. */
1157
+ targetTexture?: RenderTarget;
1158
+ /** Viewport applied to the target before the blit. When undefined (default),
1159
+ * the whole target is overwritten and the encoder-copy fast path becomes
1160
+ * available. When set, the blit path is used. */
1161
+ viewport?: NormalizedViewport | null;
1162
+ /** Source mip level to copy from. Default 0. The fast path uses this as
1163
+ * the source `mipLevel`; the blit path samples with `textureSampleLevel`. */
1164
+ lodLevel?: number;
1165
+ /** Optional single-sample texture that receives a hardware MSAA-resolve of
1166
+ * the task's MSAA color attachment at end-of-pass. Two modes:
1167
+ *
1168
+ * - Blit + resolve: `targetTexture` is MSAA and `resolveTexture` is SS.
1169
+ * The shader blit writes into `targetTexture` and at end-of-pass the
1170
+ * GPU resolves `targetTexture` into `resolveTexture`.
1171
+ *
1172
+ * - Resolve-only: `targetTexture` is omitted. The task runs a no-draw
1173
+ * render pass with `sourceTexture` as the color attachment (so the
1174
+ * source itself must be MSAA) and `resolveTexture` as its resolve
1175
+ * target. `viewport` and `lodLevel` are ignored. `sourceTexture` and
1176
+ * `resolveTexture` must have matching dimensions.
1177
+ *
1178
+ * In both modes, `resolveTexture.format` must match the MSAA
1179
+ * attachment's format and `resolveTexture` must be single-sample. */
1180
+ resolveTexture?: RenderTarget;
1181
+ }
1182
+
804
1183
  /**
805
1184
  * Create a post-process task that merges a left-eye texture with the source (right eye) into a red/cyan anaglyph.
806
1185
  * @param config - Source/target settings and the left-eye `leftTexture`.
@@ -834,6 +1213,10 @@ export declare function createAnimationTask(update: AnimationTaskUpdate, options
834
1213
  /** Create a bare ArcRotateCamera with given params. Pure data, no scene knowledge. */
835
1214
  export declare function createArcRotateCamera(alpha: number, beta: number, radius: number, target: Vec3): ArcRotateCamera;
836
1215
 
1216
+ /** Build an axis-drag gizmo and attach it to the given utility layer. Call
1217
+ * `attachAxisDragGizmoToNode` to bind it to a node so it follows + drives it. */
1218
+ export declare function createAxisDragGizmo(engine: EngineContext, layer: UtilityLayer, options: AxisDragGizmoOptions): AxisDragGizmo;
1219
+
837
1220
  /**
838
1221
  * Creates a billboard sprite system whose quads rotate only around a fixed world axis.
839
1222
  * @param atlas - Sprite atlas supplying frames.
@@ -844,6 +1227,8 @@ export declare function createArcRotateCamera(alpha: number, beta: number, radiu
844
1227
  */
845
1228
  export declare function createAxisLockedBillboardSystem(atlas: SpriteAtlas, axis: readonly [number, number, number], opts?: BillboardSpriteSystemOptions): AxisLockedBillboardSpriteSystem;
846
1229
 
1230
+ export declare function createAxisScaleGizmo(engine: EngineContext, layer: UtilityLayer, options: AxisScaleGizmoOptions): AxisScaleGizmo;
1231
+
847
1232
  /**
848
1233
  * Build a custom-shader descriptor to pass as `customShader` when creating a billboard system.
849
1234
  * The descriptor is opaque; the pipeline consumes it lazily.
@@ -877,9 +1262,28 @@ export declare function createBloomPostProcessTask(config: BloomPostProcessTaskC
877
1262
  */
878
1263
  export declare function createBlurPostProcessTask(config: BlurPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): BlurPostProcessTask;
879
1264
 
1265
+ export declare function createBoundingBoxGizmo(engine: EngineContext, layer: UtilityLayer, options?: BoundingBoxGizmoOptions): BoundingBoxGizmo;
1266
+
880
1267
  /** Create a box mesh. Caller must assign material. */
881
1268
  export declare function createBox(engine: EngineContext, size?: number): Mesh;
882
1269
 
1270
+ /** Build a display-only camera gizmo and attach it to the given utility
1271
+ * layer. Call `attachCameraGizmoToCamera` to bind a camera.
1272
+ *
1273
+ * The gizmo has two independently-toggleable parts, both visible by default
1274
+ * and parented to a root that follows the attached camera's world translation
1275
+ * + orientation each frame:
1276
+ *
1277
+ * - A camera **body** (`displayBody`, defaults to `true`) — a distance-scaled
1278
+ * box + 3 cylinders ported from BJS `_CreateCameraMesh`, lit grey, sized
1279
+ * so it stays a roughly constant size on screen.
1280
+ * - A camera **frustum** (`displayFrustum`, defaults to `true`) — 12 thin
1281
+ * cylinder edges forming a truncated-pyramid wireframe sized from the
1282
+ * camera's fov / near / far (far clamped to 60× near), unlit white.
1283
+ *
1284
+ * Set the matching option to `false` to display only one of them. */
1285
+ export declare function createCameraGizmo(engine: EngineContext, layer: UtilityLayer, options?: CameraGizmoOptions): CameraGizmo;
1286
+
883
1287
  /**
884
1288
  * Create a post-process task that simulates chromatic aberration by shifting color channels outward from a center point.
885
1289
  * @param config - Aberration parameters and source/target settings.
@@ -889,6 +1293,19 @@ export declare function createBox(engine: EngineContext, size?: number): Mesh;
889
1293
  */
890
1294
  export declare function createChromaticAberrationPostProcessTask(config: ChromaticAberrationPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): ChromaticAberrationPostProcessTask;
891
1295
 
1296
+ /**
1297
+ * Create a circle-of-confusion post-process task. The output is a grayscale map
1298
+ * where 0 = in focus and 1 = maximally out of focus, computed from the supplied
1299
+ * depth texture and the lens parameters (the usual first stage of a depth-of-field
1300
+ * pipeline). See https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch23.html.
1301
+ *
1302
+ * @param config - Depth texture, camera, lens parameters and source/target settings.
1303
+ * @param engine - The owning engine.
1304
+ * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.
1305
+ * @returns The circle-of-confusion post-process task.
1306
+ */
1307
+ export declare function createCircleOfConfusionPostProcessTask(config: CircleOfConfusionPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): CircleOfConfusionPostProcessTask;
1308
+
892
1309
  /**
893
1310
  * Create an empty {@link ClusteredLightContainer}. Add point lights with
894
1311
  * {@link createClusteredPointLight}, then register it on a scene via
@@ -909,6 +1326,8 @@ export declare function createClusteredLightContainer(options?: ClusteredLightCo
909
1326
  */
910
1327
  export declare function createClusteredPointLight(container: ClusteredLightContainer, options: ClusteredPointLightOptions): ClusteredPointLight;
911
1328
 
1329
+ export declare function createCopyToTextureTask(config: CopyToTextureTaskConfig, engine: EngineContext, scene: SceneContext): CopyToTextureTask;
1330
+
912
1331
  /**
913
1332
  * Builds a {@link Csg2Solid} from a mesh's CPU geometry, baking its world transform.
914
1333
  * @param mesh - Source mesh; must retain CPU positions, normals, and indices.
@@ -944,6 +1363,8 @@ export declare function createCsmDirectionalShadowGenerator(engine: EngineContex
944
1363
  /** Create a cylinder (or cone / truncated cone / prism) mesh. Caller must assign material. */
945
1364
  export declare function createCylinder(engine: EngineContext, options?: CylinderOptions): Mesh;
946
1365
 
1366
+ export declare function createCylinderData(options?: CylinderOptions): CylinderData;
1367
+
947
1368
  /**
948
1369
  * Extract debug visualization geometry from the generated navmesh.
949
1370
  * Faces are detached (each triangle gets its own 3 vertices) and per-vertex
@@ -964,6 +1385,28 @@ export declare function createDebugNavMeshGeometry(plugin: NavigationPlugin): {
964
1385
  * Matches Babylon.js createDefaultCameraOrLight(true, true, true). */
965
1386
  export declare function createDefaultCamera(scene: SceneContext): ArcRotateCamera;
966
1387
 
1388
+ /** Shape `text` with the default layout, extract glyph curves, and bundle into a
1389
+ * `DefaultTextData`. `textColor` is applied as the run's defaultColor (per-glyph color
1390
+ * overrides remain available via direct `updateTextData(replaceRun)` calls).
1391
+ *
1392
+ * The returned `DefaultTextData` owns its underlying `GlyphStorage` — release both with
1393
+ * `disposeDefaultTextData(data)`. */
1394
+ export declare function createDefaultTextData(font: Font, fontSizePx: number, text: string, textColor?: readonly [number, number, number, number], options?: TextLayoutOptions): DefaultTextData;
1395
+
1396
+ /**
1397
+ * Create a depth-of-field post-process task. The source image is first reduced
1398
+ * to a circle-of-confusion map (from the depth texture + lens parameters), then
1399
+ * blurred at one to three decreasing resolutions with CoC-weighted blurs, and
1400
+ * finally merged so each pixel transitions smoothly from sharp to blurred based
1401
+ * on how far out of focus it is.
1402
+ *
1403
+ * @param config - Source/depth textures, camera, lens parameters, blur level, and target settings.
1404
+ * @param engine - The owning engine.
1405
+ * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.
1406
+ * @returns The depth-of-field post-process task.
1407
+ */
1408
+ export declare function createDepthOfFieldPostProcessTask(config: DepthOfFieldPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): DepthOfFieldPostProcessTask;
1409
+
967
1410
  /**
968
1411
  * Creates a directional light shining along `direction` (a parallel light source, like the sun).
969
1412
  * @param direction - World-space direction the light travels along.
@@ -983,7 +1426,7 @@ export declare function createDisc(engine: EngineContext, options?: DiscOptions)
983
1426
  * Call `registerEffectRenderer` to start rendering, `unregisterEffectRenderer`
984
1427
  * to pause, and `disposeEffectRenderer` to free GPU resources.
985
1428
  */
986
- export declare function createEffectRenderer(engine: EngineContext, effect: EffectWrapper, options?: EffectRendererOptions): EffectRenderer;
1429
+ export declare function createEffectRenderer(surface: SurfaceContext, effect: EffectWrapper, options?: EffectRendererOptions): EffectRenderer;
987
1430
 
988
1431
  /**
989
1432
  * Create a frame-graph task that draws an effect as a fullscreen pass into `config.target`.
@@ -1003,9 +1446,15 @@ export declare function createEffectRenderTask(config: EffectRenderTaskConfig, e
1003
1446
  */
1004
1447
  export declare function createEffectWrapper(engine: EngineContext, options: EffectWrapperOptions): EffectWrapper;
1005
1448
 
1006
- /** Create the Babylon Lite engine. Acquires GPU adapter + device, configures swapchain.
1007
- * Accepts either a DOM canvas (main thread) or an `OffscreenCanvas` (e.g. transferred to
1008
- * a Web Worker)see {@link RenderCanvas}. */
1449
+ /** Create the Babylon Lite engine bound to `canvas`. Acquires the GPU adapter + device,
1450
+ * configures the canvas's WebGPU context, and returns an `EngineContext` that *is also*
1451
+ * the primary `SurfaceContext`i.e. the returned engine is itself the surface for the
1452
+ * given canvas. Additional canvases can be attached afterwards via
1453
+ * `createSurface(engine, otherCanvas, ...)`; they share device-scoped GPU resources
1454
+ * (textures, meshes, pipelines, bind groups) with the engine and with each other.
1455
+ *
1456
+ * Accepts either a DOM canvas (main thread) or an `OffscreenCanvas` (e.g. transferred
1457
+ * to a Web Worker) — see {@link RenderCanvas}. */
1009
1458
  export declare function createEngine(canvas: RenderCanvas, options?: EngineOptions): Promise<EngineContext>;
1010
1459
 
1011
1460
  /**
@@ -1038,12 +1487,32 @@ export declare function createExtrudeShape(engine: EngineContext, options: Extru
1038
1487
  */
1039
1488
  export declare function createFacingBillboardSystem(atlas: SpriteAtlas, opts?: BillboardSpriteSystemOptions): FacingBillboardSpriteSystem;
1040
1489
 
1041
- /** Create a scene-less frame-graph context for fullscreen effects and post-process chains. */
1042
- export declare function createFrameGraphContext(engine: EngineContext, options?: FrameGraphContextOptions): FrameGraphContext;
1490
+ /** Build a `Font` from an in-memory TTF/OTF buffer. */
1491
+ export declare function createFontFromBuffer(data: ArrayBuffer): Font;
1492
+
1493
+ /** Create a scene-less frame-graph context bound to `surface`, for fullscreen effects
1494
+ * and post-process chains. Pass the engine directly for the single-canvas case (since
1495
+ * `EngineContext extends SurfaceContext`); pass an auxiliary surface for multi-canvas. */
1496
+ export declare function createFrameGraphContext(surface: SurfaceContext, options?: FrameGraphContextOptions): FrameGraphContext;
1043
1497
 
1044
1498
  /** Create a FreeCamera at the given position looking at target. Pure data, no scene knowledge. */
1045
1499
  export declare function createFreeCamera(position: Vec3, target: Vec3): FreeCamera;
1046
1500
 
1501
+ /** Create a geometry-renderer task. All GPU resources are allocated lazily
1502
+ * during the first `record()` call (when the frame graph is built). */
1503
+ export declare function createGeometryRendererTask(config: GeometryRendererTaskConfig, engine: EngineContext, scene: SceneContext): GeometryRendererTask;
1504
+
1505
+ /** Create a {@link GeospatialCamera} for a planet of the given radius. Pure data, no scene knowledge. */
1506
+ export declare function createGeospatialCamera(options: GeospatialCameraOptions): GeospatialCamera;
1507
+
1508
+ /** Create geospatial limits for a planet of the given radius, matching Babylon.js defaults. */
1509
+ export declare function createGeospatialLimits(planetRadius: number): GeospatialLimits;
1510
+
1511
+ /** Build a `GlyphStorage`. If `initial` is provided, each curve-set is packed into its
1512
+ * own atlas synchronously. The passed inner maps are *adopted* by the storage — the
1513
+ * caller must not mutate them directly afterward (use `updateGlyphStorage` instead). */
1514
+ export declare function createGlyphStorage(initial?: Map<CurveSetId, Map<number, GlyphCurves>>): GlyphStorage;
1515
+
1047
1516
  /** Create a GPU picker bound to the given scene. */
1048
1517
  export declare function createGpuPicker(scene: SceneContext): GpuPicker;
1049
1518
 
@@ -1080,6 +1549,9 @@ export declare function createGroundFromHeightMap(engine: EngineContext, url: st
1080
1549
  * const hknp = await HavokPhysics({ locateFile: () => "/HavokPhysics.wasm" });
1081
1550
  * const world = createHavokWorld(scene, hknp);
1082
1551
  * ```
1552
+ *
1553
+ * For Large World Rendering, call {@link enableHavokFloatingOrigin} on the returned world (before
1554
+ * creating any bodies) to opt into multi-region floating-origin simulation.
1083
1555
  */
1084
1556
  export declare function createHavokWorld(scene: SceneContext, hknp: any, gravity?: Vec3): PhysicsWorld;
1085
1557
 
@@ -1097,6 +1569,11 @@ export declare function createHemisphericLight(direction?: [number, number, numb
1097
1569
  */
1098
1570
  export declare function createImageProcessingTask(config: ImageProcessingTaskConfig, engine: EngineContext, scene: SceneContext): Task;
1099
1571
 
1572
+ /** Build a display-only light gizmo and attach it to the utility layer. The
1573
+ * per-light-type geometry is built lazily on the first `attachLightGizmoToLight`
1574
+ * (since the light type isn't known until then). */
1575
+ export declare function createLightGizmo(engine: EngineContext, layer: UtilityLayer, options?: LightGizmoOptions): LightGizmo;
1576
+
1100
1577
  /** Create a linear-depth ShaderMaterial that writes `(d, d, d, 1)` per fragment.
1101
1578
  * The depth is computed from the view-space z, normalized by the supplied
1102
1579
  * near/far range (or 0.03/15 by default). Override per material via the
@@ -1176,6 +1653,11 @@ export declare function createNavigationPluginAsync(options?: {
1176
1653
  */
1177
1654
  export declare function createNavMesh(plugin: NavigationPlugin, meshes: Mesh[], params: NavMeshParameters): void;
1178
1655
 
1656
+ /** Build a navmesh from raw CPU geometry sources. This is the non-rendering twin of
1657
+ * `createNavMesh`: callers that already own procedural navigation geometry can avoid
1658
+ * creating hidden GPU meshes just to feed Recast. */
1659
+ export declare function createNavMeshFromSources(plugin: NavigationPlugin, sources: NavMeshSource[], params: NavMeshParameters): void;
1660
+
1179
1661
  /** Create a no-color view over a NodeMaterial source. */
1180
1662
  export declare function createNodeNoColorMaterialView(source: NodeMaterial): MaterialView;
1181
1663
 
@@ -1234,6 +1716,14 @@ export declare function createPhysicsShape(world: PhysicsWorld, options: Physics
1234
1716
  /** Create a plane (unit quad facing -Z). Caller must assign material. */
1235
1717
  export declare function createPlane(engine: EngineContext, options?: PlaneOptions): Mesh;
1236
1718
 
1719
+ export declare function createPlaneDragGizmo(engine: EngineContext, layer: UtilityLayer, options: PlaneDragGizmoOptions): PlaneDragGizmo;
1720
+
1721
+ export declare function createPlaneRotationGizmo(engine: EngineContext, layer: UtilityLayer, options: PlaneRotationGizmoOptions): PlaneRotationGizmo;
1722
+
1723
+ /** Build a PointerDrag descriptor. The drag is inert until `registerPointerDrag`
1724
+ * is called against a utility layer with collider meshes assigned to it. */
1725
+ export declare function createPointerDrag(options: PointerDragOptions): PointerDrag;
1726
+
1237
1727
  /**
1238
1728
  * Creates a point light that emits in all directions from `position` with distance falloff.
1239
1729
  * @param position - World-space position of the light.
@@ -1245,6 +1735,11 @@ export declare function createPointLight(position: [number, number, number], int
1245
1735
  /** Create a polyhedron (15 presets). Caller must assign material. */
1246
1736
  export declare function createPolyhedron(engine: EngineContext, options?: PolyhedronOptions): Mesh;
1247
1737
 
1738
+ /** Build a composite position gizmo. Colors match BJS PositionGizmo
1739
+ * defaults: half-saturation red / green / blue along X / Y / Z
1740
+ * (`Color3.Red().scale(0.5)` etc.). */
1741
+ export declare function createPositionGizmo(engine: EngineContext, layer: UtilityLayer, options?: PositionGizmoOptions): PositionGizmo;
1742
+
1248
1743
  /**
1249
1744
  * Creates a Gaussian Splatting mesh with `splatCount` placeholder splats and attaches
1250
1745
  * it to the scene's render pipeline. Useful for procedurally filling splat data later.
@@ -1304,11 +1799,33 @@ export declare function createRenderTargetTexture(engine: EngineContext, descrip
1304
1799
  * Swapchain-targeted tasks acquire the swap view per-frame at execute time. */
1305
1800
  export declare function createRenderTask(config: RenderTaskConfig, engine: EngineContext, scene: SceneContext): RenderTask;
1306
1801
 
1802
+ /**
1803
+ * Create an empty `Texture2D` usable as **both a render target and a sampled texture**
1804
+ * (`RENDER_ATTACHMENT | TEXTURE_BINDING`). This is the building block for offscreen
1805
+ * render-to-texture: render a pass into `tex.view`, then sample `tex` in a later pass
1806
+ * (e.g. a fullscreen post-process). Defaults to the engine's swapchain format + a
1807
+ * linear sampler so the result can be presented directly.
1808
+ *
1809
+ * To use the result as a `SpriteRenderer` target (via `setSpriteRendererTarget`), leave
1810
+ * `format` at its default `engine.format` — sprite pipelines bake in that format, so a
1811
+ * differently-formatted target trips WebGPU validation at render-pass begin. A custom
1812
+ * `format` is for offscreen targets driven by some other pass, not the sprite renderer.
1813
+ */
1814
+ export declare function createRenderTexture2D(engine: EngineContext, width: number, height: number, options?: RenderTexture2DOptions): Texture2D;
1815
+
1307
1816
  /** Create a ribbon from an array of parallel Vec3 paths. Caller must assign material. */
1308
1817
  export declare function createRibbon(engine: EngineContext, options: RibbonOptions): Mesh;
1309
1818
 
1310
- /** Create an empty scene context bound to the given engine. */
1311
- export declare function createSceneContext(engine: EngineContext, options?: SceneContextOptions): SceneContext;
1819
+ export declare function createRotationGizmo(engine: EngineContext, layer: UtilityLayer, options?: RotationGizmoOptions): RotationGizmo;
1820
+
1821
+ export declare function createScaleGizmo(engine: EngineContext, layer: UtilityLayer, options?: ScaleGizmoOptions): ScaleGizmo;
1822
+
1823
+ /** Create an empty scene context bound to the given `surface`. The default render task
1824
+ * is built against the surface's format, MSAA configuration, and swapchain RT — the
1825
+ * scene is permanently bound to that surface. Pass `engine` directly (since
1826
+ * `EngineContext extends SurfaceContext`) for the common single-canvas case, or pass
1827
+ * an auxiliary surface created via `createSurface`. */
1828
+ export declare function createSceneContext(surface: SurfaceContext, options?: SceneContextOptions): SceneContext;
1312
1829
 
1313
1830
  /** Create a ShaderMaterial from WGSL sources and declarations, validating
1314
1831
  * attributes, uniforms, samplers, and defines.
@@ -1316,6 +1833,22 @@ export declare function createSceneContext(engine: EngineContext, options?: Scen
1316
1833
  * @returns The constructed `ShaderMaterial`. */
1317
1834
  export declare function createShaderMaterial(options: ShaderMaterialOptions): ShaderMaterial;
1318
1835
 
1836
+ /**
1837
+ * Create a no-colour view over a ShaderMaterial source, used by the shadow caster pass.
1838
+ *
1839
+ * Unlike standard/PBR/node, a ShaderMaterial needs no feature flag to drop its colour output: the shader
1840
+ * pipeline already omits the fragment stage when the render target has no colour attachment (the depth-only
1841
+ * shadow map). The view exists purely so the caster gets its OWN renderable + system UBO (written with the
1842
+ * shadow camera's view-projection) instead of clobbering the source material's main-pass UBO.
1843
+ */
1844
+ export declare function createShaderNoColorMaterialView(source: ShaderMaterial): MaterialView;
1845
+
1846
+ /** Wrap a ShaderMaterial as a normal-buffer view. The returned view renders the
1847
+ * source's geometry (instancing/displacement intact) but writes the geometric
1848
+ * normal instead of the material's colour. Idempotent-friendly: create one per
1849
+ * source and reuse it. */
1850
+ export declare function createShaderNormalMaterialView(source: ShaderMaterial, config?: ShaderNormalViewConfig): MaterialView;
1851
+
1319
1852
  /** Create a 1×1 solid-color `Texture2D` from straight RGBA components in [0, 1].
1320
1853
  * @param engine - Engine context.
1321
1854
  * @param r - Red channel (0–1).
@@ -1364,7 +1897,11 @@ export declare function createSpriteAnimationManager(options?: SpriteAnimationMa
1364
1897
  * Pack `sources` into a single `SpriteAtlas`. Shelf-packs in input order: each
1365
1898
  * frame is placed left-to-right on the current shelf, wrapping to a new shelf
1366
1899
  * (row) when it would overflow `maxWidthPx`. The texture is sized exactly to the
1367
- * packed content.
1900
+ * packed content unless `options.capacityPx` is supplied to reserve headroom for
1901
+ * later `appendSpriteAtlasFrames` calls.
1902
+ *
1903
+ * Pass `sources: []` together with `options.capacityPx` to create an empty atlas
1904
+ * sized for future appends.
1368
1905
  */
1369
1906
  export declare function createSpriteAtlasFromFrames(engine: EngineContext, sources: readonly SpriteAtlasFrameSource[], options?: SpriteAtlasPackOptions): SpriteAtlas;
1370
1907
 
@@ -1381,8 +1918,11 @@ export declare function createSpriteAtlasFromFrames(engine: EngineContext, sourc
1381
1918
  */
1382
1919
  export declare function createSpriteFrameAnimation(target: SpriteAnimationTarget, from: number, to: number, loop: boolean, delayMs: number, options?: PlaySpriteAnimationOptions): SpriteFrameAnimation;
1383
1920
 
1384
- /** Create a `SpriteRenderer` for `engine`, pre-warming pipelines for the layers' blend modes. */
1385
- export declare function createSpriteRenderer(engine: EngineContext, opts: SpriteRendererOptions): SpriteRenderer;
1921
+ /** Create a `SpriteRenderer` for `surface`, pre-warming pipelines for the layers' blend
1922
+ * modes. Pass the engine directly for the common single-canvas case (since
1923
+ * `EngineContext extends SurfaceContext`); pass an auxiliary surface created via
1924
+ * `createSurface` for multi-canvas. */
1925
+ export declare function createSpriteRenderer(surface: SurfaceContext, opts: SpriteRendererOptions): SpriteRenderer;
1386
1926
 
1387
1927
  /** Create StandardMaterial with Babylon defaults. */
1388
1928
  export declare function createStandardMaterial(): StandardMaterialProps;
@@ -1391,6 +1931,32 @@ export declare function createStandardMaterial(): StandardMaterialProps;
1391
1931
  * The view references the source; material state is never copied. */
1392
1932
  export declare function createStandardNoColorMaterialView(source: StandardMaterialProps): MaterialView;
1393
1933
 
1934
+ /**
1935
+ * Create an auxiliary rendering surface bound to an existing engine. The surface
1936
+ * configures its own `GPUCanvasContext` against `engine._device` and is appended to
1937
+ * `engine.surfaces`. GPU resources (textures, buffers, pipelines) are shared across
1938
+ * all surfaces of the same engine because they're device-scoped — render to multiple
1939
+ * canvases by creating additional surfaces and binding scenes / renderers to each.
1940
+ *
1941
+ * The engine's own primary surface (`engine.surfaces[0] === engine`) is created
1942
+ * automatically by `createEngine(canvas)`; use `createSurface` only for additional
1943
+ * canvases beyond that one.
1944
+ *
1945
+ * Accepts either a DOM canvas (main thread) or an `OffscreenCanvas` (e.g. transferred
1946
+ * to a Web Worker via `transferControlToOffscreen()`).
1947
+ */
1948
+ export declare function createSurface(engine: EngineContext, canvas: RenderCanvas, options?: SurfaceOptions): SurfaceContext;
1949
+
1950
+ /** Create a TextData bound to `storage`. If `runs` is omitted the TextData starts empty;
1951
+ * runs can be appended later via `updateTextData({ update: "addRun", … })`. */
1952
+ export declare function createTextData(storage: GlyphStorage, runs?: readonly GlyphRun[]): TextData;
1953
+
1954
+ export declare function createTextLayer(data: TextData, options?: TextLayerOptions): TextLayer;
1955
+
1956
+ export declare function createTextRenderable(data: TextData, options?: TextRenderableOptions): TextRenderable;
1957
+
1958
+ export declare function createTextRenderer(surface: SurfaceContext, opts: TextRendererOptions): TextRenderer;
1959
+
1394
1960
  /**
1395
1961
  * Create a `Texture2D` from a tightly-packed RGBA8 byte buffer.
1396
1962
  *
@@ -1441,6 +2007,14 @@ export declare function createUniformEffectRenderTask(config: UniformEffectRende
1441
2007
  */
1442
2008
  export declare function createUniformEffectWrapper(engine: EngineContext, options: UniformEffectWrapperOptions): UniformEffectWrapper;
1443
2009
 
2010
+ /** Create a utility layer attached to the given engine + main scene.
2011
+ * The returned `scene` shares the main scene's camera so view + projection
2012
+ * remain in sync without manual mirroring. The utility scene renders with a
2013
+ * fresh-cleared depth buffer (so its gizmos appear on top of the main scene)
2014
+ * while keeping NORMAL intra-layer depth testing — solid gizmo bodies (e.g.
2015
+ * the camera-gizmo box + cylinders) occlude their own back faces correctly. */
2016
+ export declare function createUtilityLayer(engine: EngineContext, mainScene: SceneContext, options?: UtilityLayerOptions): UtilityLayer;
2017
+
1444
2018
  /** Cross-fades from `fromGroup` to `toGroup`, fading the first to weight 0 and the second to `options.toWeight` (default 1). */
1445
2019
  export declare function crossFadeAnimationGroups(manager: AnimationManager, fromGroup: AnimationGroup, toGroup: AnimationGroup, options: CrossFadeAnimationGroupsOptions): void;
1446
2020
 
@@ -1513,6 +2087,15 @@ export declare interface CsmDirectionalShadowGeneratorConfig {
1513
2087
  forceRefreshEveryFrame?: boolean;
1514
2088
  }
1515
2089
 
2090
+ /** Approximate a cubic Bézier with two quadratics using the "3/4 rule" (matches Slug reference).
2091
+ * Exposed as a public helper so callers that ingest cubic outlines from their own font sources
2092
+ * (e.g. DirectWrite, FreeType) can convert into the quadratic-only format `GlyphCurves` expects. */
2093
+ export declare function cubicToQuadratics(p0x: number, p0y: number, c1x: number, c1y: number, c2x: number, c2y: number, p1x: number, p1y: number): [QuadCurve, QuadCurve];
2094
+
2095
+ /** Identifier for a curve set (a font's glyph-curves map). Strings let callers use a
2096
+ * human-readable key (e.g. the font face name) for easy debugging. */
2097
+ export declare type CurveSetId = string;
2098
+
1516
2099
  /** One extra texture bound after the atlas. In WGSL it becomes `<name>Tex` + `<name>Samp`. */
1517
2100
  export declare interface CustomShaderTexture {
1518
2101
  /** Identifier used in WGSL: becomes `<name>Tex` (texture) and `<name>Samp` (sampler). */
@@ -1520,6 +2103,26 @@ export declare interface CustomShaderTexture {
1520
2103
  readonly texture: Texture2D;
1521
2104
  }
1522
2105
 
2106
+ /**
2107
+ * CreateCylinder — matches Babylon.js MeshBuilder.CreateCylinder default options.
2108
+ *
2109
+ * Supports cylinders, cones (diameterTop=0), truncated cones, and prisms
2110
+ * (low tessellation). Options are a subset of Babylon's MeshBuilder that
2111
+ * covers the typical procedural use-case. Advanced options — `arc`,
2112
+ * `enclose`, `hasRings`, `faceColors`, `faceUV`, `cap != CAP_ALL` — are
2113
+ * intentionally omitted to keep the API small; the default behavior (full
2114
+ * 360°, single ring, CAP_ALL) matches Babylon exactly.
2115
+ *
2116
+ * Index order and normal computation are ported verbatim from
2117
+ * `@babylonjs/core/Meshes/Builders/cylinderBuilder.js` to guarantee parity.
2118
+ */
2119
+ export declare interface CylinderData {
2120
+ positions: Float32Array;
2121
+ normals: Float32Array;
2122
+ uvs: Float32Array;
2123
+ indices: Uint32Array;
2124
+ }
2125
+
1523
2126
  /** Options for `createCylinderData`. Subset of Babylon's CreateCylinder. */
1524
2127
  export declare interface CylinderOptions {
1525
2128
  height?: number;
@@ -1530,6 +2133,69 @@ export declare interface CylinderOptions {
1530
2133
  subdivisions?: number;
1531
2134
  }
1532
2135
 
2136
+ /** Convenience text-data variant that owns its `GlyphStorage` and exposes the laid-out
2137
+ * pixel-space `width` / `height` of the text block. Produced by `createDefaultTextData`. */
2138
+ export declare interface DefaultTextData extends TextData {
2139
+ readonly [defaultTextDataBrand]: true;
2140
+ /** Pixel-space width of the laid-out run (max line width). */
2141
+ readonly width: number;
2142
+ /** Pixel-space height of the laid-out run (lines × line-height). */
2143
+ readonly height: number;
2144
+
2145
+ declare const defaultTextDataBrand: unique symbol;
2146
+
2147
+ /** Quality of the depth-of-field blur. Models BJS `ThinDepthOfFieldEffectBlurLevel`. */
2148
+ export declare enum DepthOfFieldBlurLevel {
2149
+ /** Subtle blur — 1 blur level, kernel 15. */
2150
+ Low = 0,
2151
+ /** Medium blur — 2 blur levels, kernel 31. */
2152
+ Medium = 1,
2153
+ /** Large blur — 3 blur levels, kernel 51. */
2154
+ High = 2
2155
+ }
2156
+
2157
+ /** A composite depth-of-field post-process task: circle-of-confusion → CoC-weighted blur pyramid → merge. */
2158
+ export declare interface DepthOfFieldPostProcessTask extends Task, PostProcessTaskSettings {
2159
+ readonly name: string;
2160
+ sourceTexture: RenderTarget;
2161
+ targetTexture: RenderTarget | null;
2162
+ outputTexture: RenderTarget;
2163
+ lensSize: number;
2164
+ fStop: number;
2165
+ focusDistance: number;
2166
+ focalLength: number;
2167
+ /** Recompute and upload the uniforms of every sub-pass (CoC, blurs, merge). */
2168
+ updateUniforms(): void;
2169
+ }
2170
+
2171
+ /**
2172
+ * Configuration for `createDepthOfFieldPostProcessTask`.
2173
+ *
2174
+ * Models Babylon.js's `FrameGraphDepthOfFieldTask` + `ThinDepthOfFieldEffect`:
2175
+ * a circle-of-confusion pass feeds a stack of CoC-weighted separable blurs,
2176
+ * which are merged back over the sharp image for a physically-plausible
2177
+ * depth-of-field effect.
2178
+ */
2179
+ export declare interface DepthOfFieldPostProcessTaskConfig extends PostProcessTaskSettings {
2180
+ /** Depth texture. With `depthNotNormalized` it stores camera-space (view)
2181
+ * depth; otherwise normalized [0,1] view depth. */
2182
+ depthTexture: RenderTarget;
2183
+ /** Camera used to read minZ/maxZ when the depth is normalized. */
2184
+ camera: Camera;
2185
+ /** Max lens size in scene units / 1000. Default 50. */
2186
+ lensSize?: number;
2187
+ /** F-Stop of the camera. Default 1.4. */
2188
+ fStop?: number;
2189
+ /** Distance from the camera to focus on, in scene units / 1000. Default 2000. */
2190
+ focusDistance?: number;
2191
+ /** Focal length of the camera in scene units / 1000. Default 50. */
2192
+ focalLength?: number;
2193
+ /** Blur quality. Default {@link DepthOfFieldBlurLevel.Low}. */
2194
+ blurLevel?: DepthOfFieldBlurLevel;
2195
+ /** When true the depth texture stores camera-space depth (0..maxZ). */
2196
+ depthNotNormalized?: boolean;
2197
+ }
2198
+
1533
2199
  export declare interface DirectionalLight extends LightBase {
1534
2200
  readonly lightType: "directional";
1535
2201
  direction: ObservableVec3;
@@ -1547,23 +2213,41 @@ export declare interface DiscOptions {
1547
2213
  arc?: number;
1548
2214
  }
1549
2215
 
2216
+ /** Dispose the gizmo: remove meshes, unregister pointer-drag, drop materials. */
2217
+ export declare function disposeAxisDragGizmo(gizmo: AxisDragGizmo, layer: UtilityLayer): void;
2218
+
2219
+ export declare function disposeAxisScaleGizmo(gizmo: AxisScaleGizmo, layer: UtilityLayer): void;
2220
+
2221
+ export declare function disposeBoundingBoxGizmo(gizmo: BoundingBoxGizmo, layer: UtilityLayer): void;
2222
+
2223
+ export declare function disposeCameraGizmo(gizmo: CameraGizmo, layer: UtilityLayer): void;
2224
+
1550
2225
  /** Frees the WASM memory backing a solid. The solid must not be used afterwards. */
1551
2226
  export declare function disposeCsg2(solid: Csg2Solid): void;
1552
2227
 
2228
+ /** Release the per-block GPU resources AND the underlying `GlyphStorage` owned by `data`. */
2229
+ export declare function disposeDefaultTextData(data: DefaultTextData): void;
2230
+
1553
2231
  /** Unregister and free all GPU resources owned by the renderer. */
1554
2232
  export declare function disposeEffectRenderer(er: EffectRenderer): void;
1555
2233
 
1556
2234
  /** Destroy the uniform buffers and clear the cached pipelines, bind groups, and slots owned by the effect wrapper. */
1557
2235
  export declare function disposeEffectWrapper(wrapper: EffectWrapper): void;
1558
2236
 
1559
- /** Release all engine-owned GPU resources (device + swapchain). Rendering contexts
1560
- * own their own GPU resources (frame graphs, render targets) and dispose them
1561
- * separately. */
2237
+ /** Release all engine-owned GPU resources (device + every attached surface's swapchain
2238
+ * context). Rendering contexts own their own GPU resources (frame graphs, render
2239
+ * targets) and dispose them separately. */
1562
2240
  export declare function disposeEngine(engine: EngineContext): void;
1563
2241
 
1564
2242
  /** Unregister and dispose all GPU resources owned by the standalone frame graph. */
1565
2243
  export declare function disposeFrameGraphContext(ctx: FrameGraphContext): void;
1566
2244
 
2245
+ /** Release every GPU atlas owned by `storage`. Idempotent. The caller is responsible for
2246
+ * ensuring no `TextData` is still drawing from this storage. */
2247
+ export declare function disposeGlyphStorage(storage: GlyphStorage): void;
2248
+
2249
+ export declare function disposeLightGizmo(gizmo: LightGizmo, layer: UtilityLayer): void;
2250
+
1567
2251
  /**
1568
2252
  * Removes and releases all bodies, then releases the native world. Call once when tearing down physics.
1569
2253
  * @param world - The physics world to dispose.
@@ -1573,6 +2257,16 @@ export declare function disposePhysics(world: PhysicsWorld): void;
1573
2257
  /** Dispose GPU resources owned by this picker. */
1574
2258
  export declare function disposePicker(picker: GpuPicker): void;
1575
2259
 
2260
+ export declare function disposePlaneDragGizmo(gizmo: PlaneDragGizmo, layer: UtilityLayer): void;
2261
+
2262
+ export declare function disposePlaneRotationGizmo(gizmo: PlaneRotationGizmo, layer: UtilityLayer): void;
2263
+
2264
+ export declare function disposePositionGizmo(gizmo: PositionGizmo, layer: UtilityLayer): void;
2265
+
2266
+ export declare function disposeRotationGizmo(gizmo: RotationGizmo, layer: UtilityLayer): void;
2267
+
2268
+ export declare function disposeScaleGizmo(gizmo: ScaleGizmo, layer: UtilityLayer): void;
2269
+
1576
2270
  /** Release all GPU resources owned by this scene. */
1577
2271
  export declare function disposeScene(scene: SceneContext): void;
1578
2272
 
@@ -1591,9 +2285,29 @@ export declare function disposeSpriteAnimationBinding(binding: SpriteAnimationBi
1591
2285
  */
1592
2286
  export declare function disposeSpriteRenderer(sr: SpriteRenderer): void;
1593
2287
 
2288
+ /** Remove and unconfigure an auxiliary surface from its engine. Rendering contexts
2289
+ * registered on this surface are dropped from its list but not disposed — call their
2290
+ * own disposers (e.g. `disposeScene`) separately.
2291
+ *
2292
+ * Throws if called on the engine's primary surface (`surface === engine`); use
2293
+ * `disposeEngine` to tear down the engine and all its surfaces. */
2294
+ export declare function disposeSurface(surface: SurfaceContext): void;
2295
+
2296
+ /** Release per-block GPU resources owned by `data`. Does NOT dispose the bound
2297
+ * `GlyphStorage` — caller owns its lifetime and must dispose it separately via
2298
+ * `disposeGlyphStorage` once no `TextData` references it. */
2299
+ export declare function disposeTextData(data: TextData): void;
2300
+
2301
+ export declare function disposeTextRenderable(renderable: TextRenderable): void;
2302
+
2303
+ export declare function disposeTextRenderer(tr: TextRenderer): void;
2304
+
1594
2305
  /** Destroy the uniform buffer and clear cached GPU objects owned by the uniform effect wrapper. */
1595
2306
  export declare function disposeUniformEffectWrapper(wrapper: UniformEffectWrapper): void;
1596
2307
 
2308
+ /** Dispose the utility layer's underlying scene. Idempotent. */
2309
+ export declare function disposeUtilityLayer(utility: UtilityLayer): void;
2310
+
1597
2311
  /**
1598
2312
  * A per-pass draw binding produced by `Renderable.bind(engine, target)`.
1599
2313
  *
@@ -1708,6 +2422,23 @@ export declare function enableAnimationBlending(manager: AnimationManager): void
1708
2422
  */
1709
2423
  export declare function enableDetailedPicking(picker: GpuPicker): void;
1710
2424
 
2425
+ /**
2426
+ * Opt a Havok world into multi-region floating-origin simulation (Large World Rendering).
2427
+ *
2428
+ * Loads the floating-origin runtime on demand (`physics/havok-floating-origin.ts`) so worlds that
2429
+ * never call this — i.e. ordinary near-origin physics scenes — never pull that code into their
2430
+ * bundle. Once enabled, bodies far apart in world space are simulated in separate regions (each
2431
+ * within `floatingOriginWorldRadius` of its origin) so the float32 Havok solver keeps full
2432
+ * precision. Node transforms remain true world coordinates; eye-relative rendering is handled
2433
+ * independently by the floating-origin render path.
2434
+ *
2435
+ * Must be called **before** creating any bodies in the world. Pair it with an engine created with
2436
+ * `useFloatingOrigin: true` so rendering and physics share the same far-from-origin handling.
2437
+ * @param world - The physics world to enable floating origin on.
2438
+ * @param floatingOriginWorldRadius - Region capture radius in metres (default 100000, matching Babylon.js).
2439
+ */
2440
+ export declare function enableHavokFloatingOrigin(world: PhysicsWorld, floatingOriginWorldRadius?: number): Promise<void>;
2441
+
1711
2442
  /**
1712
2443
  * Enable material-plugin support for `scene`.
1713
2444
  *
@@ -1747,14 +2478,22 @@ export declare function enableThinInstanceGpuCulling(mesh: Mesh, enabled?: boole
1747
2478
  /** CPU helper matching BJS `GaussianSplattingGpuPickingMaterialPlugin.EncodeIdToColor`. */
1748
2479
  export declare function encodeIdToColor(id: number): [number, number, number];
1749
2480
 
1750
- /** Handle to the WebGPU engine — pure state, no attached methods. */
1751
- export declare interface EngineContext {
1752
- readonly canvas: RenderCanvas;
1753
- readonly msaaSamples: number;
1754
- /** Preferred GPU texture format for the swapchain. Use as the `colorFormat`
1755
- * for offscreen RTs that are sampled by main-pass materials. */
1756
- readonly format: GPUTextureFormat;
1757
- /** Number of GPU draw calls in the last rendered frame. */
2481
+ /**
2482
+ * Handle to the WebGPU engine — pure state, no attached methods.
2483
+ *
2484
+ * The engine owns the `GPUDevice` and all device-scoped GPU resources (textures, buffers,
2485
+ * pipelines, bind groups). It also **is itself a {@link SurfaceContext}** bound to the
2486
+ * canvas passed into `createEngine` the primary surface. Additional canvases can be
2487
+ * attached via `createSurface(engine, canvas, ...)`; GPU resources are shared across all
2488
+ * surfaces because they're device-scoped, while each surface owns its own swapchain
2489
+ * context.
2490
+ */
2491
+ export declare interface EngineContext extends SurfaceContext {
2492
+ /** Rendering surfaces attached to this engine, in registration order. Index 0 is
2493
+ * the engine itself (the primary surface) — the tuple type guarantees at least
2494
+ * one entry so `engine.surfaces[0]` is always defined. Use
2495
+ * `createSurface(engine, canvas, ...)` to append more. */
2496
+ readonly surfaces: readonly [SurfaceContext, ...SurfaceContext[]];
1758
2497
  /** Number of GPU draw calls in the last rendered frame, summed across all surfaces. */
1759
2498
  drawCallCount: number;
1760
2499
  /**
1761
2500
  * When true, world matrices are computed using Float64 intermediate precision
@@ -1771,27 +2510,21 @@ export declare interface EngineContext {
1771
2510
  * dynamically imported during `createEngine` only when this flag is true,
1772
2511
  * so non-LWR engines never pull the module into their bundle.
1773
2512
  */
1774
- useFloatingOrigin: boolean;
1775
- /** Clamps the effective device pixel ratio used for the swapchain backing store.
1776
- * The backing store is sized at `min(devicePixelRatio, maxDevicePixelRatio) * cssPixels`.
1777
- * `maxDevicePixelRatio = 1` renders at native CSS-pixel resolution (no DPR upscaling);
1778
- * the default `Infinity` is unclamped (full devicePixelRatio). Mutable at runtime — set
1779
- * before the next `resizeEngine` to take effect (mirrors `setHardwareScalingRatio`). */
1780
- maxDevicePixelRatio: number;
2513
+ useFloatingOrigin: boolean;
1781
2514
 
1782
2515
  /**
1783
- * Options for `createEngine`.
1784
- * - `msaaSamples`: number of MSAA samples to use for the main render pass.
1785
- * WebGPU only permits `1` (no MSAA) or `4` (4x MSAA) per the spec
1786
- * (2x is not a valid WebGPU sample count). Defaults to `4`.
2516
+ * Options for `createEngine`. Per-surface options for the primary surface (the canvas
2517
+ * passed to `createEngine`) come from {@link SurfaceOptions} and are passed alongside
2518
+ * the engine options as a single union: `createEngine(canvas, opts: EngineOptions & SurfaceOptions)`.
1787
2519
  */
1788
- export declare interface EngineOptions {
1789
- msaaSamples?: 1 | 4;
2520
+ export declare interface EngineOptions extends SurfaceOptions {
1790
2521
  /**
1791
- * WebGPU canvas alpha mode. Use "premultiplied" to enable canvas transparency (clear color
1792
- * with `alpha < 1` will let HTML content underneath show through). Defaults to "opaque".
2522
+ * Extra WebGPU device limits to request when calling `adapter.requestDevice()`.
2523
+ * Use to raise per-device caps such as `maxColorAttachmentBytesPerSample` (default 32),
2524
+ * which is required when rendering into many MRT attachments. Caller is responsible for
2525
+ * staying within the adapter's reported limits.
1793
2526
  */
1794
- alphaMode?: GPUCanvasAlphaMode;
2527
+ requiredLimits?: Record<string, GPUSize64 | undefined>;
1795
2528
  /**
1796
2529
  * Enable Float64 intermediate precision for world matrix computations. Defaults to false.
1797
2530
  */
@@ -1807,14 +2540,6 @@ export declare interface EngineOptions {
1807
2540
  * pattern as the F64 storage module).
1808
2541
  */
1809
2542
  useFloatingOrigin?: boolean;
1810
- /**
1811
- * Clamps the effective device pixel ratio used for the swapchain backing store.
1812
- * The backing store is sized at `min(devicePixelRatio, maxDevicePixelRatio) * cssPixels`.
1813
- * `maxDevicePixelRatio: 1` renders at native CSS-pixel resolution (no DPR upscaling) —
1814
- * useful on high-DPI/iOS devices where `devicePixelRatio` is ~3. Defaults to unclamped
1815
- * (full devicePixelRatio). Equivalent to Babylon.js `setHardwareScalingRatio`.
1816
- */
1817
- maxDevicePixelRatio?: number;
1818
2543
  }
1819
2544
 
1820
2545
  /** GPU-resident environment textures. */
@@ -1861,6 +2586,11 @@ declare interface EulerProxy {
1861
2586
  set(x: number, y: number, z: number): void;
1862
2587
  }
1863
2588
 
2589
+ /** Extract outlines for the requested glyph ids and add them to `target`.
2590
+ * Skips ids already present in `target`. Glyphs with no outline are silently skipped.
2591
+ * Mutates `target` directly — no allocation when no new glyphs appear. */
2592
+ export declare function extractGlyphCurves(font: Font, glyphIds: ReadonlySet<number>, target: Map<number, GlyphCurves>): void;
2593
+
1864
2594
  /** A post-process task that keeps only pixels whose luminance exceeds `threshold` and zeroes the rest. */
1865
2595
  export declare interface ExtractHighlightsPostProcessTask extends PostProcessTask {
1866
2596
  threshold: number;
@@ -1909,6 +2639,17 @@ export declare function findRandomPointAroundCircle(plugin: NavigationPlugin, po
1909
2639
  /** Mark thin instance data dirty after direct array manipulation. */
1910
2640
  export declare function flushThinInstances(mesh: Mesh): void;
1911
2641
 
2642
+ /**
2643
+ * Smoothly animate a {@link GeospatialCamera} to new yaw/pitch/radius/centre over
2644
+ * `durationMs`, driven by the scene's render loop. Yaw takes the shortest angular
2645
+ * path; the centre follows a great-circle (with an optional parabolic hop).
2646
+ *
2647
+ * The returned promise resolves when the flight completes; it also resolves early
2648
+ * if the flight is interrupted (by user input through `attachGeospatialControls`,
2649
+ * or by a subsequent `flyGeospatialCameraToAsync` call). Only one flight runs at a time.
2650
+ */
2651
+ export declare function flyGeospatialCameraToAsync(camera: GeospatialCamera, scene: SceneContext, options: GeospatialFlyOptions): Promise<void>;
2652
+
1912
2653
  /** Fog configuration — plain data. */
1913
2654
  export declare interface FogConfig {
1914
2655
  mode: 0 | 1 | 2 | 3;
@@ -1918,6 +2659,11 @@ export declare interface FogConfig {
1918
2659
  color: [number, number, number];
1919
2660
  }
1920
2661
 
2662
+ export declare interface Font {
2663
+ readonly [fontBrand]: true;
2664
+
2665
+ declare const fontBrand: unique symbol;
2666
+
1921
2667
  /** The frame graph — an ordered list of tasks. */
1922
2668
  export declare interface FrameGraph {
1923
2669
  /** Build (or rebuild) every task in execute order. */
1924
2670
  build(): void;
@@ -1930,7 +2676,8 @@ export declare interface FrameGraph {
1930
2676
  /** Build (or rebuild) every task in e
1931
2677
  /** A scene-less rendering context driven directly by a FrameGraph. */
1932
2678
  export declare interface FrameGraphContext extends RenderingContext_2 {
1933
2679
  readonly name: string;
1934
- readonly engine: EngineContext;
2680
+ /** Surface this context renders into. */
2681
+ readonly surface: SurfaceContext;
1935
2682
  readonly frameGraph: FrameGraph;
1936
2683
  clearColor: GPUColorDict;
1937
2684
  }
@@ -1988,6 +2735,251 @@ export declare interface GaussianSplattingMesh extends SceneNode {
1988
2735
  /** Numbe
1989
2736
  updateData(splatBuffer: ArrayBuffer): void;
1990
2737
  }
1991
2738
 
2739
+ export declare interface GeometryRendererTask extends Task {
2740
+ readonly name: string;
2741
+ /** The optional target texture the task wrote the real (lit) color into.
2742
+ * Equal to {@link GeometryRendererTaskConfig.targetTexture} when the
2743
+ * config provided one, otherwise `undefined`. */
2744
+ readonly outputTexture: RenderTarget | undefined;
2745
+ /** Single-attachment depth `RenderTarget` exposing the pass's depth/stencil
2746
+ * attachment. Downstream tasks (e.g. a `RenderTask` running after the
2747
+ * geometry pass) can consume this as a depth input to reuse the values
2748
+ * written here. When the caller supplied an external `depthTexture` in the
2749
+ * config, this returns that same RT; otherwise it wraps the MRT-owned
2750
+ * depth and is populated post-`record()`. */
2751
+ readonly geometryDepthTexture: RenderTarget;
2752
+ /** Per-type accessors. `null` when that type was not requested. Each value
2753
+ * is a single-attachment `RenderTarget` whose color slot aliases the
2754
+ * matching MRT attachment, so downstream tasks (copy-to-texture, etc.)
2755
+ * can consume it like an ordinary RT. */
2756
+ readonly geometryIrradianceTexture: RenderTarget | null;
2757
+ readonly geometryWorldPositionTexture: RenderTarget | null;
2758
+ readonly geometryLocalPositionTexture: RenderTarget | null;
2759
+ readonly geometryReflectivityTexture: RenderTarget | null;
2760
+ readonly geometryViewDepthTexture: RenderTarget | null;
2761
+ readonly geometryNormalizedViewDepthTexture: RenderTarget | null;
2762
+ readonly geometryScreenspaceDepthTexture: RenderTarget | null;
2763
+ readonly geometryViewNormalTexture: RenderTarget | null;
2764
+ readonly geometryWorldNormalTexture: RenderTarget | null;
2765
+ readonly geometryAlbedoTexture: RenderTarget | null;
2766
+ readonly geometryLinearVelocityTexture: RenderTarget | null;
2767
+ /** Skip a mesh from the velocity attachment's previous-world tracking. */
2768
+ excludeFromVelocity(mesh: Mesh): void;
2769
+ /** Re-include a mesh in velocity tracking. */
2770
+ includeInVelocity(mesh: Mesh): void;
2771
+ }
2772
+
2773
+ export declare interface GeometryRendererTaskConfig {
2774
+ name?: string;
2775
+ /** Caster meshes. When omitted, defaults to `scene.meshes`. */
2776
+ meshes?: readonly Mesh[];
2777
+ /** Per-pass camera override. Defaults to `scene.camera`. */
2778
+ camera?: Camera | null;
2779
+ /** Render-target size. Defaults to the scene's `surface`. */
2780
+ size?: SurfaceContext | {
2781
+ width: number;
2782
+ height: number;
2783
+ };
2784
+ /** MSAA sample count. Defaults to 1. */
2785
+ samples?: 1 | 4;
2786
+ /** Externally-owned depth attachment. When omitted, the task creates its
2787
+ * own `depth32float` depth texture sized to match the color attachments. */
2788
+ depthTexture?: RenderTarget | null;
2789
+ /** Ordered list of MRT attachments (1..8). The array index becomes the
2790
+ * fragment shader's `@location(i)` and the render-pass color attachment slot. */
2791
+ readonly textureDescriptions: readonly GeometryRendererTextureDescription[];
2792
+ /** Flip culling direction. Default false. */
2793
+ reverseCulling?: boolean;
2794
+ /** Optional color render-target that receives the *real* (lit) material
2795
+ * color, written as an additional color attachment alongside the geometry
2796
+ * data attachments. Must have the same {@link sampleCount} and resolved
2797
+ * pixel size as the geometry MRT (size: `<surface>` with samples matching).
2798
+ * When omitted, no real-color attachment is added to the pass.
2799
+ *
2800
+ * The target attachment uses `loadOp: "load"` (matches BJS), so the
2801
+ * caller must initialize the target's contents (e.g. via a clear pass)
2802
+ * before the geometry task runs — unless {@link targetTextureClearColor}
2803
+ * is provided. */
2804
+ targetTexture?: RenderTarget;
2805
+ /** When set together with {@link targetTexture}, the target attachment
2806
+ * uses `loadOp: "clear"` with this color at the start of the geometry
2807
+ * pass. Convenient for demo / standalone use where no prior task has
2808
+ * initialized the target's contents. */
2809
+ targetTextureClearColor?: GPUColor;
2810
+ }
2811
+
2812
+ /** One MRT color attachment requested by the user. */
2813
+ export declare interface GeometryRendererTextureDescription {
2814
+ /** Which geometry value to write. */
2815
+ readonly type: GeometryTextureType;
2816
+ /** Per-attachment WebGPU format override. Defaults to
2817
+ * {@link GEOMETRY_TEXTURE_DESCRIPTIONS}[type].defaultFormat. */
2818
+ readonly format?: GPUTextureFormat;
2819
+ /** Per-attachment clear-value override. Defaults to
2820
+ * {@link GEOMETRY_TEXTURE_DESCRIPTIONS}[type].clearValue. Use to match a
2821
+ * reference engine's clear behaviour (e.g. clear VIEW_DEPTH to 0 instead of
2822
+ * the camera far plane to mirror BJS's PREPASS_DEPTH). */
2823
+ readonly clearValue?: GPUColor;
2824
+ }
2825
+
2826
+ /**
2827
+ * Geometry renderer texture types.
2828
+ *
2829
+ * Each enum value corresponds to a single geometry attachment that
2830
+ * {@link createGeometryRendererTask} can write to. The companion
2831
+ * {@link GEOMETRY_TEXTURE_DESCRIPTIONS} table provides the default
2832
+ * per-type WebGPU format and the clear behaviour at the start of a
2833
+ * geometry pass.
2834
+ *
2835
+ * The enum is intentionally a subset of Babylon.js'
2836
+ * `MaterialHelperGeometryRendering.GeometryTextureDescriptions`. The
2837
+ * following BJS types are excluded by design:
2838
+ * - `ALBEDO_SQRT` — we only expose `ALBEDO`.
2839
+ * - `VELOCITY` (vec2 SS) — we only expose `LINEAR_VELOCITY` (vec3 WS).
2840
+ * - `IRRADIANCE_LEGACY` — we only expose `IRRADIANCE`.
2841
+ * - `COLOR` — handled separately via the geometry task's
2842
+ * optional `targetTexture` color attachment
2843
+ * (BJS `PREPASS_COLOR_INDEX`).
2844
+ *
2845
+ * Module is lazy-loaded by the geometry view and the geometry task only;
2846
+ * existing scenes never import it.
2847
+ */
2848
+ /** Identifies a single geometry texture supported by `createGeometryRendererTask`. */
2849
+ export declare enum GeometryTextureType {
2850
+ /** Half-float RGBA — diffuse irradiance accumulated at the surface. */
2851
+ IRRADIANCE = 0,
2852
+ /** Half-float RGBA — world-space position. */
2853
+ WORLD_POSITION = 1,
2854
+ /** Half-float RGBA — object-local position (before world transform). */
2855
+ LOCAL_POSITION = 2,
2856
+ /** Unorm8 RGBA — material reflectivity (rgb) + roughness (a). */
2857
+ REFLECTIVITY = 3,
2858
+ /** Float R — linear view-space depth (camera-far at the far plane). Cleared to camera far. */
2859
+ VIEW_DEPTH = 4,
2860
+ /** Half-float R — view-space depth normalized to [0,1] (1 at the far plane). */
2861
+ NORMALIZED_VIEW_DEPTH = 5,
2862
+ /** Half-float R — clip-space depth in [0,1] (matches GPU depth buffer post-projection). */
2863
+ SCREENSPACE_DEPTH = 6,
2864
+ /** Half-float RGBA — view-space surface normal. */
2865
+ VIEW_NORMAL = 7,
2866
+ /** Half-float RGBA — world-space surface normal. */
2867
+ WORLD_NORMAL = 8,
2868
+ /** Unorm8 RGBA — surface albedo (diffuse colour, no lighting). */
2869
+ ALBEDO = 9,
2870
+ /** Half-float RGBA — per-pixel linear world-space velocity in units / frame. */
2871
+ LINEAR_VELOCITY = 10
2872
+ }
2873
+
2874
+ /** Camera that orbits a spherical planet centred at the world origin (Babylon.js `GeospatialCamera`).
2875
+ *
2876
+ * Orientation is fully described by `center` (the anchored point on the globe in
2877
+ * ECEF coordinates), `yaw`, `pitch`, and `radius`. Setting any of these
2878
+ * recomputes the derived `position` / `upVector` and the view matrix.
2879
+ *
2880
+ * Pure state — behaviour is provided by standalone functions
2881
+ * ({@link setGeospatialOrientation}, `attachGeospatialControls`,
2882
+ * `flyGeospatialCameraToAsync`). The camera never references the scene. */
2883
+ export declare interface GeospatialCamera extends Camera, IWorldMatrixProvider, IParentable {
2884
+ /** The anchored point on the globe (ECEF). Assigning re-orbits around the new centre. */
2885
+ center: Vec3;
2886
+ /** Yaw about the geocentric up axis. Wrapped to [-π, π). 0 = north, π/2 = east. */
2887
+ yaw: number;
2888
+ /** Pitch from looking straight down (0) to the horizon (π/2). Wrapped to [-π, π). */
2889
+ pitch: number;
2890
+ /** Distance from the camera to its centre point (distinct from `planetRadius`). */
2891
+ radius: number;
2892
+ /** Limits governing yaw/pitch/radius clamping. Mutable; clamping applies on the next orientation change. */
2893
+ limits: GeospatialLimits;
2894
+ /** Derived world-space eye position. Read-only — driven by center/yaw/pitch/radius. */
2895
+ readonly position: Vec3;
2896
+ /** Derived camera up vector. Read-only. */
2897
+ readonly upVector: Vec3;
2898
+ fov: number;
2899
+ nearPlane: number;
2900
+ farPlane: number;
2901
+ viewport?: NormalizedViewport;
2902
+ children: SceneNode[];
2903
+ parent: IWorldMatrixProvider | null;
2904
+ readonly worldMatrix: Mat4;
2905
+ readonly worldMatrixVersion: number;
2906
+
2907
+ /** Options for {@link createGeospatialCamera}. */
2908
+ export declare interface GeospatialCameraOptions {
2909
+ /** Radius of the planet being orbited. */
2910
+ planetRadius: number;
2911
+ }
2912
+
2913
+ /** Options for {@link attachGeospatialControls}. */
2914
+ export declare interface GeospatialControlOptions {
2915
+ /** When true, zooming moves toward the point under the cursor; otherwise along the look vector. Default true. */
2916
+ zoomToCursor?: boolean;
2917
+ /** Enable simple sphere collision so the camera cannot dip below the surface. Default false. */
2918
+ checkCollisions?: boolean;
2919
+ }
2920
+
2921
+ /** Options for {@link flyGeospatialCameraToAsync}. Omitted target fields keep their current value. */
2922
+ export declare interface GeospatialFlyOptions {
2923
+ /** Target yaw (radians). Shortest angular path is taken. */
2924
+ yaw?: number;
2925
+ /** Target pitch (radians). */
2926
+ pitch?: number;
2927
+ /** Target radius. */
2928
+ radius?: number;
2929
+ /** Target centre (ECEF). Animated along a great-circle (slerp). */
2930
+ center?: Vec3;
2931
+ /** Flight duration in ms. Default 1000. */
2932
+ durationMs?: number;
2933
+ /** Parabolic "hop" height scale for the centre animation (0 = none). */
2934
+ centerHopScale?: number;
2935
+ }
2936
+
2937
+ /** Pitch/yaw/radius bounds for a {@link GeospatialCamera}.
2938
+ *
2939
+ * Pure state, mirroring Babylon.js `GeospatialLimits`. Behaviour
2940
+ * ({@link getEffectivePitchMax}, {@link clampZoomDistance}) lives in
2941
+ * standalone functions so unused limit logic is tree-shaken.
2942
+ *
2943
+ * All angles are in radians. Pitch is measured from "looking straight down at
2944
+ * the planet centre" (0) to "looking at the horizon" (π/2). */
2945
+ export declare interface GeospatialLimits {
2946
+ /** Radius of the planet — used for altitude/radius conversions. */
2947
+ planetRadius: number;
2948
+ /** Minimum camera distance from its centre point (closest zoom). Default 10. */
2949
+ radiusMin: number;
2950
+ /** Maximum camera distance from its centre point (farthest zoom). Default `planetRadius * 4`. */
2951
+ radiusMax: number;
2952
+ /** Minimum pitch angle (≈0 = looking straight down at the planet). */
2953
+ pitchMin: number;
2954
+ /** Maximum pitch angle (π/2 = looking at the horizon). */
2955
+ pitchMax: number;
2956
+ /**
2957
+ * Controls how pitch is disabled as the camera zooms out.
2958
+ * `x` = radius scale at which full pitch is allowed (e.g. 2 ⇒ 2·planetRadius),
2959
+ * `y` = radius scale at which pitch is fully disabled (forced to `pitchMin`).
2960
+ * `null` disables this feature (full pitch at every radius).
2961
+ */
2962
+ pitchDisabledRadiusScale: {
2963
+ x: number;
2964
+ y: number;
2965
+ } | null;
2966
+ /** Minimum yaw angle (rotation about the geocentric up axis). Default -Infinity. */
2967
+ yawMin: number;
2968
+ /** Maximum yaw angle. Default +Infinity. */
2969
+ yawMax: number;
2970
+ }
2971
+
2972
+ /** A delta to apply via {@link setGeospatialOrientation}; omitted fields keep their current value. */
2973
+ export declare interface GeospatialOrientation {
2974
+ /** Yaw in radians (0 = north, π/2 = east). */
2975
+ yaw?: number;
2976
+ /** Pitch in radians (0 = looking straight down at the planet centre, π/2 = horizon). */
2977
+ pitch?: number;
2978
+ /** Distance from the camera to its centre point. */
2979
+ radius?: number;
2980
+ /** Anchor point on the globe (ECEF) that the camera orbits. */
2981
+ center?: Vec3;
2982
+ }
2983
+
1992
2984
  /** Get the current world position of an agent. */
1993
2985
  export declare function getAgentPosition(crowd: NavCrowd, index: number): Vec3;
1994
2986
 
@@ -2014,6 +3006,14 @@ export declare function getClosestPoint(plugin: NavigationPlugin, position: Vec3
2014
3006
  /** Returns the render-target aspect ratio adjusted for the camera's normalized viewport, or the raw ratio if none. */
2015
3007
  export declare function getEffectiveAspectRatio(camera: Camera | null | undefined, targetWidth: number, targetHeight: number): number;
2016
3008
 
3009
+ /**
3010
+ * Computes the effective maximum pitch for a given camera radius. When
3011
+ * `pitchDisabledRadiusScale` is set, pitch is interpolated from `pitchMax` down
3012
+ * to `pitchMin` as the camera zooms out from `x·planetRadius` to `y·planetRadius`
3013
+ * (so a fully zoomed-out camera looks straight down).
3014
+ */
3015
+ export declare function getEffectivePitchMax(limits: GeospatialLimits, currentRadius: number): number;
3016
+
2017
3017
  /** Read the current floating-origin offset from a scene as a `Vec3`. The
2018
3018
  * offset is the active camera's world position. Returns the zero vector
2019
3019
  * when no camera is set (typical headless/precompute case). For non-LWR
@@ -2026,12 +3026,21 @@ export declare function getFrameGraph(scene: SceneContext): FrameGraph;
2026
3026
  /** Get the current seed used by Recast's randomized queries. */
2027
3027
  export declare function getNavigationRandomSeed(plugin: NavigationPlugin): number;
2028
3028
 
3029
+ /** Get or create a deduplicated sampler. Same config → same GPUSampler. */
3030
+ export declare function getOrCreateSampler(engine: EngineContext, desc?: GPUSamplerDescriptor): GPUSampler;
3031
+
2029
3032
  /**
2030
- * Returns the world's current gravity vector.
3033
+ * Get a body's current linear velocity (m/s).
3034
+ */
3035
+ export declare function getPhysicsBodyLinearVelocity(world: PhysicsWorld, body: PhysicsBody): Vec3;
3036
+
3037
+ /**
3038
+ * Returns the world's current gravity vector, or a specific region's when `worldPosition` is given.
2031
3039
  * @param world - The physics world.
3040
+ * @param worldPosition - Optional world position selecting the region to read; omit for the world-wide gravity.
2032
3041
  * @returns Gravity acceleration in m/s².
2033
3042
  */
2034
- export declare function getPhysicsGravity(world: PhysicsWorld): Vec3;
3043
+ export declare function getPhysicsGravity(world: PhysicsWorld, worldPosition?: Vec3): Vec3;
2035
3044
 
2036
3045
  /**
2037
3046
  * Returns the world's fixed simulation timestep in seconds.
@@ -2098,6 +3107,21 @@ export declare function getViewMatrix(camera: Camera): Mat4;
2098
3107
  /** Compute the view-projection matrix for a camera. Cached per worldMatrixVersion + aspect. */
2099
3108
  export declare function getViewProjectionMatrix(camera: Camera, aspectRatio: number): Mat4;
2100
3109
 
3110
+ declare interface GizmoMaterialSet {
3111
+ colored: StandardMaterialProps;
3112
+ hover: StandardMaterialProps;
3113
+ disabled: StandardMaterialProps;
3114
+ }
3115
+
3116
+ /** Tiny single-event observable used by gizmos/pointer-drag (no dependency on
3117
+ * BJS's Observable, no module-level allocations). */
3118
+ declare class GizmoObservable<T> {
3119
+ private _subs;
3120
+ add(cb: (arg: T) => void): () => void;
3121
+ notify(arg: T): void;
3122
+ clear(): void;
3123
+ }
3124
+
2101
3125
  /** Everything the animation system needs, parsed from a glTF file. */
2102
3126
  export declare interface GltfAnimationData {
2103
3127
  readonly clips: readonly AnimationClip[];
@@ -2115,6 +3139,61 @@ export declare interface GltfAnimationData {
2115
3139
  readonly excludedNodeIndices: ReadonlySet<number>;
2116
3140
  }
2117
3141
 
3142
+ export declare type GlyphBounds = {
3143
+ readonly xMin: number;
3144
+ readonly yMin: number;
3145
+ readonly xMax: number;
3146
+ readonly yMax: number;
3147
+ };
3148
+
3149
+ export declare type GlyphCurves = {
3150
+ readonly glyphId: number;
3151
+ readonly curves: readonly QuadCurve[];
3152
+ readonly bounds: GlyphBounds;
3153
+
3154
+ export declare type GlyphRun = {
3155
+ /** Which curve set this run's glyph ids index into. */
3156
+ readonly curveSet: CurveSetId;
3157
+ readonly glyphs: readonly PlacedGlyph[];
3158
+ /** Font-units → pixels scale used by the layout. */
3159
+ readonly pixelsPerFontUnit: number;
3160
+ /** Optional default color for every glyph in this run, as linear RGBA in [0,1]. A glyph's
3161
+ * own `PlacedGlyph.color` takes precedence over this. When omitted, glyphs default to
3162
+ * opaque white. The rendered alpha is additionally scaled by the whole-block opacity. */
3163
+ readonly defaultColor?: readonly [number, number, number, number];
3164
+ };
3165
+
3166
+ /** Opaque bundle of glyph outlines (organized by curve-set) and the GPU atlases packed
3167
+ * from them. Holds an arbitrary number of curve-sets — each curve-set gets its own atlas.
3168
+ * Shared by reference across any number of `TextData`s that need the same glyph catalog. */
3169
+ export declare interface GlyphStorage {
3170
+ readonly [glyphStorageBrand]: true;
3171
+
3172
+ /** Glyph storage: per-curve-set CPU outline catalog plus the GPU atlas packed from it.
3173
+ *
3174
+ * Layered:
3175
+ * - `GlyphStorage` is the opaque public handle. Holds one or more curve-sets keyed by
3176
+ * `CurveSetId` (typically a font family name). Each curve-set owns its glyph
3177
+ * outlines plus the `SharedAtlas` packed from them.
3178
+ * - `SharedAtlas` is the CPU staging: two `rgba32float`-shaped `Float32Array`s holding
3179
+ * quadratic curve control points and per-band curve-index lists, both append-only.
3180
+ * - Atlas packing (`packAppendGlyph`) and spatial-band partitioning (`buildGlyphBands`)
3181
+ * live here as internal helpers — they implement the storage's invariants and are
3182
+ * not callable from outside the module.
3183
+ * - GPU creation/upload (`SharedAtlasGpu`, `ensureSharedAtlasGpu`) lives in
3184
+ * `_gpu/text-textures.ts`; the shared types are exported from here. GPU teardown
3185
+ * is performed inline in `disposeGlyphStorage` to avoid a circular import edge.
3186
+ *
3187
+ * Lifetime is caller-owned (matches `Texture2D` semantics):
3188
+ * - `createGlyphStorage(initial?)` allocates a fresh storage, optionally seeded.
3189
+ * - `updateGlyphStorage(storage, curveSetId, curves)` adds glyphs (creating the
3190
+ * curve-set on demand). Glyph ids already present are skipped.
3191
+ * - `disposeGlyphStorage(storage)` releases every atlas. The caller must ensure no
3192
+ * `TextData` is still drawing from it — using a disposed storage is undefined
3193
+ * behavior. Idempotent.
3194
+ */
3195
+ declare const glyphStorageBrand: unique symbol;
3196
+
2118
3197
  /** Seek to a specific frame, apply the pose, and pause. */
2119
3198
  export declare function goToFrame(group: AnimationGroup, frame: number, engine?: EngineContext): void;
2120
3199
 
@@ -2269,6 +3348,13 @@ export declare function initializeCsg2Async(): Promise<void>;
2269
3348
 
2270
3349
  declare type InterpMode = 0 | 1 | 2;
2271
3350
 
3351
+ /** Force every registered scene's cached render + shadow bundles to RE-RECORD on the next frame, by bumping
3352
+ * each rendering context's `_renderableVersion` (the same signal a mesh add/remove or `resizeMeshGeometry`
3353
+ * emits). Use after an out-of-band GPU buffer REALLOCATION that the cached bundles can't otherwise notice —
3354
+ * e.g. growing a thin-instanced mesh's matrix buffer past its capacity (the bundle captured the old buffer
3355
+ * handle and would bind a freed buffer). A no-op-cheap version bump; the actual re-record happens lazily. */
3356
+ export declare function invalidateRenderBundles(engine: EngineContext): void;
3357
+
2272
3358
  /** Any object that can be attached to a parent in the scene hierarchy.
2273
3359
  * When parent is null, position/rotation/scaling are in world space. */
2274
3360
  export declare interface IParentable {
@@ -2302,6 +3388,26 @@ export declare function isBillboardSpriteHandleAlive(handle: BillboardSpriteHand
2302
3388
  /** Returns whether the manifold-3d runtime has finished loading and CSG2 is usable. */
2303
3389
  export declare function isCsg2Ready(): boolean;
2304
3390
 
3391
+ /** Returns true when the gizmo dispatcher for `canvas` has an ACTIVE drag in
3392
+ * progress (a collider was pressed and is being dragged). Unlike
3393
+ * {@link isGizmoInteracting} this ignores mere hover, so camera controls can
3394
+ * abort an optimistically-started orbit once a gizmo drag (recognised a frame
3395
+ * after pointer-down, since picking is async) reclaims the gesture — without
3396
+ * aborting a legitimate orbit when the cursor merely passes over a gizmo. */
3397
+ export declare function isGizmoDragging(canvas: HTMLCanvasElement): boolean;
3398
+
3399
+ /** Returns true when the gizmo dispatcher for `canvas` currently has a pointer
3400
+ * hovering one of its colliders or an active drag in progress. Camera
3401
+ * controls consult this on pointer-down so orbiting doesn't start when the
3402
+ * press lands on (or drags) a gizmo. */
3403
+ export declare function isGizmoInteracting(canvas: HTMLCanvasElement): boolean;
3404
+
3405
+ /** Returns true while the gizmo dispatcher for `canvas` has a pointer-down GPU
3406
+ * pick still in flight. Camera controls consult this to DEFER (not yet apply)
3407
+ * an orbit until the pick resolves, so a press that lands on a gizmo never
3408
+ * produces a stray orbit even if the async pick is slow. */
3409
+ export declare function isGizmoPickPending(canvas: HTMLCanvasElement): boolean;
3410
+
2305
3411
  /**
2306
3412
  * Returns `true` if the sprite referenced by `handle` is still present in its layer.
2307
3413
  * @param handle - Handle to test.
@@ -2333,6 +3439,19 @@ export declare interface LightBase extends IWorldMatrixProvider, IParentable {
2333
3439
  readonly worldMatrix: Mat4;
2334
3440
  readonly worldMatrixVersion: number;
2335
3441
 
3442
+ export declare interface LightGizmo {
3443
+ /** Root node — follows the attached light's position (when it has one)
3444
+ * and orients along its direction (when it has one). */
3445
+ readonly root: SceneNode;
3446
+ readonly material: StandardMaterialProps;
3447
+ /** Currently attached light — set via `attachLightGizmoToLight`. */
3448
+ attachedLight: LightBase | null;
3449
+
3450
+ export declare interface LightGizmoOptions {
3451
+ /** RGB color for the light gizmo body material. Defaults to grey. */
3452
+ color?: [number, number, number];
3453
+ }
3454
+
2336
3455
  /** Options for `createLinearDepthMaterial()`. */
2337
3456
  export declare interface LinearDepthMaterialOptions {
2338
3457
  /** Camera near plane (defaults to 0.03 to match the source playground). */
@@ -2343,6 +3462,9 @@ export declare interface LinearDepthMaterialOptions {
2343
3462
  name?: string;
2344
3463
  }
2345
3464
 
3465
+ /** Convert linear [0,1] to sRGB [0,255] using the IEC 61966-2-1 transfer curve. */
3466
+ export declare function linearToSrgbByte(v: number): number;
3467
+
2346
3468
  /** Options for `loadSpriteAtlas`. PR 1 supports the `gridSize` path only. */
2347
3469
  export declare interface LoadAtlasOptions {
2348
3470
  /** Grid cell size `[w, h]` in pixels. Required in PR 1. */
@@ -2417,6 +3539,9 @@ export declare function loadEnvironment(scene: SceneContext, url: string, option
2417
3539
  brdfUrl: string;
2418
3540
  }): Promise<EnvironmentTextures>;
2419
3541
 
3542
+ /** Load a TTF or OTF font from a URL. */
3543
+ export declare function loadFont(url: string): Promise<Font>;
3544
+
2420
3545
  /**
2421
3546
  * Load a .glb or .gltf file, parse it, and upload mesh + material data to GPU.
2422
3547
  * Supports both binary GLB and separate .gltf + .bin + image files.
@@ -2455,6 +3580,14 @@ export declare function loadHdrEnvironment(scene: SceneContext, url: string, opt
2455
3580
  */
2456
3581
  export declare function loadKtxTexture2D(engine: EngineContext, baseUrl: string, suffixes: string[], opts?: Texture2DOptions): Promise<Texture2D>;
2457
3582
 
3583
+ /**
3584
+ * Resolve a node-block emitter, including the geometry-renderer terminal
3585
+ * (`GeometryTextureOutputBlock`). Pass as `blockLoader` to
3586
+ * `parseNodeMaterialFromSnippet` for node-material geometry-renderer scenes so
3587
+ * ordinary node scenes don't bundle the geometry block.
3588
+ */
3589
+ export declare function loadNodeBlockEmitterWithGeometry(className: string): Promise<BlockEmitter>;
3590
+
2458
3591
  /** Load a skybox cube texture and register it on the scene.
2459
3592
  * The auto-builder will create the pipeline and render it.
2460
3593
  *
@@ -2600,7 +3733,12 @@ export declare interface MaterialVariantData {
2600
3733
  * The view is also a Material: it inherits material state from {@link source}
2601
3734
  * through the prototype chain and owns only render-feature bits. Keeping views
2602
3735
  * material-compatible lets ordinary render paths read properties normally, so
2603
- * scenes that never create views do not retain view-specific unwrap branches. */
3736
+ * scenes that never create views do not retain view-specific unwrap branches.
3737
+ *
3738
+ * Specialized views (e.g. the Standard geometry MRT view) override
3739
+ * {@link Material._buildGroup} with a view-specific builder whose
3740
+ * `_rebuildSingle` builds the right kind of Renderable — no per-family
3741
+ * branching is required in the core render-task. */
2604
3742
  export declare interface MaterialView extends Material {
2605
3743
  readonly source: Material;
2606
3744
 
@@ -2625,6 +3763,9 @@ export declare interface Mesh extends SceneNode {
2625
3763
  boundMax?: [number, number, number];
2626
3764
  /** Skeleton GPU data (skeletal animation). Type-only — no module dependency. */
2627
3765
  skeleton?: SkeletonData | null;
3766
+ /** Baked vertex-animation (VAT) GPU data — replaces live skinning so the mesh thin-instances.
3767
+ * Mutually exclusive with live `skeleton` skinning. Type-only — no module dependency. */
3768
+ vat?: VatData | null;
2628
3769
  /** Morph target GPU data. Type-only — no module dependency. */
2629
3770
  morphTargets?: MorphTargetData | null;
2630
3771
  /** User-controlled render order. Lower = drawn first within phase.
@@ -2637,7 +3778,10 @@ export declare interface Mesh extends SceneNode {
2637
3778
  * (`needAlphaBlending`) are deferred. No effect on tasks without transmission. */
2638
3779
  renderOnTop?: boolean;
2639
3780
  /** Thin instance data (CPU-side). GPU buffer managed by render system. */
2640
- thinInstances?: ThinInstanceData | null;
3781
+ thinInstances?: ThinInstanceData | null;
3782
+ /** When `false`, the GPU picker skips this mesh. Defaults to `true`
3783
+ * (undefined behaves as pickable). Mirrors BJS `AbstractMesh.isPickable`. */
3784
+ pickable?: boolean;
2641
3785
 
2642
3786
  /** Opaque GPU geometry handle (user never touches these). */
2643
3787
  export declare interface MeshGPU {
@@ -2720,6 +3864,12 @@ export declare interface NavMeshParameters {
2720
3864
  keepIntermediates?: boolean;
2721
3865
  }
2722
3866
 
3867
+ /** A single mesh source for navmesh construction. */
3868
+ export declare interface NavMeshSource {
3869
+ positions: ArrayLike<number>;
3870
+ indices: ArrayLike<number>;
3871
+ }
3872
+
2723
3873
  /** Parsed block in the graph. */
2724
3874
  declare interface NodeBlock {
2725
3875
  readonly id: number;
@@ -2810,8 +3960,7 @@ declare interface NodeBuildState {
2810
3960
  hasSkeleton: boolean;
2811
3961
  /** When false (default), InstancesBlock passes through the uniform world
2812
3962
  * matrix. Set to true when thin-instance attributes are bound. */
2813
- hasInstances: boolean;
2814
- }
3963
+ hasInstances: boolean;
2815
3964
 
2816
3965
  /** A single connection point on a block — input only.
2817
3966
  * Output connection types are resolved by the emitter at graph-walk time. */
@@ -2927,6 +4076,9 @@ export declare interface NormalizedViewport {
2927
4076
  height: number;
2928
4077
  }
2929
4078
 
4079
+ /** Wrap an angle to [-π, π), matching Babylon.js `Scalar.NormalizeRadians`. */
4080
+ export declare function normalizeRadians(angle: number): number;
4081
+
2930
4082
  /**
2931
4083
  * Normalizes the vector `(x, y, z)` to unit length.
2932
4084
  * @param x - X component.
@@ -3033,6 +4185,10 @@ export declare function onCsmReceiverUpdate(sg: ShadowGenerator, cb: (data: Floa
3033
4185
  * user-owned GPU resources (e.g. a `SpriteRenderer`) to the scene's lifetime. */
3034
4186
  export declare function onSceneDispose(scene: SceneContext, cb: () => void): void;
3035
4187
 
4188
+ /** Convert a packed 0xRRGGBB sRGB color to a linear-RGBA tuple suitable for
4189
+ * text-renderer `defaultColor` / `PlacedGlyph.color`. */
4190
+ export declare function packedSrgbToLinearRgba(packed: number, alpha?: number): readonly [number, number, number, number];
4191
+
3036
4192
  /** Parse a Babylon NME graph (by snippet ID or inline JSON), emit WGSL, compile
3037
4193
  * the GPU pipeline, and return a ready-to-render `NodeMaterial`.
3038
4194
  * @param engine - Engine context.
@@ -3230,8 +4386,7 @@ export declare interface PhysicsAggregateOptions {
3230
4386
 
3231
4387
  /** Opaque handle to a Havok rigid body, bound to a scene node and a motion type. */
3232
4388
  export declare interface PhysicsBody {
3233
4389
  readonly node: SceneNode;
3234
- readonly motionType: PhysicsMotionType;
3235
- }
4390
+ readonly motionType: PhysicsMotionType;
3236
4391
 
3237
4392
  /** How a body moves: `STATIC` (immovable), `ANIMATED` (driven by the node transform), or `DYNAMIC` (simulated). */
3238
4393
  export declare const enum PhysicsMotionType {
@@ -3275,7 +4430,7 @@ export declare const enum PhysicsShapeType {
3275
4430
  export declare interface PhysicsWorld {
3276
4431
 
3277
4432
  /** Pick the mesh at CSS-space canvas coordinates, matching Babylon.js Scene.pick. Returns a PickingInfo. */
3278
- export declare function pickAsync(picker: GpuPicker, x: number, y: number): Promise<PickingInfo>;
4433
+ export declare function pickAsync(picker: GpuPicker, x: number, y: number, options?: PickOptions): Promise<PickingInfo>;
3279
4434
 
3280
4435
  /** Result of a GPU pick operation. */
3281
4436
  export declare interface PickingInfo {
@@ -3298,6 +4453,16 @@ export declare interface PickingInfo {
3298
4453
  ray: Ray | null;
3299
4454
  }
3300
4455
 
4456
+ /** Options for {@link pickAsync}. */
4457
+ export declare interface PickOptions {
4458
+ /** Restrict the pick to a subset of the scene's meshes — return `true` for a mesh that may be picked,
4459
+ * `false` to ignore it entirely (it neither occludes nor is returned). Lets a caller provide its
4460
+ * "list of pickables" so decorative meshes (grass, foliage, particles, …) can't swallow a pick of a
4461
+ * structure behind/around them. When omitted, every mesh is pickable (previous behaviour). Applied
4462
+ * identically to the id-assignment and id-resolve passes so ids stay consistent. */
4463
+ filter?: (mesh: Mesh) => boolean;
4464
+ }
4465
+
3301
4466
  /** Sampler and format overrides for `createTexture2DFromPixels()`. */
3302
4467
  export declare interface PixelsTexture2DOptions {
3303
4468
  /** Address mode U. Default 'clamp-to-edge'. */
@@ -3321,6 +4486,36 @@ export declare interface PixelViewport {
3321
4486
  height: number;
3322
4487
  }
3323
4488
 
4489
+ export declare type PlacedGlyph = {
4490
+ readonly glyphId: number;
4491
+ /** Pixel position of glyph baseline origin. */
4492
+ readonly x: number;
4493
+ readonly y: number;
4494
+ /** Optional per-glyph color as linear RGBA in [0,1]. When present this overrides the
4495
+ * run's `defaultColor` for this glyph. When omitted, the glyph falls back to the run's
4496
+ * `defaultColor`, and if that is also omitted, to opaque white. The rendered alpha is
4497
+ * additionally scaled by the whole-block opacity (e.g. `TextRenderable.opacity`). */
4498
+ readonly color?: readonly [number, number, number, number];
4499
+ };
4500
+
4501
+ export declare interface PlaneDragGizmo {
4502
+ readonly root: SceneNode;
4503
+ readonly drag: PointerDrag;
4504
+ readonly onPositionChanged: GizmoObservable<Vec3>;
4505
+ attachedNode: SceneNode | null;
4506
+ /** When true, the plane normal rotates with the attached node each frame
4507
+ * (local-coord mode). When false, the normal stays world-aligned. */
4508
+ useLocalCoordinates: boolean;
4509
+ readonly materials: GizmoMaterialSet;
4510
+
4511
+ export declare interface PlaneDragGizmoOptions {
4512
+ /** World-space drag plane normal (unit vector). */
4513
+ dragPlaneNormal: Vec3;
4514
+ color?: [number, number, number];
4515
+ hoverColor?: [number, number, number];
4516
+ disableColor?: [number, number, number];
4517
+ }
4518
+
3324
4519
  /** Options for `createPlaneData`. Subset of Babylon's CreatePlane. */
3325
4520
  export declare interface PlaneOptions {
3326
4521
  size?: number;
@@ -3328,6 +4523,33 @@ export declare interface PlaneOptions {
3328
4523
  height?: number;
3329
4524
  }
3330
4525
 
4526
+ export declare interface PlaneRotationGizmo {
4527
+ readonly root: SceneNode;
4528
+ readonly drag: PointerDrag;
4529
+ readonly onRotationChanged: GizmoObservable<[number, number, number, number]>;
4530
+ attachedNode: SceneNode | null;
4531
+ /** Local-coord mode: plane normal rotates with the attached node. */
4532
+ useLocalCoordinates: boolean;
4533
+ readonly materials: GizmoMaterialSet;
4534
+ /** ShaderMaterial driving the rotation-sector camembert visual. Exposed so
4535
+ * callers can change the colour at runtime. */
4536
+ readonly rotationDisplayMaterial: ShaderMaterial;
4537
+
4538
+ export declare interface PlaneRotationGizmoOptions {
4539
+ /** World-space rotation plane normal (unit vector). */
4540
+ planeNormal: Vec3;
4541
+ color?: [number, number, number];
4542
+ hoverColor?: [number, number, number];
4543
+ disableColor?: [number, number, number];
4544
+ /** Torus tessellation. Default 32 (matches BJS). */
4545
+ tessellation?: number;
4546
+ /** Tube thickness multiplier. Default 1. */
4547
+ thickness?: number;
4548
+ /** Colour of the rotation "camembert" sector visual shown while dragging.
4549
+ * Defaults to the hover colour. */
4550
+ rotationColor?: [number, number, number];
4551
+ }
4552
+
3331
4553
  /** Start playing an animation group. */
3332
4554
  export declare function playAnimation(group: AnimationGroup): void;
3333
4555
 
@@ -3415,6 +4637,70 @@ export declare interface PluginUboField {
3415
4637
  readonly type: string;
3416
4638
  }
3417
4639
 
4640
+ export declare interface PointerDrag {
4641
+ readonly options: Readonly<PointerDragOptions>;
4642
+ enabled: boolean;
3418
4643
  /** Fired once when a pointer-down lands on one of `_colliders`. */
4644
+ onDragStart: GizmoObservable<PointerDragStartEvent>;
4645
+ /** Fired on every pointer-move while a drag is active. */
4646
+ onDrag: GizmoObservable<PointerDragMoveEvent>;
4647
+ /** Fired once when the pointer is released. */
4648
+ onDragEnd: GizmoObservable<PointerDragEndEvent>;
4649
+ /** Fired when the pointer hovers over one of `_colliders` (no button pressed).
4650
+ * Used by gizmos to swap to a hover-coloured material before any drag.
4651
+ * Always fires AFTER a previous `onHoverEnd` for a different drag, so the
4652
+ * receiver doesn't need to track which collider is currently hovered. */
4653
+ onHoverStart: GizmoObservable<void>;
4654
+ /** Fired when the pointer leaves a previously-hovered collider. */
4655
+ onHoverEnd: GizmoObservable<void>;
4656
+ /** True while a drag is in progress. */
4657
+ dragging: boolean;
4658
+ /** True while the pointer is hovering one of `_colliders` (no drag). */
4659
+ hovering: boolean;
4660
+ }
4661
+
4662
+ export declare interface PointerDragEndEvent {
4663
+ pointerEvent: PointerEvent | null;
4664
+ }
4665
+
4666
+ export declare interface PointerDragMoveEvent {
4667
+ /** World-space delta from the previous drag-plane point. For axis-drag this
4668
+ * is already projected onto the drag axis (parallel to axis). */
4669
+ delta: Vec3;
4670
+ /** Current world-space point on the drag plane (post-projection). */
4671
+ dragPlanePoint: Vec3;
4672
+ /** Signed scalar distance projected onto the drag axis since drag start
4673
+ * (axis-drag mode); for plane mode this is `delta.length()`. */
4674
+ dragDistance: number;
4675
+ }
4676
+
4677
+ export declare interface PointerDragOptions {
4678
+ /** Drag along a single world-space axis (unit vector). Mutually exclusive
4679
+ * with `dragPlaneNormal`. */
4680
+ dragAxis?: Vec3;
4681
+ /** Drag inside a plane defined by this world-space normal. Mutually
4682
+ * exclusive with `dragAxis`. */
4683
+ dragPlaneNormal?: Vec3;
4684
+ /** When false, the dispatcher fires events but doesn't move the picked
4685
+ * mesh. Gizmos always set this to false and apply transforms to their
4686
+ * attached node themselves. */
4687
+ moveAttached?: boolean;
4688
+ /** Optional override for the drag-plane anchor point (plane mode only).
4689
+ * When it returns a point, the camera-facing drag plane passes through that
4690
+ * point instead of the picked surface point, so the screen→world scale is
4691
+ * taken at that depth. The BoundingBoxGizmo body drag anchors at the
4692
+ * bounding-box CENTRE (matching BJS, whose body `_dragMesh` sits at the box
4693
+ * centroid) so the translation scale doesn't depend on where the press
4694
+ * landed on the (inset, camera-facing) body surface. */
4695
+ getPlanePoint?: () => Vec3 | null;
4696
+ }
4697
+
4698
+ export declare interface PointerDragStartEvent {
4699
+ /** World-space point where the ray intersected the drag plane on drag start. */
4700
+ dragPlanePoint: Vec3;
4701
+ /** Browser pointer event that triggered drag start. */
4702
+ pointerEvent: PointerEvent;
4703
+ }
4704
+
3419
4705
  export declare interface PointLight extends LightBase {
3420
4706
  readonly lightType: "point";
3421
4707
  position: ObservableVec3;
@@ -3440,6 +4726,25 @@ export declare interface PolyhedronOptions {
3440
4726
  flat?: boolean;
3441
4727
  }
3442
4728
 
4729
+ export declare interface PositionGizmo {
4730
+ readonly xGizmo: AxisDragGizmo;
4731
+ readonly yGizmo: AxisDragGizmo;
4732
+ readonly zGizmo: AxisDragGizmo;
4733
+ readonly xPlaneGizmo: PlaneDragGizmo | null;
4734
+ readonly yPlaneGizmo: PlaneDragGizmo | null;
4735
+ readonly zPlaneGizmo: PlaneDragGizmo | null;
4736
+ attachedNode: SceneNode | null;
4737
+ }
4738
+
4739
+ export declare interface PositionGizmoOptions {
4740
+ /** When true, planar drag gizmos (XY/XZ/YZ) are created in addition to the
4741
+ * 3 axis arrows. Default false — matches BJS where `planarGizmoEnabled`
4742
+ * defaults to false and must be opted into. */
4743
+ planarEnabled?: boolean;
4744
+ /** Tube thickness multiplier for the axis arrows. */
4745
+ thickness?: number;
4746
+ }
4747
+
3443
4748
  /** Output blend mode: `0` opaque, `1` additive, `2` premultiplied, `7` non-premultiplied alpha. */
3444
4749
  export declare type PostProcessAlphaMode = 0 | 1 | 2 | 7;
3445
4750
 
@@ -3521,6 +4826,15 @@ export declare interface PropertyAnimationTrackOptions {
3521
4826
  readonly quaternion?: boolean;
3522
4827
  }
3523
4828
 
4829
+ export declare type QuadCurve = {
4830
+ readonly p0x: number;
4831
+ readonly p0y: number;
4832
+ readonly p1x: number;
4833
+ readonly p1y: number;
4834
+ readonly p2x: number;
4835
+ readonly p2y: number;
4836
+ };
4837
+
3524
4838
  /** Quaternion rotation */
3525
4839
  declare interface Quat {
3526
4840
  x: number;
@@ -3580,27 +4894,59 @@ export declare interface RefractionProps {
3580
4894
  dispersion?: number;
3581
4895
  }
3582
4896
 
3583
- /** Register the effect renderer with its engine. Idempotent — a second call is a no-op. */
4897
+ /** Register the effect renderer with its surface. Idempotent — a second call is a no-op. */
3584
4898
  export declare function registerEffectRenderer(er: EffectRenderer): void;
3585
4899
 
3586
- /** Build and register the standalone frame-graph context with its engine. */
4900
+ /** Build and register the standalone frame-graph context with its surface. */
3587
4901
  export declare function registerFrameGraphContext(ctx: FrameGraphContext): void;
3588
4902
 
4903
+ /** Register the drag's colliders + handlers with the per-canvas dispatcher for
4904
+ * this utility layer. Returns a function that unregisters the drag. When the
4905
+ * last drag for a canvas is unregistered, the dispatcher tears itself down
4906
+ * (canvas listeners are detached, the GPU picker is disposed, the cache entry
4907
+ * is removed) so disposing all gizmos doesn't leak listeners or GPU resources. */
4908
+ export declare function registerPointerDrag(layer: UtilityLayer, canvas: HTMLCanvasElement, drag: PointerDrag): () => void;
4909
+
3589
4910
  /**
3590
4911
  * Register a scene with the engine. Builds deferred work, sorts renderables by order,
3591
- * and adds the scene to the engine's render list in overlay order.
4912
+ * and adds the scene to its bound surface's render list in overlay order. The scene is
4913
+ * always attached to `scene.surface` (which equals the engine itself in the
4914
+ * single-canvas case).
3592
4915
  */
3593
- export declare function registerScene(engine: EngineContext, scene: SceneContext): Promise<void>;
4916
+ export declare function registerScene(scene: SceneContext): Promise<void>;
3594
4917
 
3595
4918
  /**
3596
4919
  * Register a scene with the engine and install the scene-owned shadow frame-graph task.
3597
- * Use only for scenes that generate shadow maps.
4920
+ * Use only for scenes that generate shadow maps. Like {@link registerScene}, the scene
4921
+ * is attached to `scene.surface` (and its owning engine is `scene.surface.engine`).
3598
4922
  */
3599
- export declare function registerSceneWithShadowSupport(engine: EngineContext, scene: SceneContext): Promise<void>;
4923
+ export declare function registerSceneWithShadowSupport(scene: SceneContext): Promise<void>;
3600
4924
 
3601
4925
  /** Push the renderer onto its engine's `_renderingContexts`. Idempotent — a second call is a no-op. */
3602
4926
  export declare function registerSpriteRenderer(sr: SpriteRenderer): void;
3603
4927
 
4928
+ export declare function registerTextRenderer(tr: TextRenderer): void;
4929
+
4930
+ /** Register the utility layer with the engine. Must be called after the main
4931
+ * scene has been registered so the swapchain overlay path is enabled. */
4932
+ export declare function registerUtilityLayer(utility: UtilityLayer): Promise<void>;
4933
+
4934
+ /**
4935
+ * Release a collision shape's native handle, freeing its WASM memory. Only call once no body still
4936
+ * references the shape (e.g. after {@link removePhysicsBody}). Useful when rebuilding a changing set of
4937
+ * static colliders so their shapes don't accumulate.
4938
+ * @param world - The physics world.
4939
+ * @param shape - The shape to release.
4940
+ */
4941
+ export declare function releasePhysicsShape(world: PhysicsWorld, shape: PhysicsShape): void;
4942
+
4943
+ /**
4944
+ * Decrement ref count on a Texture2D.
4945
+ * Calls `tex.texture.destroy()` when count reaches 0.
4946
+ * Returns true if the texture was destroyed.
4947
+ */
4948
+ export declare function releaseTexture(tex: Texture2D): boolean;
4949
+
3604
4950
  /** Detaches `group` from `manager`, removing its animation task so it is no longer ticked. */
3605
4951
  export declare function removeAnimationGroup(manager: AnimationManager, group: AnimationGroup): void;
3606
4952
 
@@ -3631,6 +4977,16 @@ export declare function removeMeshFromTask(task: RenderTask, mesh: object): void
3631
4977
  /** Remove an obstacle previously added by `addBoxObstacle` / `addCylinderObstacle`. */
3632
4978
  export declare function removeObstacle(plugin: NavigationPlugin, obstacle: ObstacleHandle): void;
3633
4979
 
4980
+ /**
4981
+ * Remove a single body from the world and release its native handle (the per-frame step skips it from
4982
+ * now on). After this the body must not be reused. A body that isn't in the world is ignored, so this is
4983
+ * safe to call once per body. Does NOT release the body's collision shape — release that separately with
4984
+ * {@link releasePhysicsShape} if it isn't shared.
4985
+ * @param world - The physics world.
4986
+ * @param body - The body to remove.
4987
+ */
4988
+ export declare function removePhysicsBody(world: PhysicsWorld, body: PhysicsBody): void;
4989
+
3634
4990
  /**
3635
4991
  * Removes the sprite referenced by `handle`. Does nothing if it is already gone.
3636
4992
  * @param handle - Handle of the sprite to remove.
@@ -3657,6 +5013,8 @@ export declare function removeSpriteAnimationManager(manager: AnimationManager,
3657
5013
  /** Remove a layer from the renderer and destroy any GPU resources cached for it. */
3658
5014
  export declare function removeSpriteRendererLayer(sr: SpriteRenderer, layer: Sprite2DLayer): boolean;
3659
5015
 
5016
+ export declare function removeTextRendererLayer(tr: TextRenderer, layer: TextLayer): boolean;
5017
+
3660
5018
  /** Remove instance by index. Swap-removes: last instance fills the gap. */
3661
5019
  export declare function removeThinInstance(mesh: Mesh, index: number): void;
3662
5020
 
@@ -3686,6 +5044,8 @@ export declare interface Renderable {
3686
5044
  */
3687
5045
  export declare type RenderCanvas = HTMLCanvasElement | OffscreenCanvas;
3688
5046
 
5047
+ export declare function renderFrame(engine: EngineContext, delta: number): void;
5048
+
3689
5049
  /**
3690
5050
  * Minimal surface an engine sees for anything it renders. Scenes (and any other
3691
5051
  * future renderable thing) register themselves as a `RenderingContext` and
@@ -3700,7 +5060,8 @@ export declare interface RenderPass extends Pass {
3700
5060
  /** Per-frame mutable sta
3701
5061
  * before iterating its passes. */
3702
5062
  clearColor: GPUColorDict;
3703
5063
  /** True → loadOp `"clear"`, false → `"load"` (overlay mode). */
3704
- clear: boolean;
5064
+ clear: boolean;
5065
+ }
3705
5066
 
3706
5067
  /** Body of a render pass — receives the live render-pass encoder and returns
3707
5068
  * the number of draws issued. */
@@ -3712,22 +5073,22 @@ export declare interface RenderTarget {
3712
5073
  /** Describes a render target — what attachments to create, not the GPU objects
3713
5074
  * themselves. GPU textures are allocated later by `buildRenderTarget`. */
3714
5075
  export declare interface RenderTargetDescriptor {
3715
- label?: string;
3716
- colorFormat?: GPUTextureFormat;
3717
- depthStencilFormat?: GPUTextureFormat;
3718
5076
  sampleCount: number;
3719
- /** 'canvas' means match the canvas pixel size. Otherwise explicit pixels. */
3720
- size: "canvas" | {
5077
+ /** Debug label applied to the allocated GPU color/depth textures. */
5078
+ lbl?: string;
5079
+ /** Color attachment texture format (e.g. `"bgra8unorm"`, `"rgba16float"`). Omit for a depth-only target. */
5080
+ format?: GPUTextureFormat;
5081
+ /** Depth/stencil attachment format (e.g. `"depth24plus-stencil8"`). Omit for a color-only target (e.g. the swapchain). */
5082
+ dFormat?: GPUTextureFormat;
3721
5083
  /** MSAA sample count: `1` = single-sample (no multisampling), `4` = 4x MSAA. */
5084
+ samples: number;
5085
+ /** A `SurfaceContext` to size to that surface's swapchain (re-resolved each
5086
+ * `buildRenderTarget`), or explicit `{ width, height }` in device pixels. Pass a
5087
+ * surface for canvas-sized RTs; the RT then tracks that specific surface in
5088
+ * multi-surface setups. In the common single-canvas case, pass the engine directly
5089
+ * (since `EngineContext extends SurfaceContext`). */
5090
+ size: SurfaceContext | {
3722
5091
  width: number;
3723
5092
  height: number;
3724
5093
  };
3725
- /** If true, the color attachment resolves to the swapchain texture. The RT still
3726
- * owns the MSAA texture (when sampleCount \> 1) and the depth texture; only the
3727
- * final color is the swapchain view, acquired per frame and patched in at execute
3728
- * time. With sampleCount === 1 the RT owns no color texture (the swap view is the
3729
- * color attachment directly). */
3730
- resolveToSwapchain?: boolean;
3731
- /** Override projection Y-flip. Defaults to true for offscreen targets and false for swapchain targets. */
3732
- flipY?: boolean;
3733
5094
  }
3734
5095
 
3735
5096
  /** Signature of a render target's attachment set — enough to key a GPURenderPipeline. */
@@ -3752,10 +5113,32 @@ export declare interface RenderTaskConfig {
3752
5113
  * management is virtualized, callers must provide the concrete target; once
3753
5114
  * virtualized, the task should create/manage its own render target. */
3754
5115
  rt: RenderTarget;
5116
+ /** Optional single-sample resolve target. When `rt` is multisampled
5117
+ * (`sampleCount > 1`), the color attachment resolves into this target's
5118
+ * color texture at end-of-pass — letting an MSAA render feed a post-process
5119
+ * that requires a single-sample source, without an extra resolve pass.
5120
+ * Caller contract (not validated): must be single-sample with a color
5121
+ * format and size matching `rt`; WebGPU errors at pass-encode time if not.
5122
+ * Ignored when `rt` is single-sample. */
5123
+ rst?: RenderTarget;
5124
+ /** Optional separate depth/stencil attachment. The pass binds this target's
5125
+ * depth view instead of `rt`'s own, and uses its `depthStencilFormat` for
5126
+ * pipeline signature matching. The colour `rt` must omit `depthStencilFormat`
5127
+ * (so it allocates no internal depth) and match this target in size + sample
5128
+ * count. Two ownership modes, distinguished by `_eager`:
5129
+ * - `_eager` depth (e.g. a `GeometryRendererTask` output): the task neither
5130
+ * builds nor clears nor disposes it — it loads it (`loadOp: "load"`) and the
5131
+ * caller owns clearing. This is how scenes reuse a pre-rendered depth buffer.
5132
+ * - non-`_eager` depth: the task owns it — builds/rebuilds it in `record()`,
5133
+ * clears it (`loadOp: "clear"`), and disposes it. Used by the default
5134
+ * single-sample scene task, whose colour `rt` is the depth-less
5135
+ * engine `scRT`. */
5136
+ depth?: RenderTarget;
3755
5137
  /** Background clear color. May be mutated frame-to-frame. */
3756
5138
  clrColor?: GPUColorDict;
3757
- /** When true, controls color + depth `loadOp` ("clear"). When false, use "load"
3758
- * so this pass overlays previous content (UI overlays, second scene, etc.). */
5139
+ /** When true, color `loadOp` is "clear"; when false, "load" (overlays previous
5140
+ * color content). Depth is always cleared when rt-owned and always loaded when
5141
+ * supplied via `depth`. */
3759
5142
  clr?: boolean;
3760
5143
  /** Per-pass camera override. Null/undefined uses `scene.camera`. */
3761
5144
  cam?: Camera | null;
@@ -3769,21 +5152,60 @@ export declare interface RenderTaskConfig {
3769
5152
  };
3770
5153
  }
3771
5154
 
5155
+ /** Sampler / format overrides for `createRenderTexture2D()`. */
5156
+ export declare interface RenderTexture2DOptions {
5157
+ /** Address mode U. Default 'clamp-to-edge'. */
5158
+ addressModeU?: GPUAddressMode;
5159
+ /** Address mode V. Default 'clamp-to-edge'. */
5160
+ addressModeV?: GPUAddressMode;
5161
+ /** Min filter. Default 'linear'. */
5162
+ minFilter?: GPUFilterMode;
5163
+ /** Mag filter. Default 'linear'. */
5164
+ magFilter?: GPUFilterMode;
5165
+ /**
5166
+ * Color format. Default `engine.format` so it can be sampled and presented.
5167
+ *
5168
+ * ⚠️ Only the default `engine.format` is compatible with a `SpriteRenderer`
5169
+ * target (`setSpriteRendererTarget`): sprite pipelines are created with
5170
+ * `engine.format`, and a render pass whose color attachment format differs from
5171
+ * the bound pipeline fails WebGPU validation at pass begin. Override this **only**
5172
+ * for offscreen targets you render into by some OTHER means (a custom pass /
5173
+ * `EffectRenderer`), never as a sprite-render target.
5174
+ */
5175
+ format?: GPUTextureFormat;
5176
+ }
5177
+
3772
5178
  /**
3773
5179
  * Reset all variant-participating meshes to their original (default) materials.
3774
5180
  */
3775
5181
  export declare function resetVariant(container: AssetContainer): void;
3776
5182
 
3777
- /** Resize the swapchain backing-store to match the canvas client size. When the size
3778
- * changes, asks every registered rendering context to rebuild its canvas-sized GPU
3779
- * resources via the optional `_resize` hook. If the canvas has not been laid out yet,
3780
- * preserves its explicit backing-store size.
3781
- *
3782
- * Only DOM canvases are auto-sized from layout here. An `OffscreenCanvas` has no layout
3783
- * box, so its size is pushed in externally via {@link setEngineSize} (e.g. from the host
3784
- * thread that owns the visible canvas) and this call is a no-op for it. */
5183
+ /** Resize every surface attached to this engine (including the engine's own primary
5184
+ * surface). For DOM-canvas surfaces, snaps the swapchain backing store to the current
5185
+ * `clientWidth × clientHeight × devicePixelRatio` (capped by each surface's
5186
+ * `maxDevicePixelRatio`). For `OffscreenCanvas` surfaces this is a no-op per surface —
5187
+ * call `setSurfaceSize` on the specific surface instead, since an `OffscreenCanvas`
5188
+ * has no layout. */
3785
5189
  export declare function resizeEngine(engine: EngineContext): void;
3786
5190
 
5191
+ /** Replace a mesh's GPU geometry IN PLACE with new (possibly larger or smaller) buffers, reusing the
5192
+ * same Mesh object so existing references to it (scene entries, shadow-caster lists, materials) stay
5193
+ * valid. Unlike `updateMeshPositions`, this REALLOCATES the GPU buffers, so it's the way to GROW a
5194
+ * dynamically-generated mesh past its original vertex/index capacity (e.g. an ever-larger bridge whose
5195
+ * box budget overflows). The old GPU buffers are destroyed to free device memory. Recomputes bounds. */
5196
+ export declare function resizeMeshGeometry(engine: EngineContext, mesh: Mesh, positions: Float32Array, normals: Float32Array, indices: Uint32Array, uvs?: Float32Array, uvs2?: Float32Array, tangents?: Float32Array, colors?: Float32Array): void;
5197
+
5198
+ /** Resize this surface's swapchain backing store to match the canvas client size. When
5199
+ * the size changes, asks every rendering context registered on this surface to rebuild
5200
+ * its canvas-sized GPU resources via the optional `_resize` hook. If the canvas has
5201
+ * not been laid out yet, preserves its explicit backing-store size.
5202
+ *
5203
+ * Only DOM canvases are auto-sized from layout here. An `OffscreenCanvas` has no
5204
+ * layout box, so its size must be pushed in externally via {@link setSurfaceSize}
5205
+ * (e.g. from the host thread that owns the visible canvas) and this call is a no-op
5206
+ * for it. */
5207
+ export declare function resizeSurface(surface: SurfaceContext): void;
5208
+
3787
5209
  /** Resolve a Babylon-style normalized viewport to integer render-target pixels.
3788
5210
  * Babylon viewport y is normalized from the bottom; WebGPU viewport/scissor y is from the top. */
3789
5211
  export declare function resolveCameraViewport(camera: Camera | null | undefined, targetWidth: number, targetHeight: number): PixelViewport;
@@ -3796,6 +5218,31 @@ export declare interface RibbonOptions {
3796
5218
  offset?: number;
3797
5219
  }
3798
5220
 
5221
+ export declare interface RotationGizmo {
5222
+ readonly xGizmo: PlaneRotationGizmo;
5223
+ readonly yGizmo: PlaneRotationGizmo;
5224
+ readonly zGizmo: PlaneRotationGizmo;
5225
+ attachedNode: SceneNode | null;
5226
+ }
5227
+
5228
+ export declare interface RotationGizmoOptions {
5229
+ tessellation?: number;
5230
+ thickness?: number;
5231
+ }
5232
+
5233
+ export declare interface ScaleGizmo {
5234
+ readonly xGizmo: AxisScaleGizmo;
5235
+ readonly yGizmo: AxisScaleGizmo;
5236
+ readonly zGizmo: AxisScaleGizmo;
5237
+ /** Central uniform-scale gizmo (single arrow with uniformScaling = true). */
5238
+ readonly uniformScaleGizmo: AxisScaleGizmo;
5239
+ attachedNode: SceneNode | null;
5240
+ }
5241
+
5242
+ export declare interface ScaleGizmoOptions {
5243
+ thickness?: number;
5244
+ }
5245
+
3799
5246
  /** Scattering sub-feature. Presence enables screen-space subsurface scattering.
3800
5247
  * NOTE: PrePass/SSS pipeline is not yet implemented — this type is reserved. */
3801
5248
  declare interface ScatteringProps {
@@ -3816,7 +5263,12 @@ export declare interface SceneColorGrab {
3816
5263
 
3817
5264
  /** Top-level scene context — pure state, no attached methods. */
3818
5265
  export declare interface SceneContext extends RenderingContext_2 {
3819
- readonly engine: EngineContext;
5266
+ /** Surface this scene renders into. Set at scene-creation time and immutable
5267
+ * afterwards — the default render task is sized and MSAA-matched to this surface,
5268
+ * and `registerScene` attaches the scene to it. For the engine's primary surface
5269
+ * (the common single-canvas case) this is the engine itself. The owning engine is
5270
+ * reachable via `scene.surface.engine`. */
5271
+ readonly surface: SurfaceContext;
3820
5272
  clearColor: GPUColorDict;
3821
5273
  camera: Camera | null;
3822
5274
  lights: LightBase[];
@@ -3867,6 +5319,29 @@ export declare interface SceneUniformUpdater {
3867
5319
  update(engine: EngineContext): void;
3868
5320
  }
3869
5321
 
5322
+ /**
5323
+ * A captured frame, read back from the canvas swapchain.
5324
+ *
5325
+ * `data` is tightly-packed RGBA8 (4 bytes/pixel), row-major, top row first — the same
5326
+ * layout `ImageData` expects, so it can be handed straight to a 2D canvas:
5327
+ *
5328
+ * ```ts
5329
+ * const shot = await captureScreenshot(surface);
5330
+ * const cv = new OffscreenCanvas(shot.width, shot.height);
5331
+ * cv.getContext("2d")!.putImageData(new ImageData(shot.data, shot.width, shot.height), 0, 0);
5332
+ * const url = await cv.convertToBlob({ type: "image/jpeg", quality: 0.85 });
5333
+ * ```
5334
+ *
5335
+ * Alpha is forced to 255 (fully opaque): the swapchain is presented opaque, so its alpha
5336
+ * channel is not meaningful for a saved image. Colours are the final, presented 8-bit
5337
+ * values (BGRA swizzled to RGBA when the preferred canvas format is BGRA).
5338
+ */
5339
+ export declare interface Screenshot {
5340
+ readonly width: number;
5341
+ readonly height: number;
5342
+ readonly data: Uint8ClampedArray;
5343
+ }
5344
+
3870
5345
  /**
3871
5346
  * Select a material variant by name on a loaded glTF asset.
3872
5347
  *
@@ -3969,11 +5444,10 @@ export declare function setEffectTexture(wrapper: EffectWrapper, bindingNameOrIn
3969
5444
  */
3970
5445
  export declare function setEffectUniforms(wrapper: EffectWrapper, data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): void;
3971
5446
 
3972
- /** Set the swapchain backing-store size directly, in device pixels. Use this when the
3973
- * engine renders into an `OffscreenCanvas` whose layout size is only known on another
3974
- * thread (the host posts the CSS size × devicePixelRatio). When the size changes, asks
3975
- * every registered rendering context to rebuild its canvas-sized GPU resources via the
3976
- * optional `_resize` hook. */
5447
+ /** Set the engine's primary-surface swapchain backing-store size directly, in device
5448
+ * pixels. Convenience wrapper around `setSurfaceSize(engine, w, h)` since the engine
5449
+ * *is* its own primary surface for auxiliary surfaces, prefer calling `setSurfaceSize`
5450
+ * on the specific target. */
3977
5451
  export declare function setEngineSize(engine: EngineContext, widthPx: number, heightPx: number): void;
3978
5452
 
3979
5453
  /**
@@ -3987,6 +5461,9 @@ export declare function setEngineSize(engine: EngineContext, widthPx: number, he
3987
5461
  */
3988
5462
  export declare function setFog(scene: SceneContext, config: FogConfig): void;
3989
5463
 
5464
+ /** Set one or more orientation fields at once (single recompute). Omitted fields keep their value. */
5465
+ export declare function setGeospatialOrientation(camera: GeospatialCamera, orientation: GeospatialOrientation): void;
5466
+
3990
5467
  /** Raise (or lower) the maximum number of scene lights in the shared lights UBO.
3991
5468
  * Must be called BEFORE scene pipelines are compiled — existing pipelines
3992
5469
  * and UBOs bake the cap into their WGSL/layout. */
@@ -4011,13 +5488,33 @@ export declare function setNavigationRandomSeed(plugin: NavigationPlugin, seed:
4011
5488
  */
4012
5489
  export declare function setParent(child: Mesh, parent: IWorldMatrixProvider | null): void;
4013
5490
 
5491
+ /**
5492
+ * Set a body's angular velocity (rad/s).
5493
+ */
5494
+ export declare function setPhysicsBodyAngularVelocity(world: PhysicsWorld, body: PhysicsBody, velocity: Vec3): void;
5495
+
5496
+ /**
5497
+ * Set a body's linear velocity (m/s) directly — e.g. to impart a throw velocity on release.
5498
+ */
5499
+ export declare function setPhysicsBodyLinearVelocity(world: PhysicsWorld, body: PhysicsBody, velocity: Vec3): void;
5500
+
4014
5501
  /**
4015
5502
  * Sets a body's mass and a matching diagonal inertia tensor.
4016
5503
  * @param world - The physics world.
4017
5504
  * @param body - The body to update.
4018
5505
  * @param mass - Mass in kilograms.
5506
+ * @param centerOfMass - Optional body-local centre of mass (defaults to the origin). Use this when the
5507
+ * collision shape is offset from the body's reference frame (e.g. a prop whose body origin sits at
5508
+ * its base but whose shape is centred on its middle) so it tumbles around its real centre.
4019
5509
  */
4020
- export declare function setPhysicsBodyMass(world: PhysicsWorld, body: PhysicsBody, mass: number): void;
5510
+ export declare function setPhysicsBodyMass(world: PhysicsWorld, body: PhysicsBody, mass: number, centerOfMass?: Vec3): void;
5511
+
5512
+ /**
5513
+ * Switch a body's motion type at runtime (e.g. ANIMATED/kinematic while a prop is grabbed, then
5514
+ * DYNAMIC on release). Mutates `body.motionType` so the per-frame step syncs it the right way
5515
+ * (ANIMATED: node → body before the step; DYNAMIC: body → node after).
5516
+ */
5517
+ export declare function setPhysicsBodyMotionType(world: PhysicsWorld, body: PhysicsBody, motionType: PhysicsMotionType): void;
4021
5518
 
4022
5519
  /**
4023
5520
  * Assigns a collision shape to a body.
@@ -4028,11 +5525,20 @@ export declare function setPhysicsBodyMass(world: PhysicsWorld, body: PhysicsBod
4028
5525
  export declare function setPhysicsBodyShape(world: PhysicsWorld, body: PhysicsBody, shape: PhysicsShape): void;
4029
5526
 
4030
5527
  /**
4031
- * Sets the world's gravity vector.
5528
+ * Teleport a body to a world position + orientation (a pure transform set — velocities are left
5529
+ * unchanged). For grab-follow, save-restore, and undo. Also updates the bound node so a render that
5530
+ * reads the node before the next physics step stays consistent.
5531
+ */
5532
+ export declare function setPhysicsBodyTransform(world: PhysicsWorld, body: PhysicsBody, position: Vec3, rotation: Quat): void;
5533
+
5534
+ /**
5535
+ * Sets gravity for the world, or for a single region when `worldPosition` is given.
5536
+ * Passing a position is useful for planetary scenarios where gravity direction varies by location.
4032
5537
  * @param world - The physics world.
4033
5538
  * @param gravity - Gravity acceleration in m/s².
5539
+ * @param worldPosition - Optional world position selecting the region to update; omit to update all regions.
4034
5540
  */
4035
- export declare function setPhysicsGravity(world: PhysicsWorld, gravity: Vec3): void;
5541
+ export declare function setPhysicsGravity(world: PhysicsWorld, gravity: Vec3, worldPosition?: Vec3): void;
4036
5542
 
4037
5543
  /**
4038
5544
  * Sets a shape's surface material properties.
@@ -4058,6 +5564,14 @@ export declare function setPhysicsTimestep(world: PhysicsWorld, dt: number): voi
4058
5564
  */
4059
5565
  export declare function setPhysicsVelocityLimits(world: PhysicsWorld, maxLinear: number, maxAngular: number): void;
4060
5566
 
5567
+ export declare function setPositionGizmoLocalCoordinates(gizmo: PositionGizmo, useLocal: boolean): void;
5568
+
5569
+ export declare function setRotationGizmoLocalCoordinates(gizmo: RotationGizmo, useLocal: boolean): void;
5570
+
5571
+ /** Toggle local-coord mode on the per-axis scale arrows. The uniform-scale
5572
+ * gizmo (centre) is always uniform so it ignores the flag. */
5573
+ export declare function setScaleGizmoLocalCoordinates(gizmo: ScaleGizmo, useLocal: boolean): void;
5574
+
4061
5575
  /** Set a declared `f32` uniform. Convenience wrapper over `setShaderUniform()`. */
4062
5576
  export declare function setShaderFloat(material: ShaderMaterial, name: string, value: number): void;
4063
5577
 
@@ -4121,6 +5635,18 @@ export declare function setSprite2DShaderParams(layer: Sprite2DLayer, params: re
4121
5635
  */
4122
5636
  export declare function setSprite2DUvOffset(layer: Sprite2DLayer, index: number, uvOffset: readonly [number, number]): void;
4123
5637
 
5638
+ /**
5639
+ * Redirect a sprite renderer's output to an offscreen render {@link Texture2D} `target` (for
5640
+ * render-to-texture / post-processing), or pass `null` to render to the swapchain (the
5641
+ * default). Pair with {@link createRenderTexture2D} at its default format and the renderer's
5642
+ * target size. The target's texture must be the engine's swapchain format: sprite pipelines
5643
+ * are baked with `engine.format`, so a target of any OTHER format fails WebGPU validation at
5644
+ * render-pass begin. A second renderer can then sample that texture (e.g. a fullscreen
5645
+ * custom-shader layer) and present it. Renderers registered later run later, so register the
5646
+ * offscreen scene pass before the presenting pass.
5647
+ */
5648
+ export declare function setSpriteRendererTarget(sr: SpriteRenderer, target: Texture2D | null): void;
5649
+
4124
5650
  /** Set `visible` on `node` and all descendants (via `node.children`). glTF
4125
5651
  * KHR_node_visibility specifies that children inherit their parent's
4126
5652
  * invisibility — we materialize this at set-time so the render hot-path
@@ -4129,9 +5655,34 @@ declare function setSubtreeVisible(node: SceneNode, v: boolean): void;
4129
5655
  export { setSubtreeVisible as setMeshVisible }
4130
5656
  export { setSubtreeVisible }
4131
5657
 
5658
+ /** Set this surface's swapchain backing-store size directly, in device pixels. Use this
5659
+ * when the surface renders into an `OffscreenCanvas` whose layout size is only known
5660
+ * on another thread (the host posts the CSS size × devicePixelRatio). When the size
5661
+ * changes, asks every rendering context registered on this surface to rebuild its
5662
+ * canvas-sized GPU resources via the optional `_resize` hook. */
5663
+ export declare function setSurfaceSize(surface: SurfaceContext, widthPx: number, heightPx: number): void;
5664
+
5665
+ /** Update the layer's pixel position. Convenience wrapper. */
5666
+ export declare function setTextLayerPosition(layer: TextLayer, x: number, y: number): void;
5667
+
5668
+ /** Update ONE instance's RGBA color in place — the color twin of `setThinInstanceMatrix`. Only the
5669
+ * touched span re-uploads (dirty-range), so per-instance color churn (e.g. streamed instances carrying
5670
+ * per-slot animation timestamps) stays cheap on large pools. Requires colors to have been set via
5671
+ * `setThinInstanceColors` first. */
5672
+ export declare function setThinInstanceColor(mesh: Mesh, index: number, r: number, g: number, b: number, a: number): void;
5673
+
4132
5674
  /** Set per-instance RGBA colors for a thin-instanced mesh. */
4133
5675
  export declare function setThinInstanceColors(mesh: Mesh, colors: Float32Array): void;
4134
5676
 
5677
+ /** Update ONLY the active instance count (and re-upload the [0,count) matrix range), leaving `_capacity`
5678
+ * — and therefore the already-allocated GPU buffer — untouched. This is the way to vary how many instances
5679
+ * draw FRAME-TO-FRAME on an established thin-instanced mesh WITHOUT recreating the GPU buffer (which would
5680
+ * invalidate any cached render/shadow bundle that captured the old buffer handle). Pre-size the buffer once
5681
+ * with `setThinInstances(mesh, matrices, capacity)`, then call this each update with `count <= capacity`.
5682
+ * The draw reads `count` live, so the bundle stays valid. Caller must keep writing into the SAME `matrices`
5683
+ * array the mesh already references. No-op if the mesh isn't thin-instanced yet. */
5684
+ export declare function setThinInstanceCount(mesh: Mesh, count: number): void;
5685
+
4135
5686
  /** Update one instance's matrix. */
4136
5687
  export declare function setThinInstanceMatrix(mesh: Mesh, index: number, matrix: Mat4): void;
4137
5688
 
@@ -4178,7 +5729,9 @@ export declare interface ShaderMaterial extends Material {
4178
5729
  readonly needAlphaTesting: boolean;
4179
5730
  readonly backFaceCulling: boolean;
4180
5731
  readonly depthWrite: boolean;
4181
- readonly depthCompare: GPUCompareFunction;
5732
+ readonly depthCompare: GPUCompareFunction;
5733
+ readonly depthBias: number;
5734
+ readonly depthBiasSlopeScale: number;
4182
5735
 
4183
5736
  /** Options describing a ShaderMaterial: WGSL sources, attributes, uniforms,
4184
5737
  * samplers, defines, and blend/depth state. Passed to `createShaderMaterial()`. */
@@ -4206,6 +5759,28 @@ export declare interface ShaderMaterialOptions {
4206
5759
  readonly backFaceCulling?: boolean;
4207
5760
  readonly depthWrite?: boolean;
4208
5761
  readonly depthCompare?: GPUCompareFunction;
5762
+ /** Constant depth-bias added in the pipeline's depth-stencil state (units of the depth format's minimum
5763
+ * representable value). Lets a surface that hugs another (e.g. tiles overlapping a cone, decals) win the
5764
+ * depth test consistently and avoid z-fighting. Default 0 (no bias). */
5765
+ readonly depthBias?: number;
5766
+ /** Slope-scaled depth bias — extra bias proportional to the depth gradient, so steeply-angled (grazing)
5767
+ * surfaces get more bias. Pairs with `depthBias` to kill z-fighting at oblique angles. Default 0. */
5768
+ readonly depthBiasSlopeScale?: number;
5769
+ }
5770
+
5771
+ /** Configuration for {@link createShaderNormalMaterialView}. */
5772
+ export declare interface ShaderNormalViewConfig {
5773
+ /** Name of the world-position varying the source vertex stage emits. Default `"vWorldPos"`. */
5774
+ readonly worldPosVarying?: string;
5775
+ /** `@location()` of that varying in the vertex output struct. Default `0`. */
5776
+ readonly worldPosLocation?: number;
5777
+ /** Output space of the encoded normal: `"view"` (default — ready for
5778
+ * Blender-style screen-space curvature) or `"world"`. */
5779
+ readonly space?: "view" | "world";
5780
+ /** When set, the output ALPHA encodes the fragment's view distance normalized by this range
5781
+ * (`clamp(viewZ / range, 0, 1)`) so a consumer can fade the effect with distance. Clear the target's
5782
+ * alpha to `1` as the "no geometry" sentinel. When omitted, alpha is a flat `1` (validity only). */
5783
+ readonly distanceEncodeRange?: number;
4209
5784
  }
4210
5785
 
4211
5786
  /** A sampler declaration: WGSL identifier and the bound texture's sample type. */
@@ -4507,15 +6082,31 @@ export declare interface SpriteAtlas {
4507
6082
  readonly texture: Texture2D;
4508
6083
  readonly textureSizePx: readonly [number, number];
4509
6084
  readonly frames: readonly SpriteFrame[];
4510
- readonly premultipliedAlpha: boolean;
4511
- }
6085
+ readonly premultipliedAlpha: boolean;
4512
6086
 
4513
- /** One source frame for `createSpriteAtlasFromFrames`. */
6087
+ /** One source frame for `createSpriteAtlasFromFrames` / `appendSpriteAtlasFrames`. The packed
6088
+ * region is `width × height` texels. By default the source is read as a tightly-packed RGBA8
6089
+ * buffer of exactly that size starting at byte 0; the optional `srcX` / `srcY` / `srcStrideBytes`
6090
+ * fields let the source describe a sub-rectangle of a larger buffer without forcing the caller
6091
+ * to copy out the sub-rect first. */
4514
6092
  export declare interface SpriteAtlasFrameSource {
4515
- /** Tightly packed RGBA8 bytes — `width * height * 4`, row-major, top-to-bottom, straight alpha. */
6093
+ /** RGBA8 bytes, row-major, top-to-bottom, straight alpha. When `srcX` / `srcY` /
6094
+ * `srcStrideBytes` are all defaulted, this must be exactly `width * height * 4` bytes;
6095
+ * when sub-rect fields are supplied, it must be large enough to cover the rect
6096
+ * (see those fields' docs). */
4516
6097
  readonly pixels: Uint8Array;
6098
+ /** Width of the frame to pack (texels written to the atlas). */
4517
6099
  readonly width: number;
6100
+ /** Height of the frame to pack (texels written to the atlas). */
4518
6101
  readonly height: number;
6102
+ /** Top-left x of the sub-rect to pack, in texels into `pixels`. Default `0`. */
6103
+ readonly srcX?: number;
6104
+ /** Top-left y of the sub-rect to pack, in texels into `pixels`. Default `0`. */
6105
+ readonly srcY?: number;
6106
+ /** Bytes between consecutive rows of `pixels`. Default `width * 4` (tightly packed).
6107
+ * Must satisfy `(srcX + width) * 4 <= srcStrideBytes` — i.e. each row's sub-rect window
6108
+ * must fit within one stride, so reads do not spill into the next row. */
6109
+ readonly srcStrideBytes?: number;
4519
6110
  /** Pivot in [0,1] of the frame. Default `[0.5, 0.5]`. */
4520
6111
  readonly pivot?: readonly [number, number];
4521
6112
  /** Recorded on the emitted `SpriteFrame.name`. */
@@ -4531,6 +6122,11 @@ export declare interface SpriteAtlasPackOptions {
4531
6122
  /** Min/mag filter for the packed texture. Default `"nearest"`. */
4532
6123
  sampling?: SpriteSampling;
4533
6124
  premultipliedAlpha?: boolean;
6125
+ /** Pre-allocate the atlas texture at this `[width, height]` regardless of initial-content
6126
+ * size, leaving headroom for later `appendSpriteAtlasFrames` calls (which never grow the
6127
+ * texture). Required when `sources` is empty. Defaults to the size required by the initial
6128
+ * `sources` (no append headroom). */
6129
+ capacityPx?: readonly [number, number];
4534
6130
  }
4535
6131
 
4536
6132
  /**
@@ -4635,6 +6231,9 @@ export declare interface SpriteRendererOptions {
4635
6231
  /** Texture sampling mode for a sprite atlas. */
4636
6232
  export declare type SpriteSampling = "linear" | "nearest";
4637
6233
 
6234
+ /** Inverse of `linearToSrgbByte` — sRGB byte [0,255] → linear [0,1]. */
6235
+ export declare function srgbByteToLinear(b: number): number;
6236
+
4638
6237
  /** Which shader stage an emitter writes into. Neutral blocks can run in either;
4639
6238
  * the walker places them in the stage of their consumer (fragment by default). */
4640
6239
  declare type Stage = "vertex" | "fragment";
@@ -4770,6 +6369,60 @@ export declare interface SubSurfaceProps {
4770
6369
  refraction?: RefractionProps;
4771
6370
  }
4772
6371
 
6372
+ /**
6373
+ * Per-canvas rendering surface — owns the GPU canvas context, swapchain format, MSAA
6374
+ * configuration, and the list of `RenderingContext`s (scenes, effect renderers,
6375
+ * frame-graph contexts, sprite/text renderers) that present to this canvas.
6376
+ *
6377
+ * The `EngineContext` *is itself a `SurfaceContext`* (the primary one, bound to the
6378
+ * canvas passed into `createEngine`). Additional surfaces for auxiliary canvases are
6379
+ * created via {@link createSurface}. GPU resources (textures, buffers, pipelines, bind
6380
+ * groups) live on the {@link EngineContext} (device-scoped) and are shared across all
6381
+ * surfaces of the same engine — only the swapchain output is per-surface.
6382
+ */
6383
+ export declare interface SurfaceContext {
6384
+ /** Owning engine. For the engine's primary surface this points back to the engine
6385
+ * itself (`engine.engine === engine`). */
6386
+ readonly engine: EngineContext;
6387
+ /** Canvas this surface presents to. */
6388
+ readonly canvas: RenderCanvas;
6389
+ /** Swapchain texture format for this surface. Use as the `format` for offscreen
6390
+ * RTs that will be composited onto this surface. */
6391
+ readonly format: GPUTextureFormat;
6392
+ /** MSAA sample count for the main render pass into this surface (1 or 4). */
6393
+ readonly msaaSamples: number;
4773
6394
  /**
6395
+ * Surface-owned color-only render target that wraps this canvas's swapchain texture.
6396
+ * Its `_colorTexture`/`_colorView` are re-acquired from `context.getCurrentTexture()`
6397
+ * once per frame (see `_refreshScRT`), so it is always single-sample and carries no
6398
+ * depth. Render/post-process/copy tasks target it (or resolve into it) to present to
6399
+ * the canvas. It is `_eager` — `buildRenderTarget` and `disposeRenderTarget` both
6400
+ * no-op on it and the surface owns its textures, so its shared `_descriptor` must
6401
+ * never be mutated.
6402
+ */
6403
+ readonly scRT: RenderTarget;
6404
+ /** Clamps the effective device pixel ratio used for this surface's swapchain backing
6405
+ * store. The backing store is sized at `min(devicePixelRatio, maxDevicePixelRatio) * cssPixels`.
6406
+ * `maxDevicePixelRatio = 1` renders at native CSS-pixel resolution (no DPR upscaling);
6407
+ * the default `Infinity` is unclamped (full devicePixelRatio). Mutable at runtime — set
6408
+ * before the next `resizeSurface` to take effect (mirrors Babylon `setHardwareScalingRatio`). */
6409
+ maxDevicePixelRatio: number;
6410
+
6411
+ /** Options for {@link createSurface}, and for the per-surface portion of `createEngine`. */
6412
+ export declare interface SurfaceOptions {
6413
+ /** MSAA sample count for the main render pass. WebGPU only permits `1` (no MSAA)
6414
+ * or `4` (4x MSAA). Defaults to `4`. */
6415
+ msaaSamples?: 1 | 4;
6416
+ /** WebGPU canvas alpha mode. Use `"premultiplied"` to enable canvas transparency
6417
+ * (clear color with `alpha < 1` will let HTML content underneath show through).
6418
+ * Defaults to `"opaque"`. */
6419
+ alphaMode?: GPUCanvasAlphaMode;
6420
+ /** Override the swapchain format. Defaults to `navigator.gpu.getPreferredCanvasFormat()`. */
6421
+ format?: GPUTextureFormat;
6422
+ /** Clamps the effective device pixel ratio used for the swapchain backing store.
6423
+ * Defaults to unclamped (full devicePixelRatio). */
6424
+ maxDevicePixelRatio?: number;
6425
+ }
6426
+
4774
6427
  declare type TargetPath = 0 | 1 | 2 | 3 | 4;
4775
6428
 
4776
6429
  /** Polymorphic interface that all frame-graph tasks implement: records `Pass` objects during `record()` and is executed once per frame. */
@@ -4785,6 +6438,125 @@ export declare interface Task {
4785
6438
  dispose(): void;
4786
6439
  }
4787
6440
 
6441
+ export declare interface TextData {
6442
+ readonly [textDataBrand]: true;
6443
+ /** Live, in-insertion-order view of the runs currently rendered. Mutated by
6444
+ * `updateTextData`. Do not mutate from outside. */
6445
+ readonly runs: readonly GlyphRun[];
6446
+
6447
+ declare const textDataBrand: unique symbol;
6448
+
6449
+ /** Discriminated union driving `updateTextData`. Each variant's `update` field is the
6450
+ * discriminator. Arrays/maps passed inside any variant are *adopted* by the `TextData`
6451
+ * and must not be read or mutated by the caller afterward. */
6452
+ export declare type TextDataUpdate = {
6453
+ /** Rebuild runs and/or swap to a different storage. Both `runs` and `storage`
6454
+ * are optional; missing fields default to the TextData's current value, so
6455
+ * `{ update: "reset" }` with neither performs a pure compaction pass that
6456
+ * re-lays-out the slot allocator without dead slots or gaps.
6457
+ * Invalidates any previously-passed `GlyphRun` references when `runs` is set. */
6458
+ update: "reset";
6459
+ runs?: GlyphRun[];
6460
+ storage?: GlyphStorage;
6461
+ } | {
6462
+ /** Append a new run to the live runs list, or insert it before the run currently at
6463
+ * `insertBefore`. The run's `curveSet` must already exist in the bound storage. */
6464
+ update: "addRun";
6465
+ run: GlyphRun;
6466
+ /** Index in `data.runs` to insert before. Default = append at end. */
6467
+ insertBefore?: number;
6468
+ } | {
6469
+ /** Remove a previously-added run. Accepts either the `GlyphRun` reference or its
6470
+ * current index in `data.runs`. */
6471
+ update: "removeRun";
6472
+ run: GlyphRun | number;
6473
+ } | {
6474
+ /** Replace one run's contents in place. The new run takes the slot in `data.runs`
6475
+ * that the previous run occupied. Cheapest when the new run has the same glyph
6476
+ * count and the same `curveSet` as the previous one. */
6477
+ update: "replaceRun";
6478
+ previous: GlyphRun | number;
6479
+ run: GlyphRun;
6480
+ };
6481
+
6482
+ /** Pure-data 2D text layer. Mutate fields directly between frames. */
6483
+ export declare interface TextLayer {
4788
6484
  readonly data: TextData;
6485
+ positionPx: {
6486
+ x: number;
6487
+ y: number;
6488
+ };
6489
+ rotationRad: number;
6490
+ scale: number;
6491
+ order: number;
6492
+ opacity: number;
6493
+ visible: boolean;
6494
+
6495
+ export declare interface TextLayerOptions {
6496
+ /** Top-left origin (in canvas pixels) for the layer's local coordinate frame. Default (0, 0). */
6497
+ readonly positionPx?: {
6498
+ readonly x: number;
6499
+ readonly y: number;
6500
+ };
6501
+ /** Z-axis rotation about `positionPx`, in radians. Default 0. */
6502
+ readonly rotationRad?: number;
6503
+ /** Uniform scale applied to the laid-out text. Default 1. */
6504
+ readonly scale?: number;
6505
+ /** Sort order within a renderer (lower draws first). Default 0. */
6506
+ readonly order?: number;
6507
+ /** Alpha multiplier in [0, 1]. Default 1. */
6508
+ readonly opacity?: number;
6509
+ /** Default true. */
6510
+ readonly visible?: boolean;
6511
+ }
6512
+
6513
+ export declare type TextLayoutOptions = {
6514
+ /** Max line width in pixels before word-wrap. Default: Infinity. */
6515
+ readonly maxWidth?: number;
6516
+ /** Line-height multiplier. Default: 1.2. */
6517
+ readonly lineHeight?: number;
6518
+ /** Horizontal alignment. Default: "left". */
6519
+ readonly align?: "left" | "center" | "right";
6520
+ /** Extra spacing in font units. Default: 0. */
6521
+ readonly letterSpacing?: number;
6522
+ /** Tab size in spaces. Default: 4. */
6523
+ readonly tabSize?: number;
6524
+ };
6525
+
6526
+ export declare interface TextRenderable extends Renderable {
4789
6527
  readonly position: ObservableVec3;
6528
+ readonly rotation: EulerProxy;
6529
+ readonly rotationQuaternion: ObservableQuat;
6530
+ readonly scaling: ObservableVec3;
6531
+ /** Whole-block opacity in [0,1]. Color is supplied per-glyph by the `TextData` descriptor. */
6532
+ opacity: number;
6533
+ ignoreDepth: boolean;
6534
+ order: number;
6535
+
6536
+ export declare interface TextRenderableOptions {
6537
+ readonly position?: Readonly<Vec3>;
6538
+ readonly rotationQuaternion?: {
6539
+ readonly x: number;
6540
+ readonly y: number;
6541
+ readonly z: number;
6542
+ readonly w: number;
6543
+ };
6544
+ readonly scaling?: Readonly<Vec3>;
6545
+ /** Whole-block opacity in [0,1]. Default 1. Per-glyph/per-run color comes from the `TextData`
6546
+ * descriptor (`PlacedGlyph.color` / `GlyphRun.defaultColor`), not from the renderable. */
6547
+ readonly opacity?: number;
6548
+ readonly ignoreDepth?: boolean;
6549
+ readonly order?: number;
6550
+ }
6551
+
6552
+ export declare interface TextRenderer extends RenderingContext_2 {
4790
6553
  readonly layers: readonly TextLayer[];
6554
+
6555
+ export declare interface TextRendererOptions {
6556
+ layers: readonly TextLayer[];
6557
+ /** Default true. Set false for HUD overlays so the text pass preserves existing scene color. */
6558
+ clear?: boolean;
6559
+ /** Default `{ r: 0, g: 0, b: 0, a: 1 }`. */
6560
+ clearValue?: GPUColorDict;
6561
+ }
6562
+
4791
6563
  /** A loaded 2D texture: the GPU texture, its default view and sampler, pixel
4792
6564
  * dimensions, and an optional per-texture UV transform. This is the public
4793
6565
  * texture handle returned by `loadTexture2D()`, `createSolidTexture2D()`, etc. */
@@ -4990,18 +6762,21 @@ export declare interface UniformEffectWrapperOptions {
4990
6762
  uniformByteLength: number;
4991
6763
  }
4992
6764
 
4993
- /** Unregister the effect renderer from its engine. No-op if not registered. */
6765
+ /** Unregister the effect renderer from its surface. No-op if not registered. */
4994
6766
  export declare function unregisterEffectRenderer(er: EffectRenderer): void;
4995
6767
 
4996
- /** Unregister the standalone frame-graph context from its engine. */
6768
+ /** Unregister the standalone frame-graph context from its surface. */
4997
6769
  export declare function unregisterFrameGraphContext(ctx: FrameGraphContext): void;
4998
6770
 
4999
- /** Remove a previously-registered scene. Idempotent. Does not dispose scene resources. */
5000
- export declare function unregisterScene(engine: EngineContext, scene: SceneContext): void;
6771
+ /** Remove a previously-registered scene. Idempotent. Does not dispose scene resources.
6772
+ * The scene is always removed from `scene.surface`. */
6773
+ export declare function unregisterScene(scene: SceneContext): void;
5001
6774
 
5002
6775
  /** Splice the renderer out of its engine's `_renderingContexts`. No-op if not present. */
5003
6776
  export declare function unregisterSpriteRenderer(sr: SpriteRenderer): void;
5004
6777
 
6778
+ export declare function unregisterTextRenderer(tr: TextRenderer): void;
6779
+
5005
6780
  /** Advances every active task by `deltaMs` (or by `fixedDeltaMs` when set), running the category handler first.
5006
6781
  * Ignores non-finite or negative steps. */
5007
6782
  export declare function updateAnimationManager(manager: AnimationManager, deltaMs: number): void;
@@ -5023,6 +6798,28 @@ export declare function updateBillboardSprite(handle: BillboardSpriteHandle, pat
5023
6798
  */
5024
6799
  export declare function updateBillboardSpriteIndex(system: BillboardSpriteSystem, index: number, patch: Partial<BillboardSpriteInit>): void;
5025
6800
 
6801
+ /** Re-shape `text` and apply the new run via `updateTextData(replaceRun)`. New glyphs are
6802
+ * added to the storage in place. When `textColor` is omitted, the live run's existing
6803
+ * `defaultColor` is preserved (so any caller-driven color override survives a text re-shape). */
6804
+ export declare function updateDefaultTextData(data: DefaultTextData, text: string, textColor?: readonly [number, number, number, number]): void;
6805
+
6806
+ /** Add glyphs to the named curve-set, creating it if it doesn't exist yet. Glyph ids
6807
+ * already present in the curve-set are skipped (the existing outline + atlas slot wins).
6808
+ * Safe to call between frames: the atlas grows in place and the next render uploads the
6809
+ * new glyphs. */
6810
+ export declare function updateGlyphStorage(storage: GlyphStorage, curveSetId: CurveSetId, curves: ReadonlyMap<number, GlyphCurves>): void;
6811
+
6812
+ /** Re-upload (part of) a mesh's COLOR buffer — the twin of `updateMeshNormals`/`updateMeshPositions`
6813
+ * for dynamically re-generated geometry whose per-vertex colors change (e.g. a procedural mesh whose
6814
+ * parts are re-tinted each rebuild). The color attribute is vec4 (16 bytes/vertex). No-op if the mesh
6815
+ * was created without colors. Zero-allocation GPU upload only. */
6816
+ export declare function updateMeshColors(engine: EngineContext, mesh: Mesh, colors: Float32Array, vertexOffset?: number): void;
6817
+
6818
+ /** Re-upload (part of) a mesh's NORMAL buffer — the twin of `updateMeshPositions` for dynamically
6819
+ * re-generated geometry whose per-vertex normals change (e.g. a swept tube re-fitted each rebuild).
6820
+ * No-op if the mesh was created without normals. Zero-allocation GPU upload only. */
6821
+ export declare function updateMeshNormals(engine: EngineContext, mesh: Mesh, normals: Float32Array, vertexOffset?: number): void;
6822
+
5026
6823
  /** Update a mesh's GPU vertex positions in place (e.g. CPU vertex animation).
5027
6824
  * `positions` must hold tightly-packed XYZ floats matching the mesh's vertex count.
5028
6825
  * `vertexOffset` is the first vertex to overwrite (defaults to 0).
@@ -5030,6 +6827,24 @@ export declare function updateBillboardSpriteIndex(system: BillboardSpriteSystem
5030
6827
  * Zero-allocation GPU upload only — CPU-side picking geometry is not refreshed. */
5031
6828
  export declare function updateMeshPositions(engine: EngineContext, mesh: Mesh, positions: Float32Array, vertexOffset?: number): void;
5032
6829
 
6830
+ /** Re-upload (part of) a mesh's TANGENT buffer — the twin of `updateMeshColors` for dynamically
6831
+ * re-generated geometry whose per-vertex tangent (vec4) payload changes each rebuild (e.g. a procedural
6832
+ * batch that streams a per-vertex coordinate frame / mask through the tangent slot). The tangent attribute
6833
+ * is vec4 (16 bytes/vertex). No-op if the mesh was created without tangents. Zero-allocation GPU upload only. */
6834
+ export declare function updateMeshTangents(engine: EngineContext, mesh: Mesh, tangents: Float32Array, vertexOffset?: number): void;
6835
+
6836
+ /** Re-upload (part of) a mesh's second UV buffer (uv2) — the twin of `updateMeshUvs` for dynamically
6837
+ * re-generated geometry whose per-vertex uv2 payload changes each rebuild (e.g. a procedural batch that
6838
+ * re-bakes per-vertex AO / gradient data). The uv2 attribute is vec2 (8 bytes/vertex). No-op if the mesh
6839
+ * was created without uv2. Zero-allocation GPU upload only. */
6840
+ export declare function updateMeshUv2(engine: EngineContext, mesh: Mesh, uvs2: Float32Array, vertexOffset?: number): void;
6841
+
6842
+ /** Re-upload (part of) a mesh's UV buffer — the twin of `updateMeshNormals`/`updateMeshColors` for
6843
+ * dynamically re-generated geometry whose per-vertex UVs change (e.g. a procedural mesh whose parts
6844
+ * carry per-rebuild UV payloads). The uv attribute is vec2 (8 bytes/vertex). No-op if the mesh was
6845
+ * created without UVs. Zero-allocation GPU upload only. */
6846
+ export declare function updateMeshUvs(engine: EngineContext, mesh: Mesh, uvs: Float32Array, vertexOffset?: number): void;
6847
+
5033
6848
  /** Advance the crowd simulation by `dt` seconds. */
5034
6849
  export declare function updateNavCrowd(crowd: NavCrowd, dt: number): void;
5035
6850
 
@@ -5055,6 +6870,8 @@ export declare function updateSprite2DIndex(layer: Sprite2DLayer, index: number,
5055
6870
  */
5056
6871
  export declare function updateSpriteAnimationManager(manager: SpriteAnimationManager, deltaMs: number): void;
5057
6872
 
6873
+ export declare function updateTextData(data: TextData, update: TextDataUpdate): void;
6874
+
5058
6875
  /**
5059
6876
  * Update a rectangular region of an existing `Texture2D` from a tightly-packed RGBA8 byte buffer.
5060
6877
  *
@@ -5072,6 +6889,22 @@ export declare function updateSpriteAnimationManager(manager: SpriteAnimationMan
5072
6889
  */
5073
6890
  export declare function updateTexture2DFromPixels(engine: EngineContext, tex: Texture2D, data: Uint8Array, x?: number, y?: number, width?: number, height?: number): void;
5074
6891
 
6892
+ /** UtilityLayer handle. The `scene` field is a regular `SceneContext` — pass it
6893
+ * to gizmo factories so their meshes are added there instead of the main
6894
+ * scene. */
6895
+ export declare interface UtilityLayer {
6896
+ readonly scene: SceneContext;
6897
+ readonly mainScene: SceneContext;
6898
+ }
6899
+
6900
+ export declare interface UtilityLayerOptions {
6901
+ /** Add a built-in hemispheric light so gizmo materials are visible without
6902
+ * the caller adding one. Defaults to true. */
6903
+ addDefaultLight?: boolean;
6904
+ /** Default light intensity when `addDefaultLight` is true. Defaults to 1.0. */
6905
+ lightIntensity?: number;
6906
+ }
6907
+
5075
6908
  /** Per-mesh original + variant material entry. */
5076
6909
  declare interface VariantMeshEntry {
5077
6910
  mesh: Mesh;
@@ -5080,6 +6913,75 @@ declare interface VariantMeshEntry {
5080
6913
 
5081
6914
  declare interface Varying {
5082
6915
 
6916
+ /** Result of baking — the GPU texture plus a per-clip row map for choosing playback params. */
6917
+ export declare interface VatBakeResult {
6918
+ readonly texture: GPUTexture;
6919
+ readonly boneCount: number;
6920
+ readonly frameCount: number;
6921
+ /** Clip name → row range, for building the per-mesh/per-instance (fromRow,toRow,offset,fps) params. */
6922
+ readonly clips: Record<string, VatClip>;
6923
+ }
6924
+
6925
+ /** Where one clip landed in the baked texture: its first row, its frame count, and its native fps. */
6926
+ export declare interface VatClip {
6927
+ readonly fromRow: number;
6928
+ readonly frameCount: number;
6929
+ readonly fps: number;
6930
+ }
6931
+
6932
+ /** VAT (Vertex Animation Texture) GPU data — BAKED skinning. Attached to `mesh.vat` by vat/vat-baker.ts.
6933
+ * The skeletal animation is pre-evaluated into `texture` (one frame per row); the shader reads bone
6934
+ * matrices from the current frame's row instead of a live per-frame upload, so the mesh thin-instances.
6935
+ * Reuses the same joints/weights vertex-buffer field names as SkeletonData so the renderable binds either. */
6936
+ declare interface VatData {
6937
+ readonly boneCount: number;
6938
+ /** Baked bone-matrix texture: rgba32float, (boneCount*4) × frameCount, one animation frame per row
6939
+ * (identical per-row layout to the live bone texture in skeleton/create-skeleton.ts). */
6940
+ readonly texture: GPUTexture;
6941
+ readonly frameCount: number;
6942
+ /** UBO consumed by the VAT vertex fragment: `params` vec4 = (fromRow, toRow, frameOffset, fps);
6943
+ * `clock` vec4 .x = elapsed seconds. Advanced by the VAT manager (vat/vat-baker.ts). */
6944
+ readonly settingsBuffer: GPUBuffer;
6945
+ readonly jointsBuffer: GPUBuffer;
6946
+ readonly weightsBuffer: GPUBuffer;
6947
+ readonly joints1Buffer: GPUBuffer | null;
6948
+ readonly weights1Buffer: GPUBuffer | null;
6949
+ /** Optional per-instance VAT params texture (rgba32float, (2*instanceCount) x 1): TWO texels per
6950
+ * thin-instance — A=(fromRow,toRow,offset,fps), B=(fromRow,toRow,blend,fps) — so each instance plays
6951
+ * its own clip + phase (and can blend two clips) from the one shared baked texture. Present + the mesh
6952
+ * thin-instanced ⇒ the VAT vertex path reads its frame rows from this texture indexed by
6953
+ * `@builtin(instance_index)` instead of the shared settings UBO. Set via the VatHandle. */
6954
+ instanceTexture?: GPUTexture | null;
6955
+ }
6956
+
6957
+ /** Runtime VAT playback handle for one mesh (the analogue of BJS BakedVertexAnimationManager + the
6958
+ * per-mesh settings). Advance `update()` each frame; set the active clip with `play()`. */
6959
+ export declare interface VatHandle {
6960
+ /** The mesh this drives (its `mesh.vat` is set). */
6961
+ readonly mesh: Mesh;
6962
+ /** Baked clip row map. */
6963
+ readonly clips: Record<string, VatClip>;
6964
+ /** Select the clip to play (by name) or set explicit playback params. */
6965
+ play(clip: string, opts?: {
6966
+ offset?: number;
6967
+ fps?: number;
6968
+ }): void;
6969
+ /** Advance the animation clock by `dtSeconds` and upload it. */
6970
+ update(dtSeconds: number): void;
6971
+ /** Enable/refresh PER-INSTANCE VAT: upload one vec4 (fromRow, toRow, timeOffset, fps) per thin-instance,
6972
+ * so every instance plays its own clip + phase from the one shared baked texture (all instances in a
6973
+ * single draw call). `params.length` must be `4 * instanceCount`. Call this BEFORE registerScene the
6974
+ * first time — it sets `mesh.vat.instanceTexture`; a VAT mesh that is thin-instanced then takes the
6975
+ * per-instance vertex path. Later calls re-upload in place. Use `clips` to look up each clip's
6976
+ * fromRow/toRow/fps when building `params`. (Internally expanded to the dual-clip layout, blend 0.) */
6977
+ setInstances(params: Float32Array): void;
6978
+ /** PER-INSTANCE DUAL-CLIP VAT: like setInstances, but each instance carries TWO clips that are blended,
6979
+ * so gait cross-fades stay smooth. `params.length` must be `8 * instanceCount` — two vec4s per instance:
6980
+ * A = (fromRowA, toRowA, timeOffset, fpsA), B = (fromRowB, toRowB, blendWeight, fpsB), where blendWeight
6981
+ * in [0,1] lerps A→B and B reuses A's timeOffset. Same per-instance VAT path as setInstances. */
6982
+ setInstancesBlend(params: Float32Array): void;
6983
+ }
6984
+
5083
6985
  /** 3-component vector (position, direction, color) */
5084
6986
  export declare interface Vec3 {
5085
6987
  x: number;