@babylonjs/lite 0.1.1 → 0.2.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 (197) hide show
  1. package/_mat4-storage-f64-Bvh5TymE.js +10 -0
  2. package/_mat4-storage-f64-Bvh5TymE.js.map +1 -0
  3. package/{alpha-test-fragment-CUiHCw7W.js → alpha-test-fragment-BCChpzaV.js} +2 -2
  4. package/{alpha-test-fragment-CUiHCw7W.js.map → alpha-test-fragment-BCChpzaV.js.map} +1 -1
  5. package/{background-dds-skybox-yHTqabU3.js → background-dds-skybox-ZjrSIxrT.js} +4 -4
  6. package/background-dds-skybox-ZjrSIxrT.js.map +1 -0
  7. package/{background-ground-DIw6D3qf.js → background-ground-B2Mie-MI.js} +3 -3
  8. package/background-ground-B2Mie-MI.js.map +1 -0
  9. package/{background-hdr-skybox-c4uuTmkP.js → background-hdr-skybox-DDRJYuT2.js} +3 -3
  10. package/background-hdr-skybox-DDRJYuT2.js.map +1 -0
  11. package/{background-solid-skybox-DPGBpPbm.js → background-solid-skybox-fjXlnWaD.js} +3 -3
  12. package/{background-solid-skybox-DPGBpPbm.js.map → background-solid-skybox-fjXlnWaD.js.map} +1 -1
  13. package/{billboard-renderable-D8mlVGCd.js → billboard-renderable-DKmlOgbM.js} +2 -2
  14. package/{billboard-renderable-D8mlVGCd.js.map → billboard-renderable-DKmlOgbM.js.map} +1 -1
  15. package/{clamp-block-BdII67hT.js → clamp-block-CxRBPlUq.js} +2 -2
  16. package/{clamp-block-BdII67hT.js.map → clamp-block-CxRBPlUq.js.map} +1 -1
  17. package/{clearcoat-fragment-LCiG98Rf.js → clearcoat-fragment-KbZAa0TA.js} +2 -2
  18. package/{clearcoat-fragment-LCiG98Rf.js.map → clearcoat-fragment-KbZAa0TA.js.map} +1 -1
  19. package/{create-skeleton-C9JdIJnb.js → create-skeleton-BBI5urcj.js} +2 -2
  20. package/{create-skeleton-C9JdIJnb.js.map → create-skeleton-BBI5urcj.js.map} +1 -1
  21. package/{cubemap-skybox-material-DvXMVc4k.js → cubemap-skybox-material-DvW81drX.js} +2 -2
  22. package/{cubemap-skybox-material-DvXMVc4k.js.map → cubemap-skybox-material-DvW81drX.js.map} +1 -1
  23. package/{curve-block-BlJpXVYv.js → curve-block-Dh_xdUj-.js} +2 -2
  24. package/{curve-block-BlJpXVYv.js.map → curve-block-Dh_xdUj-.js.map} +1 -1
  25. package/{emissive-fragment-BnNvbBCw.js → emissive-fragment-DD8cvHyx.js} +2 -2
  26. package/{emissive-fragment-BnNvbBCw.js.map → emissive-fragment-DD8cvHyx.js.map} +1 -1
  27. package/{esm-shadow-view-DGKdF1NI.js → esm-shadow-view-15S4JK6p.js} +2 -2
  28. package/{esm-shadow-view-DGKdF1NI.js.map → esm-shadow-view-15S4JK6p.js.map} +1 -1
  29. package/{esm-shadow-view-Dk9NFtLq.js → esm-shadow-view-DHVS9r7H.js} +2 -2
  30. package/{esm-shadow-view-Dk9NFtLq.js.map → esm-shadow-view-DHVS9r7H.js.map} +1 -1
  31. package/{esm-shadow-view-DN9HIaM4.js → esm-shadow-view-DYAc62Kl.js} +2 -2
  32. package/{esm-shadow-view-DN9HIaM4.js.map → esm-shadow-view-DYAc62Kl.js.map} +1 -1
  33. package/{gaussian-splatting-pipeline-sh-DgJl7l56.js → gaussian-splatting-pipeline-sh-BvkUhA9V.js} +2 -2
  34. package/{gaussian-splatting-pipeline-sh-DgJl7l56.js.map → gaussian-splatting-pipeline-sh-BvkUhA9V.js.map} +1 -1
  35. package/{gltf-animation-D7uyTyO3.js → gltf-animation-KnPzeOIY.js} +3 -3
  36. package/{gltf-animation-D7uyTyO3.js.map → gltf-animation-KnPzeOIY.js.map} +1 -1
  37. package/gltf-color-normalize-Qxl-9C48.js +29 -0
  38. package/gltf-color-normalize-Qxl-9C48.js.map +1 -0
  39. package/{gltf-ext-basisu-CPg5kPrx.js → gltf-ext-basisu-kmth3UWX.js} +7 -4
  40. package/gltf-ext-basisu-kmth3UWX.js.map +1 -0
  41. package/{gltf-ext-node-visibility-MafA9ot2.js → gltf-ext-node-visibility-BjRRd6si.js} +2 -2
  42. package/{gltf-ext-node-visibility-MafA9ot2.js.map → gltf-ext-node-visibility-BjRRd6si.js.map} +1 -1
  43. package/{gltf-ext-uv-transform-CE_-T1Tr.js → gltf-ext-uv-transform-MHmR-YyM.js} +2 -2
  44. package/{gltf-ext-uv-transform-CE_-T1Tr.js.map → gltf-ext-uv-transform-MHmR-YyM.js.map} +1 -1
  45. package/{gltf-feature-animation-pointer-BjpwOOqo.js → gltf-feature-animation-pointer-rFqLfbO_.js} +3 -3
  46. package/{gltf-feature-animation-pointer-BjpwOOqo.js.map → gltf-feature-animation-pointer-rFqLfbO_.js.map} +1 -1
  47. package/{gltf-feature-animations-CCizegp8.js → gltf-feature-animations-DikONdzi.js} +2 -2
  48. package/{gltf-feature-animations-CCizegp8.js.map → gltf-feature-animations-DikONdzi.js.map} +1 -1
  49. package/{gltf-feature-gpu-instancing-2e_CFQnl.js → gltf-feature-gpu-instancing-Cj1XjmM6.js} +5 -4
  50. package/gltf-feature-gpu-instancing-Cj1XjmM6.js.map +1 -0
  51. package/{gltf-feature-lights-punctual-DDDg4j0U.js → gltf-feature-lights-punctual-C-0SlGmD.js} +5 -5
  52. package/{gltf-feature-lights-punctual-DDDg4j0U.js.map → gltf-feature-lights-punctual-C-0SlGmD.js.map} +1 -1
  53. package/{gltf-feature-morph-CKCw6tkX.js → gltf-feature-morph-BAcY14XU.js} +3 -3
  54. package/{gltf-feature-morph-CKCw6tkX.js.map → gltf-feature-morph-BAcY14XU.js.map} +1 -1
  55. package/gltf-feature-registry-97sY_x5O.js +59 -0
  56. package/gltf-feature-registry-97sY_x5O.js.map +1 -0
  57. package/{gltf-feature-skeleton-D8hWLqi2.js → gltf-feature-skeleton-lVjkDfIU.js} +3 -3
  58. package/{gltf-feature-skeleton-D8hWLqi2.js.map → gltf-feature-skeleton-lVjkDfIU.js.map} +1 -1
  59. package/{gltf-feature-variants-Ds6v9byg.js → gltf-feature-variants-BphF4JmV.js} +2 -2
  60. package/{gltf-feature-variants-Ds6v9byg.js.map → gltf-feature-variants-BphF4JmV.js.map} +1 -1
  61. package/{gltf-interleave-DGnUlz28.js → gltf-interleave-C9eBqH_F.js} +2 -2
  62. package/{gltf-interleave-DGnUlz28.js.map → gltf-interleave-C9eBqH_F.js.map} +1 -1
  63. package/gltf-normals-b2h74380.js +37 -0
  64. package/gltf-normals-b2h74380.js.map +1 -0
  65. package/{gltf-pbr-builder-ext-BFOxOCnQ.js → gltf-pbr-builder-ext-DPC0zg_u.js} +2 -2
  66. package/{gltf-pbr-builder-ext-BFOxOCnQ.js.map → gltf-pbr-builder-ext-DPC0zg_u.js.map} +1 -1
  67. package/{gltf-variants-DFbr8EES.js → gltf-variants-CnBEZr0o.js} +4 -4
  68. package/{gltf-variants-DFbr8EES.js.map → gltf-variants-CnBEZr0o.js.map} +1 -1
  69. package/{gs-picking-pipeline-DzfMASL9.js → gs-picking-pipeline-Bx8LTav6.js} +2 -2
  70. package/{gs-picking-pipeline-DzfMASL9.js.map → gs-picking-pipeline-Bx8LTav6.js.map} +1 -1
  71. package/{index-C8HOR2sB.js → index-B7Qhw0xL.js} +3047 -1037
  72. package/index-B7Qhw0xL.js.map +1 -0
  73. package/index.d.ts +504 -17
  74. package/index.js +322 -304
  75. package/{input-block-DgAJBzN_.js → input-block-Coi_aZwl.js} +2 -2
  76. package/{input-block-DgAJBzN_.js.map → input-block-Coi_aZwl.js.map} +1 -1
  77. package/{iridescence-fragment-Gymp7or5.js → iridescence-fragment-DwZcCTdD.js} +2 -2
  78. package/{iridescence-fragment-Gymp7or5.js.map → iridescence-fragment-DwZcCTdD.js.map} +1 -1
  79. package/{light-block-B11ew7FA.js → light-block-Np_h5gPI.js} +2 -2
  80. package/{light-block-B11ew7FA.js.map → light-block-Np_h5gPI.js.map} +1 -1
  81. package/{loop-block-Bb23EOMb.js → loop-block-BFkLFYGm.js} +2 -2
  82. package/{loop-block-Bb23EOMb.js.map → loop-block-BFkLFYGm.js.map} +1 -1
  83. package/{mesh-features-BLENkYVt.js → mesh-features-BAJpbMog.js} +6 -3
  84. package/mesh-features-BAJpbMog.js.map +1 -0
  85. package/{morph-fragment-DOVo70gP.js → morph-fragment-DqH-w61u.js} +2 -2
  86. package/{morph-fragment-DOVo70gP.js.map → morph-fragment-DqH-w61u.js.map} +1 -1
  87. package/{multilight-wgsl-BGyiIOp3.js → multilight-wgsl-B9Mf9d-q.js} +4 -4
  88. package/{multilight-wgsl-BGyiIOp3.js.map → multilight-wgsl-B9Mf9d-q.js.map} +1 -1
  89. package/no-color-view-DsyLSL-W.js +8 -0
  90. package/no-color-view-DsyLSL-W.js.map +1 -0
  91. package/{node-registry-DwgC4yth.js → node-registry-Bd-AlrgC.js} +8 -8
  92. package/{node-registry-DwgC4yth.js.map → node-registry-Bd-AlrgC.js.map} +1 -1
  93. package/{node-registry-extra-compat-Dhrw8fDQ.js → node-registry-extra-compat-Ch7ApZHF.js} +2 -2
  94. package/{node-registry-extra-compat-Dhrw8fDQ.js.map → node-registry-extra-compat-Ch7ApZHF.js.map} +1 -1
  95. package/{node-registry-extra-math-CsAHvIZo.js → node-registry-extra-math-6ezzTkPj.js} +2 -2
  96. package/{node-registry-extra-math-CsAHvIZo.js.map → node-registry-extra-math-6ezzTkPj.js.map} +1 -1
  97. package/{node-renderable-DlLIdBmd.js → node-renderable-CS0CmsSp.js} +28 -11
  98. package/node-renderable-CS0CmsSp.js.map +1 -0
  99. package/{node-shadow-DKrcqmNg.js → node-shadow-CpnrdvtJ.js} +2 -2
  100. package/{node-shadow-DKrcqmNg.js.map → node-shadow-CpnrdvtJ.js.map} +1 -1
  101. package/{normal-map-fragment-DpsIXrJf.js → normal-map-fragment-DradEMl-.js} +3 -3
  102. package/{normal-map-fragment-DpsIXrJf.js.map → normal-map-fragment-DradEMl-.js.map} +1 -1
  103. package/pack-mat4-with-offset-BqB8Jqo7.js +37 -0
  104. package/pack-mat4-with-offset-BqB8Jqo7.js.map +1 -0
  105. package/package.json +3 -3
  106. package/{parse-camera-DM3oJJeT.js → parse-camera-CgV4bWc0.js} +2 -2
  107. package/{parse-camera-DM3oJJeT.js.map → parse-camera-CgV4bWc0.js.map} +1 -1
  108. package/pbr-fog-wgsl-BqdCid6r.js +8 -0
  109. package/pbr-fog-wgsl-BqdCid6r.js.map +1 -0
  110. package/{pbr-metallic-roughness-block-h_KAOZrW.js → pbr-metallic-roughness-block-BFwZj2Nw.js} +2 -2
  111. package/{pbr-metallic-roughness-block-h_KAOZrW.js.map → pbr-metallic-roughness-block-BFwZj2Nw.js.map} +1 -1
  112. package/{pbr-metallic-roughness-block-full-6vMm1Jk6.js → pbr-metallic-roughness-block-full-5t0HT3xl.js} +2 -2
  113. package/{pbr-metallic-roughness-block-full-6vMm1Jk6.js.map → pbr-metallic-roughness-block-full-5t0HT3xl.js.map} +1 -1
  114. package/{pbr-mr-helper-core-CIwm-T1G.js → pbr-mr-helper-core-R5tOZ8Ap.js} +2 -2
  115. package/{pbr-mr-helper-core-CIwm-T1G.js.map → pbr-mr-helper-core-R5tOZ8Ap.js.map} +1 -1
  116. package/{pbr-refraction-DGmMSa2v.js → pbr-refraction-Dd11HnaI.js} +2 -2
  117. package/{pbr-refraction-DGmMSa2v.js.map → pbr-refraction-Dd11HnaI.js.map} +1 -1
  118. package/{pbr-renderable-BJxUtPBb.js → pbr-renderable-BHAdF5Vw.js} +80 -38
  119. package/pbr-renderable-BHAdF5Vw.js.map +1 -0
  120. package/{pbr-shadow-fragment-LO9SlbJj.js → pbr-shadow-fragment-BxUrFJYZ.js} +6 -1
  121. package/pbr-shadow-fragment-BxUrFJYZ.js.map +1 -0
  122. package/{pbr-template-ext-8q7BcTDf.js → pbr-template-ext-CGgB2n2y.js} +3 -2
  123. package/{pbr-template-ext-8q7BcTDf.js.map → pbr-template-ext-CGgB2n2y.js.map} +1 -1
  124. package/{pbr-tracking-B3alzn91.js → pbr-tracking-D6i3yPb7.js} +2 -2
  125. package/{pbr-tracking-B3alzn91.js.map → pbr-tracking-D6i3yPb7.js.map} +1 -1
  126. package/pbr-transmission-ext-Dll8EYwE.js +190 -0
  127. package/pbr-transmission-ext-Dll8EYwE.js.map +1 -0
  128. package/{reflectance-fragment-BCrgPmrt.js → reflectance-fragment-ejMJ4O1o.js} +2 -2
  129. package/{reflectance-fragment-BCrgPmrt.js.map → reflectance-fragment-ejMJ4O1o.js.map} +1 -1
  130. package/{shader-renderable-D-6796KR.js → shader-renderable-BMf_vvO0.js} +41 -12
  131. package/shader-renderable-BMf_vvO0.js.map +1 -0
  132. package/shader-thin-instance-5_WUfi3m.js +150 -0
  133. package/shader-thin-instance-5_WUfi3m.js.map +1 -0
  134. package/shadow-fragment-core-DHN2G6FI.js.map +1 -1
  135. package/{sheen-fragment-Dze2f7XJ.js → sheen-fragment-CS6z29Fs.js} +2 -2
  136. package/{sheen-fragment-Dze2f7XJ.js.map → sheen-fragment-CS6z29Fs.js.map} +1 -1
  137. package/{singlelight-directional-wgsl-CmUDZxwz.js → singlelight-directional-wgsl-4MIgZMeC.js} +2 -2
  138. package/{singlelight-directional-wgsl-CmUDZxwz.js.map → singlelight-directional-wgsl-4MIgZMeC.js.map} +1 -1
  139. package/{singlelight-hemispheric-wgsl-t-83IP_s.js → singlelight-hemispheric-wgsl-CK-GUYWe.js} +2 -2
  140. package/{singlelight-hemispheric-wgsl-t-83IP_s.js.map → singlelight-hemispheric-wgsl-CK-GUYWe.js.map} +1 -1
  141. package/{singlelight-point-wgsl-CLzULIYV.js → singlelight-point-wgsl-CYtzqCbP.js} +2 -2
  142. package/{singlelight-point-wgsl-CLzULIYV.js.map → singlelight-point-wgsl-CYtzqCbP.js.map} +1 -1
  143. package/{singlelight-spot-wgsl-DEEUrfVM.js → singlelight-spot-wgsl-DVbaVufF.js} +2 -2
  144. package/{singlelight-spot-wgsl-DEEUrfVM.js.map → singlelight-spot-wgsl-DVbaVufF.js.map} +1 -1
  145. package/{skeleton-fragment-B_XlFbtx.js → skeleton-fragment-BOVmc8YS.js} +2 -2
  146. package/{skeleton-fragment-B_XlFbtx.js.map → skeleton-fragment-BOVmc8YS.js.map} +1 -1
  147. package/{skybox-renderable-DDwzu-PT.js → skybox-renderable-DDcCPSly.js} +3 -3
  148. package/{skybox-renderable-DDwzu-PT.js.map → skybox-renderable-DDcCPSly.js.map} +1 -1
  149. package/{standard-renderable-GjxL9xSf.js → standard-renderable-D1bhoF0K.js} +27 -81
  150. package/standard-renderable-D1bhoF0K.js.map +1 -0
  151. package/{std-ambient-fragment-BoUsD06w.js → std-ambient-fragment-C6WNm8dQ.js} +2 -2
  152. package/{std-ambient-fragment-BoUsD06w.js.map → std-ambient-fragment-C6WNm8dQ.js.map} +1 -1
  153. package/{std-cube-reflection-fragment-ulqc3bsP.js → std-cube-reflection-fragment-Bqutpy2q.js} +2 -2
  154. package/{std-cube-reflection-fragment-ulqc3bsP.js.map → std-cube-reflection-fragment-Bqutpy2q.js.map} +1 -1
  155. package/{std-emissive-fragment-DNGj1HdQ.js → std-emissive-fragment-B-A83rqX.js} +2 -2
  156. package/{std-emissive-fragment-DNGj1HdQ.js.map → std-emissive-fragment-B-A83rqX.js.map} +1 -1
  157. package/{std-lightmap-fragment-Bqj89aIe.js → std-lightmap-fragment-Df7KJezh.js} +2 -2
  158. package/{std-lightmap-fragment-Bqj89aIe.js.map → std-lightmap-fragment-Df7KJezh.js.map} +1 -1
  159. package/{std-opacity-fragment-KuPh5N2Z.js → std-opacity-fragment-D9et2jip.js} +2 -2
  160. package/{std-opacity-fragment-KuPh5N2Z.js.map → std-opacity-fragment-D9et2jip.js.map} +1 -1
  161. package/{std-reflection-fragment-BA5Ghn_M.js → std-reflection-fragment-DBJeT-yg.js} +2 -2
  162. package/{std-reflection-fragment-BA5Ghn_M.js.map → std-reflection-fragment-DBJeT-yg.js.map} +1 -1
  163. package/std-shadow-fragment-C6fD8rW-.js +13 -0
  164. package/std-shadow-fragment-C6fD8rW-.js.map +1 -0
  165. package/{std-specular-fragment-CE-6scqd.js → std-specular-fragment-C2ZOss-t.js} +2 -2
  166. package/{std-specular-fragment-CE-6scqd.js.map → std-specular-fragment-C2ZOss-t.js.map} +1 -1
  167. package/{std-tracking-CNKZ-hJN.js → std-tracking-C4L4nQGc.js} +2 -2
  168. package/{std-tracking-CNKZ-hJN.js.map → std-tracking-C4L4nQGc.js.map} +1 -1
  169. package/{subsurface-fragment-liM3y2-P.js → subsurface-fragment-C1H4ytqK.js} +2 -2
  170. package/{subsurface-fragment-liM3y2-P.js.map → subsurface-fragment-C1H4ytqK.js.map} +1 -1
  171. package/thin-instance-cull-binding-CCxrPNO6.js +310 -0
  172. package/thin-instance-cull-binding-CCxrPNO6.js.map +1 -0
  173. package/{thin-instance-gpu-C9Gv_Z1w.js → thin-instance-gpu-E8DBd8XL.js} +20 -3
  174. package/thin-instance-gpu-E8DBd8XL.js.map +1 -0
  175. package/{tracking-primitives-wgdBY85t.js → tracking-primitives-w4BVV9p9.js} +2 -2
  176. package/{tracking-primitives-wgdBY85t.js.map → tracking-primitives-w4BVV9p9.js.map} +1 -1
  177. package/{unlit-fragment-BIlhJpz6.js → unlit-fragment-DU9_mhzZ.js} +2 -2
  178. package/{unlit-fragment-BIlhJpz6.js.map → unlit-fragment-DU9_mhzZ.js.map} +1 -1
  179. package/{wgsl-helpers-DyzNzCeE.js → wgsl-helpers-D8sl1VVA.js} +4 -4
  180. package/{wgsl-helpers-DyzNzCeE.js.map → wgsl-helpers-D8sl1VVA.js.map} +1 -1
  181. package/background-dds-skybox-yHTqabU3.js.map +0 -1
  182. package/background-ground-DIw6D3qf.js.map +0 -1
  183. package/background-hdr-skybox-c4uuTmkP.js.map +0 -1
  184. package/gltf-ext-basisu-CPg5kPrx.js.map +0 -1
  185. package/gltf-feature-gpu-instancing-2e_CFQnl.js.map +0 -1
  186. package/index-C8HOR2sB.js.map +0 -1
  187. package/mesh-features-BLENkYVt.js.map +0 -1
  188. package/node-renderable-DlLIdBmd.js.map +0 -1
  189. package/pbr-renderable-BJxUtPBb.js.map +0 -1
  190. package/pbr-shadow-fragment-LO9SlbJj.js.map +0 -1
  191. package/pbr-transmission-ext-BxW4CEGu.js +0 -581
  192. package/pbr-transmission-ext-BxW4CEGu.js.map +0 -1
  193. package/shader-renderable-D-6796KR.js.map +0 -1
  194. package/standard-renderable-GjxL9xSf.js.map +0 -1
  195. package/std-shadow-fragment-FNQfrJuC.js +0 -8
  196. package/std-shadow-fragment-FNQfrJuC.js.map +0 -1
  197. package/thin-instance-gpu-C9Gv_Z1w.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-C8HOR2sB.js","sources":["../src/engine/engine.ts","../src/mesh/mesh-dispose.ts","../src/frame-graph/frame-graph.ts","../src/engine/render-target.ts","../src/math/mat4-multiply-into.ts","../src/math/mat4-perspective-lh-to-ref.ts","../src/camera/camera.ts","../src/render/scene-helpers.ts","../src/resource/gpu-buffers.ts","../src/shader/scene-uniforms-size.ts","../src/light/types.ts","../src/render/lights-ubo.ts","../src/frame-graph/render-task.ts","../src/scene/scene-core.ts","../src/math/mat4-identity.ts","../src/math/mat4-look-at-lh.ts","../src/math/vec3-up.ts","../src/scene/world-matrix-state.ts","../src/math/observable-vec3.ts","../src/camera/arc-rotate.ts","../src/math/vec3-ctor.ts","../src/scene/scene-camera.ts","../src/scene/scene-remove.ts","../src/scene/visibility.ts","../src/frame-graph/pass.ts","../src/frame-graph/render-pass.ts","../src/frame-graph/frame-graph-actions.ts","../src/frame-graph/frame-graph-context.ts","../src/frame-graph/image-processing-task.ts","../src/frame-graph/shadow-inputs.ts","../src/frame-graph/shadow-task.ts","../src/resource/gpu-pool.ts","../src/resource/samplers.ts","../src/texture/rtt.ts","../src/effect/effect-renderer.ts","../src/effect/uniform-effect-renderer.ts","../src/frame-graph/post-process-task.ts","../src/post-process/black-and-white.ts","../src/post-process/anaglyph.ts","../src/post-process/blur.ts","../src/post-process/extract-highlights.ts","../src/post-process/chromatic-aberration.ts","../src/post-process/bloom.ts","../src/camera/arc-rotate-controls.ts","../src/camera/free-camera.ts","../src/camera/free-camera-controls.ts","../src/light/light-base.ts","../src/light/light-matrix.ts","../src/light/hemispheric.ts","../src/math/mat4-translation.ts","../src/light/point-light.ts","../src/light/directional-light.ts","../src/light/spot-light.ts","../src/math/mat4-compose-into.ts","../src/math/mat4-compose.ts","../src/math/observable-quat.ts","../src/scene/scene-node.ts","../src/mesh/mesh.ts","../src/math/compute-aabb.ts","../src/mesh/create-sphere.ts","../src/mesh/create-box.ts","../src/mesh/create-torus.ts","../src/mesh/create-ground.ts","../src/mesh/create-cylinder.ts","../src/mesh/create-plane.ts","../src/mesh/create-disc.ts","../src/mesh/polyhedron-data.ts","../src/mesh/compute-normals.ts","../src/mesh/create-polyhedron.ts","../src/mesh/create-ribbon.ts","../src/math/cross-vec3.ts","../src/math/length-vec3.ts","../src/math/normalize-vec3-object.ts","../src/math/sub-vec3.ts","../src/mesh/path3d.ts","../src/mesh/create-tube.ts","../src/mesh/create-extrude.ts","../src/mesh/mesh-factories.ts","../src/math/mat4-invert.ts","../src/math/normalize-vec3.ts","../src/mesh/csg.ts","../src/mesh/csg2.ts","../src/texture/solid-texture.ts","../src/texture/pixels-texture.ts","../src/texture/texture-2d.ts","../src/texture/compressed-formats.ts","../src/texture/ktx-loader.ts","../src/texture/basis-loader.ts","../src/material/standard/standard-flags.ts","../src/material/standard/standard-group-builder.ts","../src/material/standard/create-standard-material.ts","../src/material/material-view.ts","../src/material/standard/no-color-view.ts","../src/material/pbr/pbr-flag-bits.ts","../src/material/pbr/pbr-flags.ts","../src/material/pbr/pbr-material.ts","../src/material/shader/shader-group-builder.ts","../src/material/shader/shader-material.ts","../src/material/grid/grid-material.ts","../src/material/pbr/no-color-view.ts","../src/material/node/node-parser.ts","../src/material/node/node-types.ts","../src/material/node/node-emitter.ts","../shaders/scene-uniforms.wgsl?raw","../src/shader/scene-uniforms.ts","../src/shader/ubo-layout.ts","../src/material/node/node-pipeline.ts","../src/material/node/node-material.ts","../src/material/node/node-flags.ts","../src/material/node/no-color-view.ts","../src/material/material-dirty.ts","../src/material/material-rebuild.ts","../src/material/observable-material.ts","../src/scene/transform-node.ts","../src/loader-gltf/gltf-parser.ts","../src/loader-gltf/gltf-material.ts","../src/texture/mip-count.ts","../src/math/color.ts","../src/loader-gltf/gltf-pbr-builder.ts","../src/loader-gltf/load-gltf.ts","../src/loader-gltf/material-variants.ts","../src/math/mat4-multiply.ts","../src/scene/set-parent.ts","../src/loader-babylon/load-babylon.ts","../src/loader-env/env-helpers.ts","../src/material/pbr/scene-size.ts","../src/loader-env/load-env.ts","../src/math/spherical-harmonics.ts","../src/loader-hdr/hdr-parser.ts","../shaders/hdr-equirect-to-cube.compute.wgsl?raw","../shaders/hdr-prefilter-cube.compute.wgsl?raw","../shaders/hdr-brdf-lut.compute.wgsl?raw","../src/loader-hdr/hdr-ibl-pipeline.ts","../src/loader-hdr/load-hdr.ts","../src/texture/generate-mipmaps.ts","../src/texture/cube-texture.ts","../src/loader-skybox/load-skybox.ts","../src/loader-splat/splat-ply-parser.ts","../src/loader-splat/splat-data.ts","../src/math/mat4-scale.ts","../src/mesh/GaussianSplatting/gaussian-splatting-mesh.ts","../shaders/gaussian-splatting.wgsl?raw","../src/mesh/GaussianSplatting/gaussian-splatting-pipeline.ts","../src/loader-splat/load-splat.ts","../src/loader-splat/zip-parser.ts","../src/loader-splat/load-sog.ts","../src/loader-splat/load-spz.ts","../src/mesh/GaussianSplatting/gaussian-splatting-bake.ts","../src/mesh/GaussianSplatting/create-gaussian-splatting-mesh.ts","../src/mesh/GaussianSplatting/gs-depth-fragments.ts","../src/mesh/GaussianSplatting/gs-gpu-picking-fragment.ts","../src/render/linear-depth-material.ts","../src/shadow/shadow-base.ts","../shaders/shadow-blur.vertex.wgsl?raw","../src/shadow/esm-directional-shadow-generator.ts","../src/shadow/pcf-shadow-task-hooks.ts","../src/shadow/pcf-spotlight-shadow-generator.ts","../src/shadow/pcf-directional-shadow-generator.ts","../src/animation/types.ts","../src/animation/evaluate.ts","../src/skeleton/skeleton-updater.ts","../src/animation/animation-group.ts","../src/animation/animation-weight.ts","../src/animation/animation-manager.ts","../src/animation/animation-group-task.ts","../src/animation/weighted-pointer-mixer.ts","../src/animation/weighted-gltf-mixer.ts","../src/animation/property-animation.ts","../src/morph/create-morph-targets.ts","../src/mesh/thin-instance.ts","../src/camera/viewport.ts","../src/picking/picking-info.ts","../src/picking/ray.ts","../src/picking/picking-shader.ts","../src/shader/bgl-helpers.ts","../src/picking/picking-pipeline.ts","../src/picking/gpu-picker.ts","../src/picking/deformed-geometry.ts","../src/picking/detailed-picking.ts","../src/picking/picking-helpers.ts","../src/sprite/shared/sprite-atlas.ts","../src/sprite/shared/sprite-atlas-packer.ts","../src/sprite/blend-descriptors.ts","../src/sprite/sprite-blend.ts","../src/sprite/sprite-fx-hook.ts","../src/sprite/sprite-2d.ts","../src/sprite/custom-shader-core.ts","../src/sprite/sprite-pipeline.ts","../src/sprite/sprite-custom-shader.ts","../src/sprite/sprite-2d-handle.ts","../src/sprite/sprite-renderable.ts","../src/sprite/sprite-scene.ts","../src/sprite/billboard-blend.ts","../src/sprite/billboard-sprite.ts","../src/sprite/billboard-pipeline.ts","../src/sprite/billboard-custom-shader.ts","../src/sprite/billboard-sprite-handle.ts","../src/sprite/billboard-scene.ts","../src/sprite/sprite-animation.ts","../src/sprite/sprite-animation-task.ts","../src/sprite/sprite-2d-index-animation.ts","../src/sprite/sprite-2d-handle-animation.ts","../src/sprite/billboard-sprite-index-animation.ts","../src/sprite/billboard-sprite-handle-animation.ts","../src/sprite/sprite-renderer.ts","../src/physics/havok.ts","../src/navigation/navigation.ts"],"sourcesContent":["import type { Mesh } from \"../mesh/mesh.js\";\nimport type { Texture2D, Texture2DOptions } from \"../texture/texture-2d.js\";\n\n/** Babylon Lite version string. */\nexport const VERSION = \"0.1.0\";\n\n// Module-scoped visibility epoch. setSubtreeVisible (scene/visibility.ts,\n// loaded only by KHR_node_visibility / KHR_animation_pointer features) bumps\n// this. Per-scene bundle caches compare against it for invalidation.\nexport let _vis = 0;\nexport function bumpVisibilityEpoch(): void {\n _vis = (_vis + 1) | 0;\n}\n\n/**\n * A surface Babylon Lite can render into. Either a DOM canvas (main thread) or an\n * `OffscreenCanvas` (e.g. one transferred to a Web Worker via\n * `transferControlToOffscreen()`). Both expose `getContext(\"webgpu\")` plus a\n * read/write backing-store `width`/`height`; only the DOM canvas exposes layout\n * (`clientWidth`/`clientHeight`) and attributes (`setAttribute`).\n */\nexport type RenderCanvas = HTMLCanvasElement | OffscreenCanvas;\n\n/** @internal Type guard: true for a DOM canvas (has layout + attributes). */\nfunction isDomCanvas(canvas: RenderCanvas): canvas is HTMLCanvasElement {\n return \"clientWidth\" in canvas;\n}\n\n/** Handle to the WebGPU engine — pure state, no attached methods. */\nexport interface EngineContext {\n readonly canvas: RenderCanvas;\n readonly msaaSamples: number;\n /** Preferred GPU texture format for the swapchain. Use as the `colorFormat`\n * for offscreen RTs that are sampled by main-pass materials. */\n readonly format: GPUTextureFormat;\n\n /** Number of GPU draw calls in the last rendered frame. */\n drawCallCount: number;\n\n /** Clamps the effective device pixel ratio used for the swapchain backing store.\n * The backing store is sized at `min(devicePixelRatio, maxDevicePixelRatio) * cssPixels`.\n * `maxDevicePixelRatio = 1` renders at native CSS-pixel resolution (no DPR upscaling);\n * the default `Infinity` is unclamped (full devicePixelRatio). Mutable at runtime — set\n * before the next `resizeEngine` to take effect (mirrors `setHardwareScalingRatio`). */\n maxDevicePixelRatio: number;\n\n /** @internal */\n _device: GPUDevice;\n /** @internal */\n readonly _context: GPUCanvasContext;\n /** @internal */\n readonly _alphaMode: GPUCanvasAlphaMode;\n /** @internal */\n _dlr?: DeviceLostRecoveryCapture;\n /** @internal */\n _animFrameId: number;\n /** @internal */\n _renderFn: ((now: number) => void) | null;\n /** @internal Registered rendering contexts in render order (first clears; subsequent overlay). */\n _renderingContexts: RenderingContext[];\n\n // ─── Per-frame transient state ─────────────────────────────────────\n /** @internal Encoder being filled this frame. Set by `renderFrame` before each context's\n * `_update`/`_record`; consumed by frame-graph tasks and pre-passes. */\n _currentEncoder: GPUCommandEncoder;\n /** @internal Swapchain view acquired once per frame before contexts record. */\n _swapchainView: GPUTextureView;\n /** @internal Frame delta in ms (read by scenes that don't override fixedDeltaMs). */\n _currentDelta: number;\n /** @internal */\n _cbs: GPUCommandBuffer[];\n}\n\n/**\n * Minimal surface an engine sees for anything it renders. Scenes (and any other\n * future renderable thing) register themselves as a `RenderingContext` and\n * own their own update / record logic. Engine knows nothing of scene internals.\n */\nexport interface RenderingContext {\n /** @internal Draw calls produced by pre-pass work during `_update` (shadows + pre-passes). */\n _drawCallsPre: number;\n /** Clear color used when this context is the first active one in a frame. */\n clearColor: GPUColorDict;\n /** @internal Run per-frame update work (beforeRender hooks, shadow + pre-passes, UBO updates,\n * transparent sort). Reads / mutates engine state via `engine._currentEncoder` and\n * `engine._currentDelta`. */\n _update(): void;\n /** @internal Drive this context's GPU work — typically delegates to\n * `frameGraph.execute()`. Returns draw-call count. */\n _record(): number;\n /** @internal Optional. Called by the engine when the canvas backing-store size changes.\n * Implementations should rebuild any canvas-sized GPU resources (e.g. ask\n * their frame graph to rebuild so render targets get re-allocated). */\n _resize?(): void;\n}\n\n/** @internal */\ninterface DeviceLostRecoveryCapture {\n u(tex: Texture2D, url: string, opts: Texture2DOptions): void;\n s(tex: Texture2D, r: number, g: number, b: number, a: number): void;\n b(tex: Texture2D, bitmap: ImageBitmap | null, srgb: boolean, mipMaps: boolean, fallback?: Uint8Array): void;\n m(\n mesh: Mesh,\n uv2s: Float32Array | null | undefined,\n tangents: Float32Array | null | undefined,\n colors: Float32Array | null | undefined,\n gpuIndices: Uint16Array | Uint32Array,\n indexFormat: GPUIndexFormat\n ): void;\n}\n\n/** @internal Return true if `context` is already registered with `engine`. */\nexport function isRenderingContextRegistered(engine: EngineContext, context: RenderingContext): boolean {\n return engine._renderingContexts.indexOf(context) !== -1;\n}\n\n/** @internal Register a rendering context with the engine. Returns false if already present. */\nexport function registerRenderingContext(engine: EngineContext, context: RenderingContext): boolean {\n if (isRenderingContextRegistered(engine, context)) {\n return false;\n }\n engine._renderingContexts.push(context);\n return true;\n}\n\n/** @internal Unregister a rendering context from the engine. Returns false if not present. */\nexport function unregisterRenderingContext(engine: EngineContext, context: RenderingContext): boolean {\n const list = engine._renderingContexts;\n const i = list.indexOf(context);\n if (i === -1) {\n return false;\n }\n list.splice(i, 1);\n return true;\n}\n\nexport interface RenderTargetSize {\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Options for `createEngine`.\n * - `msaaSamples`: number of MSAA samples to use for the main render pass.\n * WebGPU only permits `1` (no MSAA) or `4` (4x MSAA) per the spec\n * (2x is not a valid WebGPU sample count). Defaults to `4`.\n */\nexport interface EngineOptions {\n msaaSamples?: 1 | 4;\n /**\n * WebGPU canvas alpha mode. Use \"premultiplied\" to enable canvas transparency (clear color\n * with `alpha < 1` will let HTML content underneath show through). Defaults to \"opaque\".\n */\n alphaMode?: GPUCanvasAlphaMode;\n /**\n * Clamps the effective device pixel ratio used for the swapchain backing store.\n * The backing store is sized at `min(devicePixelRatio, maxDevicePixelRatio) * cssPixels`.\n * `maxDevicePixelRatio: 1` renders at native CSS-pixel resolution (no DPR upscaling) —\n * useful on high-DPI/iOS devices where `devicePixelRatio` is ~3. Defaults to unclamped\n * (full devicePixelRatio). Equivalent to Babylon.js `setHardwareScalingRatio`.\n */\n maxDevicePixelRatio?: number;\n}\n\n/** Create the Babylon Lite engine. Acquires GPU adapter + device, configures swapchain.\n * Accepts either a DOM canvas (main thread) or an `OffscreenCanvas` (e.g. transferred to\n * a Web Worker) — see {@link RenderCanvas}. */\nexport async function createEngine(canvas: RenderCanvas, options?: EngineOptions): Promise<EngineContext> {\n const adapter = await navigator.gpu.requestAdapter({ powerPreference: \"high-performance\" });\n if (!adapter) {\n throw new Error(\"WebGPU adapter not available\");\n }\n\n const features: GPUFeatureName[] = [];\n if (adapter.features.has(\"float32-filterable\")) {\n features.push(\"float32-filterable\");\n }\n for (const f of [\"texture-compression-astc\", \"texture-compression-bc\", \"texture-compression-etc2\"] as GPUFeatureName[]) {\n if (adapter.features.has(f)) {\n features.push(f);\n }\n }\n const device = await adapter.requestDevice({ requiredFeatures: features });\n const context = canvas.getContext(\"webgpu\");\n if (!context) {\n throw new Error(\"WebGPU context not available\");\n }\n\n const format = navigator.gpu.getPreferredCanvasFormat();\n const alphaMode: GPUCanvasAlphaMode = options?.alphaMode ?? \"opaque\";\n context.configure({ device, format, alphaMode });\n\n const versionToLog = `Babylon Lite v${VERSION}`;\n // eslint-disable-next-line no-console\n console.log(`${versionToLog} - WebGPU engine`);\n if (isDomCanvas(canvas)) {\n canvas.setAttribute(\"data-engine\", versionToLog);\n }\n\n const msaaSamples: 1 | 4 = options?.msaaSamples === 1 ? 1 : 4;\n\n const engine: EngineContext = {\n _device: device,\n _context: context,\n format,\n _alphaMode: alphaMode,\n canvas,\n msaaSamples,\n drawCallCount: 0,\n maxDevicePixelRatio: options?.maxDevicePixelRatio ?? Infinity,\n _animFrameId: 0,\n _renderFn: null,\n _renderingContexts: [],\n _currentEncoder: undefined!,\n _swapchainView: undefined!,\n _currentDelta: 0,\n _cbs: [],\n };\n\n resizeEngine(engine);\n\n return engine;\n}\n\n/** Resize the swapchain backing-store to match the canvas client size. When the size\n * changes, asks every registered rendering context to rebuild its canvas-sized GPU\n * resources via the optional `_resize` hook. If the canvas has not been laid out yet,\n * preserves its explicit backing-store size.\n *\n * Only DOM canvases are auto-sized from layout here. An `OffscreenCanvas` has no layout\n * box, so its size is pushed in externally via {@link setEngineSize} (e.g. from the host\n * thread that owns the visible canvas) and this call is a no-op for it. */\nexport function resizeEngine(engine: EngineContext): void {\n const canvas = engine.canvas;\n if (!isDomCanvas(canvas)) {\n return;\n }\n const clientWidth = canvas.clientWidth;\n const clientHeight = canvas.clientHeight;\n if (!(clientWidth > 0 && clientHeight > 0)) {\n return;\n }\n const scale = Math.min(globalThis.devicePixelRatio || 1, engine.maxDevicePixelRatio);\n const w = (clientWidth * scale) | 0;\n const h = (clientHeight * scale) | 0;\n setEngineSize(engine, w, h);\n}\n\n/** Set the swapchain backing-store size directly, in device pixels. Use this when the\n * engine renders into an `OffscreenCanvas` whose layout size is only known on another\n * thread (the host posts the CSS size × devicePixelRatio). When the size changes, asks\n * every registered rendering context to rebuild its canvas-sized GPU resources via the\n * optional `_resize` hook. */\nexport function setEngineSize(engine: EngineContext, widthPx: number, heightPx: number): void {\n const canvas = engine.canvas;\n const w = widthPx | 0;\n const h = heightPx | 0;\n if (!(w > 0 && h > 0)) {\n return;\n }\n if (w === canvas.width && h === canvas.height) {\n return;\n }\n canvas.width = w;\n canvas.height = h;\n for (const c of engine._renderingContexts) {\n c._resize?.();\n }\n}\n\n/** @internal Return the canvas-backed render target dimensions. In the frame-graph\n * architecture, render targets are owned by `RenderingContext`s rather than the\n * engine itself; this helper exposes the canvas size for callers that just need\n * the swapchain dimensions (e.g. sprite renderer). */\nexport function getRenderTargetSize(engine: EngineContext): RenderTargetSize {\n const c = engine.canvas;\n return { width: c.width, height: c.height };\n}\n\n/**\n * Start the render loop. Resolves after the first frame has been rendered.\n * Scenes registered via `registerScene()` before this call are included in\n * the first frame; later registrations join on subsequent frames.\n */\nexport function startEngine(engine: EngineContext): Promise<void> {\n return new Promise<void>((resolve) => {\n let firstRafFrame = true;\n let lastTime = 0;\n engine._renderFn = (now: number) => {\n const delta = firstRafFrame ? 0 : lastTime > 0 ? now - lastTime : 16.667;\n lastTime = now;\n resizeEngine(engine);\n renderFrame(engine, delta);\n if (firstRafFrame) {\n firstRafFrame = false;\n resolve();\n }\n engine._animFrameId = requestAnimationFrame(engine._renderFn!);\n };\n engine._animFrameId = requestAnimationFrame(engine._renderFn);\n });\n}\n\n/** Stop the render loop. */\nexport function stopEngine(engine: EngineContext): void {\n if (engine._animFrameId) {\n cancelAnimationFrame(engine._animFrameId);\n }\n engine._animFrameId = 0;\n engine._renderFn = null;\n}\n\n/** Release all engine-owned GPU resources (device + swapchain). Rendering contexts\n * own their own GPU resources (frame graphs, render targets) and dispose them\n * separately. */\nexport function disposeEngine(engine: EngineContext): void {\n stopEngine(engine);\n engine._renderingContexts.length = 0;\n engine._context.unconfigure();\n engine._device.destroy();\n}\n\nfunction renderFrame(engine: EngineContext, delta: number): void {\n const ctxs = engine._renderingContexts;\n if (ctxs.length === 0) {\n return;\n }\n\n const encoder = engine._device.createCommandEncoder({ label: \"frame\" });\n engine._currentEncoder = encoder;\n engine._currentDelta = delta;\n engine._swapchainView = engine._context.getCurrentTexture().createView();\n\n let drawCalls = 0;\n for (let i = 0; i < ctxs.length; i++) {\n const s = ctxs[i]!;\n s._update();\n drawCalls += s._drawCallsPre;\n drawCalls += s._record();\n }\n\n const finalEncoder = engine._currentEncoder;\n engine._cbs[0] = finalEncoder.finish();\n engine._device.queue.submit(engine._cbs);\n engine.drawCallCount = drawCalls;\n}\n","import type { Mesh } from \"./mesh.js\";\n\n/** Destroy all GPU resources owned by a mesh (vertex buffers, skeleton, morph targets). */\nexport function disposeMeshGpu(mesh: Mesh): void {\n const g = mesh._gpu;\n g.positionBuffer.destroy();\n g.normalBuffer.destroy();\n g.uvBuffer.destroy();\n g.indexBuffer.destroy();\n g.tangentBuffer?.destroy();\n g.uv2Buffer?.destroy();\n mesh.thinInstances?._gpuBuffer?.destroy();\n mesh.thinInstances?._colorGpuBuffer?.destroy();\n const sk = mesh.skeleton;\n if (sk) {\n sk.boneTexture.destroy();\n sk.jointsBuffer.destroy();\n sk.weightsBuffer.destroy();\n sk.joints1Buffer?.destroy();\n sk.weights1Buffer?.destroy();\n }\n if (mesh.morphTargets) {\n mesh.morphTargets.texture.destroy();\n mesh.morphTargets.weightsBuffer.destroy();\n }\n}\n","/**\n * FrameGraph — orchestrates a scene's per-frame GPU work as an ordered list\n * of tasks. There is no privileged \"main\" task: a scene-render task that\n * draws into the swapchain is just one task among many. Pre-pass RTTs run\n * first, the scene-render task draws into the swapchain, UI overlay tasks\n * run after, etc. Order is the user's responsibility (controlled via\n * `addTask`, `addTaskAtStart`, and `addTaskBefore`).\n *\n * Lifecycle:\n * 1. createFrameGraph(engine) → empty graph\n * 2. `addTask{,AtStart,Before}` → register tasks\n * (createSceneContext registers a default scene-render task)\n * 3. fg.build() → record every task\n * (allocate render-target textures, build pass descriptors)\n * 4. fg.execute() → drain every task into the\n * current command encoder (called from scene._record)\n * 5. fg.dispose() → free everything\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Task } from \"./task.js\";\n\n/** The frame graph — an ordered list of tasks. */\nexport interface FrameGraph {\n /** Ordered list of tasks. Executed in array order each frame. */\n /** @internal */\n _tasks: Task[];\n\n /** Set during `build()` while a single task's `record()` is running.\n * Used by `addRenderPass` to associate a\n * freshly-created pass with the task that is currently recording.\n * Mirrors BJS' implicit \"currentProcessedTask\" in `frameGraph.buildAsync`. */\n /** @internal */\n _currentProcessedTask: Task | null;\n\n /** Build (or rebuild) every task in execute order. */\n build(): void;\n\n /** Execute every task's recorded passes. Returns total draw calls. */\n execute(): number;\n\n /** Free all GPU resources owned by the frame graph. */\n dispose(): void;\n}\n\n/** Create an empty frame graph bound to the given engine. */\nexport function createFrameGraph(_engine: EngineContext): FrameGraph {\n const fg: FrameGraph = {\n _tasks: [],\n _currentProcessedTask: null,\n\n build(): void {\n // Phase 1 — record. Each task creates its passes; `createRenderPass`\n // appends each new pass to the currently-recording task's `_passes` list.\n for (let i = 0; i < fg._tasks.length; i++) {\n const task = fg._tasks[i]!;\n task._passes.length = 0;\n fg._currentProcessedTask = task;\n task.record();\n fg._currentProcessedTask = null;\n }\n // Phase 2 — initialize. Runs after every task has finished recording\n // so passes can safely reference resources allocated by other tasks\n // (e.g. RTTs whose textures are wired up by a later task's `record`).\n for (let i = 0; i < fg._tasks.length; i++) {\n const passes = fg._tasks[i]!._passes;\n for (let j = 0; j < passes.length; j++) {\n passes[j]!._initialize();\n }\n }\n },\n\n execute(): number {\n let drawCalls = 0;\n for (const task of fg._tasks) {\n if (task.execute) {\n drawCalls += task.execute();\n } else {\n for (const pass of task._passes) {\n drawCalls += pass._execute();\n }\n }\n }\n return drawCalls;\n },\n\n dispose(): void {\n for (const task of fg._tasks) {\n task.dispose();\n }\n fg._tasks.length = 0;\n fg._currentProcessedTask = null;\n },\n };\n return fg;\n}\n\n/** Add a task at the END of execute order. */\nexport function _appendTask(fg: FrameGraph, task: Task): void {\n fg._tasks.push(task);\n}\n","/**\n * RenderTarget — describes and owns the GPU textures for a render pass.\n *\n * A RenderTarget is a pure-state description of color + depth/stencil\n * attachments. GPU textures are allocated during the frame graph build\n * phase (`buildRenderTarget`) and freed on dispose or rebuild.\n *\n * `createRenderTargetTexture` (texture/rtt.ts) eagerly allocates and marks\n * the target so subsequent build calls are no-ops, allowing the color or depth\n * view to be wired as a sampled texture before the frame graph is built.\n */\n\nimport type { EngineContext } from \"./engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\n\n/** Signature of a render target's attachment set — enough to key a GPURenderPipeline. */\nexport interface RenderTargetSignature {\n /** @internal */\n readonly _colorFormat?: GPUTextureFormat;\n /** @internal */\n readonly _depthStencilFormat?: GPUTextureFormat;\n /** @internal Depth compare for this target. Defaults to reverse-Z `\"greater-equal\"`. Shadow-map targets use standard-Z `\"less-equal\"`. */\n readonly _depthCompare?: GPUCompareFunction;\n /** @internal */\n readonly _sampleCount: number;\n /** When true, the projection matrix's Y is flipped (offscreen RTT — see writePassSceneUBO).\n * Pipelines must invert frontFace to keep back-face culling correct. */\n /** @internal */\n readonly _flipY?: boolean;\n /** @internal Internal per-task refraction texture shared by transmissive material bindings. */\n readonly _transmissionTexture?: Texture2D | null;\n}\n\n/** Description of a render target — what to create, not the GPU objects themselves. */\nexport const REVERSE_DEPTH_COMPARE = \"greater-equal\" as GPUCompareFunction;\n\n/** Describes a render target — what attachments to create, not the GPU objects\n * themselves. GPU textures are allocated later by `buildRenderTarget`. */\nexport interface RenderTargetDescriptor {\n label?: string;\n colorFormat?: GPUTextureFormat;\n depthStencilFormat?: GPUTextureFormat;\n /** @internal Depth clear value. Defaults to reverse-Z far depth `0`. Shadow-map targets use standard-Z far depth `1`. */\n _depthClearValue?: number;\n /** @internal Depth compare for pipelines targeting this RT. Defaults to reverse-Z `\"greater-equal\"`. */\n _depthCompare?: GPUCompareFunction;\n sampleCount: number;\n /** 'canvas' means match the canvas pixel size. Otherwise explicit pixels. */\n size: \"canvas\" | { width: number; height: number };\n /** If true, the color attachment resolves to the swapchain texture. The RT still\n * owns the MSAA texture (when sampleCount \\> 1) and the depth texture; only the\n * final color is the swapchain view, acquired per frame and patched in at execute\n * time. With sampleCount === 1 the RT owns no color texture (the swap view is the\n * color attachment directly). */\n resolveToSwapchain?: boolean;\n /** Override projection Y-flip. Defaults to true for offscreen targets and false for swapchain targets. */\n flipY?: boolean;\n}\n\n/** Stringified signature used to key pipelines against a render target's attachment set. */\nexport function targetSignatureKey(desc: RenderTargetSignature): string {\n return `${desc._colorFormat ?? \"-\"}|${desc._depthStencilFormat ?? \"-\"}|${desc._depthCompare ?? \"\"}|${desc._sampleCount}|${desc._flipY ? \"y\" : \"\"}`;\n}\n\n/** Allocated GPU state for a render target. */\nexport interface RenderTarget {\n /** @internal */\n readonly _descriptor: RenderTargetDescriptor;\n /** @internal */\n _colorTexture: GPUTexture | null;\n /** @internal */\n _colorView: GPUTextureView | null;\n /** @internal */\n _depthTexture: GPUTexture | null;\n /** @internal */\n _depthView: GPUTextureView | null;\n /** @internal */\n _width: number;\n /** @internal */\n _height: number;\n /** True when textures were allocated eagerly (before frame graph build) —\n * `buildRenderTarget` becomes a no-op so existing GPUTexture handles\n * (e.g. exposed as SampledTexture) stay valid. */\n /** @internal */\n _eager?: boolean;\n}\n\n/** Create a render target descriptor (GPU textures allocated by `buildRenderTarget`). */\nexport function createRenderTarget(descriptor: RenderTargetDescriptor): RenderTarget {\n return {\n _descriptor: descriptor,\n _colorTexture: null,\n _colorView: null,\n _depthTexture: null,\n _depthView: null,\n _width: 0,\n _height: 0,\n };\n}\n\n/** Allocate GPU textures for the render target. Idempotent for eager targets.\n * For swapchain-resolved targets the color texture is only allocated when\n * sampleCount \\> 1 (MSAA texture used as color attachment, swap view used as\n * resolve target); with sampleCount === 1 the swap view is the color attachment\n * directly so no color texture is owned. Depth is always owned by the RT. */\nexport function buildRenderTarget(rt: RenderTarget, engine: EngineContext): void {\n if (rt._eager) {\n return;\n }\n disposeRenderTarget(rt);\n\n const desc = rt._descriptor;\n const { width, height } = resolveSize(desc, engine);\n rt._width = width;\n rt._height = height;\n\n const device = engine._device;\n const allocColor = !!desc.colorFormat && (!desc.resolveToSwapchain || desc.sampleCount > 1);\n\n if (allocColor) {\n rt._colorTexture = device.createTexture({\n label: desc.label,\n size: { width, height },\n format: desc.colorFormat!,\n sampleCount: desc.sampleCount,\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC,\n });\n rt._colorView = rt._colorTexture.createView();\n }\n\n if (desc.depthStencilFormat) {\n rt._depthTexture = device.createTexture({\n label: desc.label,\n size: { width, height },\n format: desc.depthStencilFormat,\n sampleCount: desc.sampleCount,\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n });\n rt._depthView = rt._depthTexture.createView();\n }\n}\n\n/** Free GPU textures owned by the render target. */\nexport function disposeRenderTarget(rt: RenderTarget): void {\n if (rt._colorTexture) {\n rt._colorTexture.destroy();\n rt._colorTexture = null;\n rt._colorView = null;\n }\n if (rt._depthTexture) {\n rt._depthTexture.destroy();\n rt._depthTexture = null;\n rt._depthView = null;\n }\n rt._width = 0;\n rt._height = 0;\n}\n\nfunction resolveSize(desc: RenderTargetDescriptor, engine: EngineContext): { width: number; height: number } {\n if (desc.size === \"canvas\") {\n return { width: engine.canvas.width, height: engine.canvas.height };\n }\n return desc.size;\n}\n","/** Multiply a[aOff..+16] * b[bOff..+16] into dst[dOff..+16] (fully unrolled, zero allocation). */\nexport function mat4MultiplyInto(dst: Float32Array, d: number, a: Float32Array, i: number, b: Float32Array, j: number): void {\n const a0 = a[i]!,\n a1 = a[i + 1]!,\n a2 = a[i + 2]!,\n a3 = a[i + 3]!;\n const a4 = a[i + 4]!,\n a5 = a[i + 5]!,\n a6 = a[i + 6]!,\n a7 = a[i + 7]!;\n const a8 = a[i + 8]!,\n a9 = a[i + 9]!,\n a10 = a[i + 10]!,\n a11 = a[i + 11]!;\n const a12 = a[i + 12]!,\n a13 = a[i + 13]!,\n a14 = a[i + 14]!,\n a15 = a[i + 15]!;\n let b0 = b[j]!,\n b1 = b[j + 1]!,\n b2 = b[j + 2]!,\n b3 = b[j + 3]!;\n dst[d] = a0 * b0 + a4 * b1 + a8 * b2 + a12 * b3;\n dst[d + 1] = a1 * b0 + a5 * b1 + a9 * b2 + a13 * b3;\n dst[d + 2] = a2 * b0 + a6 * b1 + a10 * b2 + a14 * b3;\n dst[d + 3] = a3 * b0 + a7 * b1 + a11 * b2 + a15 * b3;\n b0 = b[j + 4]!;\n b1 = b[j + 5]!;\n b2 = b[j + 6]!;\n b3 = b[j + 7]!;\n dst[d + 4] = a0 * b0 + a4 * b1 + a8 * b2 + a12 * b3;\n dst[d + 5] = a1 * b0 + a5 * b1 + a9 * b2 + a13 * b3;\n dst[d + 6] = a2 * b0 + a6 * b1 + a10 * b2 + a14 * b3;\n dst[d + 7] = a3 * b0 + a7 * b1 + a11 * b2 + a15 * b3;\n b0 = b[j + 8]!;\n b1 = b[j + 9]!;\n b2 = b[j + 10]!;\n b3 = b[j + 11]!;\n dst[d + 8] = a0 * b0 + a4 * b1 + a8 * b2 + a12 * b3;\n dst[d + 9] = a1 * b0 + a5 * b1 + a9 * b2 + a13 * b3;\n dst[d + 10] = a2 * b0 + a6 * b1 + a10 * b2 + a14 * b3;\n dst[d + 11] = a3 * b0 + a7 * b1 + a11 * b2 + a15 * b3;\n b0 = b[j + 12]!;\n b1 = b[j + 13]!;\n b2 = b[j + 14]!;\n b3 = b[j + 15]!;\n dst[d + 12] = a0 * b0 + a4 * b1 + a8 * b2 + a12 * b3;\n dst[d + 13] = a1 * b0 + a5 * b1 + a9 * b2 + a13 * b3;\n dst[d + 14] = a2 * b0 + a6 * b1 + a10 * b2 + a14 * b3;\n dst[d + 15] = a3 * b0 + a7 * b1 + a11 * b2 + a15 * b3;\n}\n","/** Write a reverse-Z perspective projection into `out` without allocating.\n * WebGPU clip-space depth is [0, 1]; this maps `near -> 1` and `far -> 0`. */\nexport function mat4PerspectiveLHToRef(out: Float32Array, fov: number, aspect: number, near: number, far: number): void {\n const tan = 1 / Math.tan(fov * 0.5);\n const range = far - near;\n out[0] = tan / aspect;\n out[5] = tan;\n out[10] = -near / range;\n out[11] = 1;\n out[14] = (far * near) / range;\n}\n","import type { Vec3, Mat4 } from \"../math/types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\nimport { mat4PerspectiveLHToRef } from \"../math/mat4-perspective-lh-to-ref.js\";\n\n/** Minimal camera contract — any camera that can provide view/projection matrices.\n * Both ArcRotateCamera and FreeCamera implement this interface.\n * Pure state, no scene knowledge (pillar 4b). */\nexport interface Camera {\n fov: number;\n nearPlane: number;\n farPlane: number;\n viewport?: NormalizedViewport;\n children: SceneNode[];\n readonly worldMatrix: Mat4;\n readonly worldMatrixVersion: number;\n /** @internal Cached view matrix + version. */\n _viewCache?: Float32Array;\n /** @internal */\n _viewVer?: number;\n /** @internal Cached projection matrix + version + aspect. */\n _projCache?: Float32Array;\n /** @internal */\n _projVer?: number;\n /** @internal */\n _projAspect?: number;\n /** @internal Cached view-projection matrix + version + aspect. */\n _vpCache?: Float32Array;\n /** @internal */\n _vpVer?: number;\n /** @internal */\n _vpAspect?: number;\n}\n\n/** Babylon-compatible normalized camera viewport. x/y/width/height are fractions of the render target. */\nexport interface NormalizedViewport {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Compute the view matrix for a camera. Cached per worldMatrixVersion. */\nexport function getViewMatrix(camera: Camera): Mat4 {\n const ver = camera.worldMatrixVersion;\n if (camera._viewVer === ver && camera._viewCache) {\n return camera._viewCache as unknown as Mat4;\n }\n if (!camera._viewCache) {\n camera._viewCache = new Float32Array(16);\n }\n const v = camera._viewCache;\n const w = camera.worldMatrix;\n v[0] = w[0]!;\n v[1] = w[4]!;\n v[2] = w[8]!;\n v[3] = 0;\n v[4] = w[1]!;\n v[5] = w[5]!;\n v[6] = w[9]!;\n v[7] = 0;\n v[8] = w[2]!;\n v[9] = w[6]!;\n v[10] = w[10]!;\n v[11] = 0;\n v[12] = -(w[0]! * w[12]! + w[1]! * w[13]! + w[2]! * w[14]!);\n v[13] = -(w[4]! * w[12]! + w[5]! * w[13]! + w[6]! * w[14]!);\n v[14] = -(w[8]! * w[12]! + w[9]! * w[13]! + w[10]! * w[14]!);\n v[15] = 1;\n camera._viewVer = ver;\n return v as unknown as Mat4;\n}\n\n/** Compute the projection matrix for a camera. Cached per worldMatrixVersion + aspect. */\nexport function getProjectionMatrix(camera: Camera, aspectRatio: number): Mat4 {\n const ver = camera.worldMatrixVersion;\n if (camera._projVer === ver && camera._projAspect === aspectRatio && camera._projCache) {\n return camera._projCache as unknown as Mat4;\n }\n if (!camera._projCache) {\n camera._projCache = new Float32Array(16);\n }\n mat4PerspectiveLHToRef(camera._projCache, camera.fov, aspectRatio, camera.nearPlane, camera.farPlane);\n camera._projVer = ver;\n camera._projAspect = aspectRatio;\n return camera._projCache as unknown as Mat4;\n}\n\n/** Compute the view-projection matrix for a camera. Cached per worldMatrixVersion + aspect. */\nexport function getViewProjectionMatrix(camera: Camera, aspectRatio: number): Mat4 {\n const ver = camera.worldMatrixVersion;\n if (camera._vpVer === ver && camera._vpAspect === aspectRatio && camera._vpCache) {\n return camera._vpCache as unknown as Mat4;\n }\n if (!camera._vpCache) {\n camera._vpCache = new Float32Array(16);\n }\n mat4MultiplyInto(camera._vpCache, 0, getProjectionMatrix(camera, aspectRatio), 0, getViewMatrix(camera), 0);\n camera._vpVer = ver;\n camera._vpAspect = aspectRatio;\n return camera._vpCache as unknown as Mat4;\n}\n\n/** Get the world-space position of a camera. */\nexport function getCameraPosition(camera: Camera): Vec3 {\n const w = camera.worldMatrix;\n return { x: w[12]!, y: w[13]!, z: w[14]! };\n}\n\n/** Returns the render-target aspect ratio adjusted for the camera's normalized viewport, or the raw ratio if none. */\nexport function getEffectiveAspectRatio(camera: Camera | null | undefined, targetWidth: number, targetHeight: number): number {\n const v = camera?.viewport;\n return (targetWidth / targetHeight) * (v ? v.width / v.height : 1);\n}\n","/** Scene helpers — shared utilities for renderable builders.\n *\n * Centralises patterns that PBR and Standard pipelines previously duplicated:\n * scene BGL creation, mesh world-matrix updates, and pipeline descriptors. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { REVERSE_DEPTH_COMPARE } from \"../engine/render-target.js\";\n\n// ── Scene bind group layout (group 0) ────────────────────────────\n\nlet _cachedSceneBGL: GPUBindGroupLayout | null = null;\nlet _cachedDevice: GPUDevice | null = null;\n\n/** Shared scene bind group layout:\n * binding 0: per-pass SceneUniforms UBO\n * binding 1: scene-owned LightsUniforms UBO */\nexport function getSceneBindGroupLayout(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n if (_cachedSceneBGL && _cachedDevice === device) {\n return _cachedSceneBGL;\n }\n _cachedDevice = device;\n _cachedSceneBGL = device.createBindGroupLayout({\n label: \"scene\",\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n ],\n });\n return _cachedSceneBGL;\n}\n\n/** Clear the cached scene BGL (called on disposal / device change). */\nexport function clearSceneBGLCache(): void {\n _cachedSceneBGL = null;\n _cachedDevice = null;\n}\n\n// ── Mesh world-matrix UBO update ─────────────────────────────────\n\n/** Packet-style record for world-matrix dirty checking. */\nexport interface WorldMatrixPacket {\n readonly mesh: Mesh;\n readonly meshUBO: GPUBuffer;\n /** @internal */\n _lastWorldVersion: number;\n}\n\n/** Write world matrices to UBOs for packets whose version has changed. */\nexport function updateWorldMatrixUBOs(engine: EngineContext, packets: WorldMatrixPacket[]): void {\n const device = engine._device;\n for (const p of packets) {\n const wm = p.mesh.worldMatrix;\n if (p.mesh.worldMatrixVersion !== p._lastWorldVersion) {\n device.queue.writeBuffer(p.meshUBO, 0, wm as unknown as Float32Array<ArrayBuffer>);\n p._lastWorldVersion = p.mesh.worldMatrixVersion;\n }\n }\n}\n\n// ── Pipeline descriptor builder ──────────────────────────────────\n\nexport interface PipelineDescriptorOpts {\n /** @internal */\n _label: string;\n /** @internal */\n _engine: EngineContext;\n /** @internal */\n _bgls: GPUBindGroupLayout[];\n /** @internal */\n _vertModule: GPUShaderModule;\n /** @internal */\n _fragModule: GPUShaderModule;\n /** @internal */\n _vertexBuffers: GPUVertexBufferLayout[];\n /** @internal */\n _format: GPUTextureFormat;\n /** @internal Depth-stencil format. Default: `\"depth24plus-stencil8\"` (matches the engine's default RT). */\n _depthStencilFormat?: GPUTextureFormat;\n /** @internal Depth compare. Default: reverse-Z `\"greater-equal\"`. */\n _depthCompare?: GPUCompareFunction;\n /** @internal */\n _msaaSamples: number;\n /** @internal */\n _depthWriteEnabled?: boolean;\n /** @internal */\n _cullMode?: GPUCullMode;\n /** @internal */\n _blend?: GPUBlendState;\n /** @internal When true, build with `frontFace: \"cw\"` (offscreen RTT with Y-flipped projection). */\n _flipY?: boolean;\n}\n\n/** Build a render pipeline descriptor with the engine's default reverse-Z state:\n * depth24plus-stencil8, greater-equal, triangle-list, ccw front face (cw if flipY). */\nexport function createDefaultPipelineDescriptor(opts: PipelineDescriptorOpts): GPURenderPipelineDescriptor {\n const target: GPUColorTargetState = opts._blend ? { format: opts._format, blend: opts._blend } : { format: opts._format };\n return {\n label: opts._label,\n layout: opts._engine._device.createPipelineLayout({ bindGroupLayouts: opts._bgls }),\n vertex: { module: opts._vertModule, entryPoint: \"main\", buffers: opts._vertexBuffers },\n fragment: { module: opts._fragModule, entryPoint: \"main\", targets: [target] },\n depthStencil: {\n format: opts._depthStencilFormat ?? \"depth24plus-stencil8\",\n depthCompare: opts._depthCompare ?? REVERSE_DEPTH_COMPARE,\n depthWriteEnabled: opts._depthWriteEnabled ?? true,\n },\n multisample: { count: opts._msaaSamples },\n primitive: { topology: \"triangle-list\", cullMode: opts._cullMode ?? \"back\", frontFace: opts._flipY ? \"cw\" : \"ccw\" },\n };\n}\n","import type { EngineContext } from \"../engine/engine.js\";\n\n/** Round `n` up to the nearest multiple of `to` (must be a positive integer). */\nexport function align(n: number, to: number): number {\n return (n + to - 1) & ~(to - 1);\n}\n\n/** Create a UNIFORM + COPY_DST buffer and write initial data. Size is aligned to 16 bytes. */\nexport function createUniformBuffer(engine: EngineContext, data: ArrayBufferView, label?: string): GPUBuffer {\n const device = engine._device;\n const buf = device.createBuffer({\n label,\n size: align(data.byteLength, 16),\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n device.queue.writeBuffer(buf, 0, data.buffer as ArrayBuffer, data.byteOffset, data.byteLength);\n return buf;\n}\n\n/** Create an empty UNIFORM + COPY_DST buffer. `byteLength` is aligned to 16 bytes. */\nexport function createEmptyUniformBuffer(engine: EngineContext, byteLength: number, label?: string): GPUBuffer {\n return engine._device.createBuffer({\n label,\n size: align(byteLength, 16),\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n}\n\n/** Create a mapped-at-creation buffer (for VERTEX/INDEX/STORAGE uploads). Size is padded to ≥4 and 4-byte aligned. */\nexport function createMappedBuffer(engine: EngineContext, data: ArrayBufferView, usage: GPUBufferUsageFlags): GPUBuffer {\n const size = align(Math.max(data.byteLength, 4), 4);\n const buf = engine._device.createBuffer({\n size,\n usage: usage | GPUBufferUsage.COPY_DST,\n mappedAtCreation: true,\n });\n new Uint8Array(buf.getMappedRange()).set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\n buf.unmap();\n return buf;\n}\n","/** Total size of SceneUniforms in bytes (must equal shaders/scene-uniforms.wgsl). */\nexport const SCENE_UBO_BYTES = 368;\n","/** Light extension types and registry.\n *\n * Each light type provides pipeline integration callbacks.\n * PBR + Standard both consume the shared lights UBO (render/lights-ubo.ts);\n * light type is encoded in vLightData.w (1=dir, 2=spot, 3=hemi, other=point). */\n\nimport type { Mat4 } from \"../math/types.js\";\nimport type { IWorldMatrixProvider, IParentable } from \"../scene/parentable.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\n\n/** Shared base for all light types.\n * Provides pipeline integration callbacks so render pipelines are light-agnostic. */\nexport interface LightBase extends IWorldMatrixProvider, IParentable {\n readonly lightType: string;\n children: SceneNode[];\n /** Mesh IDs excluded from this light. If set, these meshes are NOT lit by this light. */\n excludedMeshIds?: ReadonlySet<string>;\n /** If non-empty, ONLY these mesh IDs are lit by this light. Takes priority over excludedMeshIds. */\n includedOnlyMeshIds?: ReadonlySet<string>;\n /** Shadow generator attached to this light. Set this to make the light cast shadows. */\n shadowGenerator?: import(\"../shadow/shadow-generator.js\").ShadowGenerator;\n\n parent: IWorldMatrixProvider | null;\n readonly worldMatrix: Mat4;\n readonly worldMatrixVersion: number;\n /** @internal */\n readonly _writeLightUbo?: ((data: Float32Array, offset: number) => void) | undefined;\n /** @internal Monotonically increasing version — bumped when any UBO-relevant property changes. */\n readonly _lightVersion: number;\n}\n\n/** Maximum number of scene lights packed into the shared lights UBO.\n * Babylon.js defaults to 4 lights per material; Babylon Lite's cap is scene-wide\n * because all materials index the same group-0 lights buffer. Raise via\n * `setMaxLights(n)` before creating any scene / loading any asset that needs\n * more lights (e.g. the glTF loader auto-raises this when an asset declares\n * more KHR_lights_punctual lights than the current cap). */\nexport let MAX_LIGHTS = 16;\n\n/** Raise (or lower) the maximum number of scene lights in the shared lights UBO.\n * Must be called BEFORE scene pipelines are compiled — existing pipelines\n * and UBOs bake the cap into their WGSL/layout. */\nexport function setMaxLights(n: number): void {\n if (!Number.isFinite(n) || n < 1) {\n throw new Error(`setMaxLights: expected positive integer, got ${n}`);\n }\n MAX_LIGHTS = n | 0;\n}\n\n/** Bytes per light entry in the lights UBO (4 × vec4 = 64 bytes). */\nexport const LIGHT_ENTRY_FLOATS = 16;\n","/** Shared lights UBO helpers — used by both Standard and PBR pipelines.\n *\n * UBO layout: 16-byte header (u32 count + 3×u32 padding) followed by\n * up to MAX_LIGHTS × LightEntry (4 × vec4 = 64 bytes each).\n * Default total: 16 + 16 × 64 = 1040 bytes. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { LightBase } from \"../light/types.js\";\nimport { MAX_LIGHTS, LIGHT_ENTRY_FLOATS } from \"../light/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { UboField } from \"../shader/fragment-types.js\";\n\n/** Reusable typed-array pair for writing a u32 count as its float32 bit pattern.\n * Avoids allocating a Uint32Array view on every fillLightsData call. */\nconst _countU32 = new Uint32Array(1);\nconst _countF32 = new Float32Array(_countU32.buffer);\n\nconst MSH_LIGHT_INDEX_WORD_OFFSET = 20; // world matrix (16 u32) + lc (1 u32) + uniform padding (3 u32)\n\nfunction meshLightIndexVec4Count(): number {\n return Math.ceil(MAX_LIGHTS / 4);\n}\n\n/** @internal\n * Total byte size of the lights UBO (header + MAX_LIGHTS entries).\n * Recomputed dynamically because MAX_LIGHTS is mutable via `setMaxLights`. */\nexport function getLightsUboSize(): number {\n return 16 + MAX_LIGHTS * LIGHT_ENTRY_FLOATS * 4;\n}\n\n/** Compute a composite version from all lights (sum of _lightVersion).\n * Returns 0 for lights without version tracking (always refresh). */\nfunction computeLightsVersion(lights: readonly LightBase[]): number {\n let v = 0;\n for (const light of lights) {\n v += light._lightVersion ?? 0;\n }\n return v;\n}\n\n/** Fill a Float32Array with standard light data. Reused by create and refresh paths. */\nfunction fillLightsData(data: Float32Array, lights: readonly LightBase[]): void {\n data.fill(0);\n let count = 0;\n const headerFloats = 4; // count + 3 padding\n for (const light of lights) {\n if (count >= MAX_LIGHTS) {\n break;\n }\n if (!light._writeLightUbo) {\n continue;\n }\n light._writeLightUbo(data, headerFloats + count * LIGHT_ENTRY_FLOATS);\n count++;\n }\n // Write count as u32 bit pattern into the first float slot (zero allocation)\n _countU32[0] = count;\n data[0] = _countF32[0]!;\n}\n\n/** @internal */\nexport interface SceneLightGpuState {\n /** @internal */\n _buffer: GPUBuffer;\n /** @internal */\n _scratch: Float32Array;\n /** @internal */\n _version: number;\n /** @internal */\n _lightCount: number;\n /** @internal */\n _byteSize: number;\n}\n\n/** @internal */\nexport function ensureSceneLightState(engine: EngineContext, scene: SceneContext): SceneLightGpuState {\n let state = scene._lightGpuState;\n const byteSize = getLightsUboSize();\n if (state && state._byteSize === byteSize) {\n return state;\n }\n const registerDisposer = !state;\n state?._buffer.destroy();\n const scratch = new Float32Array(byteSize / 4);\n fillLightsData(scratch, scene.lights);\n state = {\n _buffer: createUniformBuffer(engine, scratch),\n _scratch: scratch,\n _version: computeLightsVersion(scene.lights),\n _lightCount: scene.lights.length,\n _byteSize: byteSize,\n };\n scene._lightGpuState = state;\n if (registerDisposer) {\n scene._disposables.push(() => {\n scene._lightGpuState?._buffer.destroy();\n scene._lightGpuState = undefined;\n });\n }\n return state;\n}\n\n/** @internal */\nexport function refreshSceneLightsUBO(engine: EngineContext, scene: SceneContext): GPUBuffer {\n const state = ensureSceneLightState(engine, scene);\n const version = computeLightsVersion(scene.lights);\n if (version !== state._version || scene.lights.length !== state._lightCount) {\n state._version = version;\n state._lightCount = scene.lights.length;\n fillLightsData(state._scratch, scene.lights);\n engine._device.queue.writeBuffer(state._buffer, 0, state._scratch as Float32Array<ArrayBuffer>);\n }\n return state._buffer;\n}\n\n/** @internal */\nexport function appendMeshLightUboFields(fields: UboField[]): void {\n fields.push({ _name: \"lc\", _type: \"u32\" });\n fields.push({ _name: \"li\", _type: `array<vec4<u32>, ${meshLightIndexVec4Count()}>` });\n}\n\n/** @internal */\nexport function meshLightIndexWGSL(meshVar: string, functionName = \"mli\"): string {\n return `fn ${functionName}(i: u32) -> u32 { return ${meshVar}.li[i / 4u][i % 4u]; }`;\n}\n\nfunction affectsMesh(light: LightBase, mesh: Mesh): boolean {\n const meshId = mesh.id;\n const included = light.includedOnlyMeshIds;\n if (included?.size) {\n return !!meshId && included.has(meshId);\n }\n return !meshId || !light.excludedMeshIds?.has(meshId);\n}\n\n/** @internal\n * Writes mesh light indices when data is provided. Return encoding:\n * 0 = no lights, `N > 0` = one light at index N - 1, `N < 0` = -affectedCount. */\nexport function writeMeshLightSelection(mesh: Mesh, lights: readonly LightBase[], data?: Float32Array): number {\n const u32 = data ? new Uint32Array(data.buffer, data.byteOffset, data.byteLength / 4) : null;\n let count = 0;\n let single = -1;\n let pi = 0;\n for (const light of lights) {\n if (pi >= MAX_LIGHTS) {\n break;\n }\n if (!light._writeLightUbo) {\n continue;\n }\n if (affectsMesh(light, mesh)) {\n single = pi;\n if (u32) {\n u32[MSH_LIGHT_INDEX_WORD_OFFSET + count] = pi;\n }\n count++;\n }\n pi++;\n }\n if (u32) {\n u32[16] = count;\n for (let i = count; i < MAX_LIGHTS; i++) {\n u32[MSH_LIGHT_INDEX_WORD_OFFSET + i] = 0;\n }\n }\n return count === 1 ? single + 1 : -count;\n}\n","/**\n * RenderTask — a frame-graph task that records a single `RenderPass`,\n * binds the scene's `RenderTarget`, and draws renderables into it.\n *\n * - `record()` builds bucketed `DrawBinding` lists from `_renderables`\n * (opaque / direct / transparent), sorts opaque + direct by\n * `order`, then creates a `RenderPass` wired to the task's render target.\n * The pass owns its\n * `GPURenderPassDescriptor` and the per-pass-encoder body lives in a\n * closure passed to `setRenderPassExecuteFunc`.\n * - Before `RenderPass._execute()` begins the GPU pass: writes the scene UBO, refreshes lights, updates\n * per-binding UBOs, mirrors live `scene.clearColor` + `clr` onto the\n * render pass. Shared task execution then calls `_execute()`. The\n * `RenderPass` itself patches the swapchain view + clearColor + loadOp\n * and brackets the body with `beginRenderPass` / `end`.\n *\n * Renderable population:\n * - Explicit: push into `_renderables` directly, or `addMesh(mesh, opts)`\n * which builds a (mesh, material) Renderable at `record()` time.\n * - Auto scene mirror: when `_renderables` is empty at record() time, copy the\n * scene's renderables. Re-sync happens automatically when the scene's\n * `_renderableVersion` changes between frames (mesh add/remove, material swap).\n *\n * Swapchain mode is detected by `rt.descriptor.resolveToSwapchain` and is\n * handled inside the `RenderPass` (the swap view is patched into the cached\n * descriptor per frame, as either the resolveTarget for MSAA RTs or the\n * direct color view otherwise). `clr: false` switches color + depth `loadOp`\n * to `\"load\"` so multiple scenes can share the swapchain in one frame\n * (e.g., a 3D scene + a UI overlay scene).\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { _vis } from \"../engine/engine.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { Renderable, DrawBinding, DrawUpdateContext } from \"../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Material } from \"../material/material.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { buildRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { getViewProjectionMatrix, getViewMatrix } from \"../camera/camera.js\";\nimport { getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { createEmptyUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { SCENE_UBO_BYTES } from \"../shader/scene-uniforms-size.js\";\nimport { ensureSceneLightState, refreshSceneLightsUBO } from \"../render/lights-ubo.js\";\nimport type { Task } from \"./task.js\";\n\n/** Configuration for `createRenderTask`: render target, clear state, optional camera override, and transmission settings. */\nexport interface RenderTaskConfig {\n name: string;\n /** TODO: rt should not live in this config long-term. Until texture\n * management is virtualized, callers must provide the concrete target; once\n * virtualized, the task should create/manage its own render target. */\n rt: RenderTarget;\n /** Background clear color. May be mutated frame-to-frame. */\n clrColor?: GPUColorDict;\n /** When true, controls color + depth `loadOp` (\"clear\"). When false, use \"load\"\n * so this pass overlays previous content (UI overlays, second scene, etc.). */\n clr?: boolean;\n /** Per-pass camera override. Null/undefined uses `scene.camera`. */\n cam?: Camera | null;\n /** Use canvas dimensions, not render-target dimensions, for this pass's scene UBO aspect. */\n cs?: boolean;\n /** Scene-texture transmission settings. `copyCount: 0` copies before every transmissive draw.\n * `generateMipmaps: false` allocates only mip 0 for the refraction texture and skips mip generation. */\n transmission?: { copyCount?: number; generateMipmaps?: boolean };\n}\n\n/** A frame-graph task that records a single `RenderPass`, binds the scene's `RenderTarget`, and draws renderables into it. */\nexport interface RenderTask extends Task {\n readonly name: string;\n /** Render tasks are scene-bound because they consume scene camera, lights, and renderables. */\n readonly scene: SceneContext;\n /** Live task configuration. Mutating `clr` or `clrColor` affects subsequent frames. */\n /** @internal */\n readonly _config: RenderTaskConfig;\n /** @internal */\n _autoFromScene: boolean;\n\n /** Source-of-truth renderables. Bucketed binding lists below are derived from\n * this list at `record()` (or re-sync when auto-filled and `_renderableVersion` changes). */\n /** @internal */\n _renderables: Renderable[];\n /** @internal */\n _opaqueBindings: DrawBinding[];\n /** @internal */\n _directBindings: DrawBinding[];\n /** @internal */\n _transparentBindings: DrawBinding[];\n /** Cached opaque render bundle. Invalidated by renderable list mutations\n * (`_lastVersion`) and visibility changes (`_lastVis`). */\n /** @internal */\n _opaqueBundles: GPURenderBundle[];\n /** @internal */\n _lastVersion: number;\n /** @internal */\n _lastVis: number;\n\n /** @internal */\n _renderPassDescriptor: GPURenderPassDescriptor;\n /** @internal */\n _colorAttachment: GPURenderPassColorAttachment;\n\n /** Per-task scene UBO + bind group. Created eagerly in createRenderTask\n * so renderables can reference `_sceneBG` at `bind()` time. Written each\n * frame by `writePassSceneUBO`. Destroyed in `dispose()`. */\n /** @internal */\n _sceneUBO: GPUBuffer;\n /** @internal */\n _sceneBG: GPUBindGroup;\n /** @internal */\n _lightsUBO: GPUBuffer;\n /** @internal */\n _suData: Float32Array;\n /** @internal */\n _su: unknown[];\n /** Optional transmission-enabled execute path: copies the scene texture for refraction and draws transmissive\n * renderables. Present only when the task was configured with `transmission`. Returns the number of draw calls issued. */\n /** @internal */\n _executeWithTransmission?(sampleCount: number): number;\n /** @internal */\n _targetSignature: RenderTargetSignature;\n\n /** Add a mesh to this task's explicit render list with an optional per-pass material override.\n * Resolved at `record()` time via `material._buildGroup._rebuildSingle`,\n * so the mesh's material family must already have been registered with\n * the scene (so its batch builder has run). */\n addMesh(mesh: Mesh, opts?: { material?: Material }): void;\n /** @internal */\n _pendingMeshes: { mesh: Mesh; material: Material }[];\n}\n\ninterface MutableDrawUpdateContext {\n targetWidth: number;\n targetHeight: number;\n _camera?: Camera | null;\n}\n\n/** Create a render pass task. GPU resources (target textures + descriptor)\n * are not allocated until `record()` runs (via `frameGraph.build()`).\n *\n * Swapchain-targeted tasks acquire the swap view per-frame at execute time. */\nexport function createRenderTask(config: RenderTaskConfig, engine: EngineContext, scene: SceneContext): RenderTask {\n const sc = scene as SceneContext;\n const rt = config.rt;\n config.clrColor ??= { r: 0.2, g: 0.2, b: 0.3, a: 1.0 };\n config.clr ??= true;\n const desc = rt._descriptor;\n // Offscreen RTTs usually need a Y-flipped projection so the result texture\n // samples upright when sourced by a downstream pass. Depth-only shadow maps\n // can override this to preserve shadow-sampler UV conventions.\n const targetSignature = {\n _colorFormat: desc.colorFormat,\n _depthStencilFormat: desc.depthStencilFormat,\n _depthCompare: desc._depthCompare,\n _sampleCount: desc.sampleCount ?? 1,\n _flipY: desc.flipY ?? desc.resolveToSwapchain !== true,\n };\n\n const sceneBGL = getSceneBindGroupLayout(engine);\n const sceneUBO = createEmptyUniformBuffer(engine, SCENE_UBO_BYTES);\n const lightsUBO = ensureSceneLightState(engine, sc)._buffer;\n const sceneBG = engine._device.createBindGroup({\n layout: sceneBGL,\n entries: [\n { binding: 0, resource: { buffer: sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const updateContext: MutableDrawUpdateContext = { targetWidth: 0, targetHeight: 0 };\n const task: RenderTask = {\n name: config.name,\n _config: config,\n engine: engine,\n scene: sc,\n _passes: [],\n _autoFromScene: false,\n _renderables: [],\n _opaqueBindings: [],\n _directBindings: [],\n _transparentBindings: [],\n _opaqueBundles: [],\n _lastVersion: -1,\n _lastVis: 0,\n _renderPassDescriptor: { colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _sceneUBO: sceneUBO,\n _sceneBG: sceneBG,\n _lightsUBO: lightsUBO,\n _suData: new Float32Array(SCENE_UBO_BYTES / 4),\n _su: [],\n _targetSignature: targetSignature,\n _pendingMeshes: [],\n addMesh(mesh, opts) {\n const material = opts?.material ?? mesh.material;\n if (!material) {\n return;\n }\n task._pendingMeshes.push({ mesh, material });\n },\n record(): void {\n if (task._autoFromScene) {\n task._renderables.length = 0;\n }\n resolvePendingMeshes(task, sc);\n task._autoFromScene = task._renderables.length === 0;\n if (task._autoFromScene) {\n task._renderables.push(...sc._renderables);\n }\n buildRenderTarget(rt, engine);\n updateContext.targetWidth = rt._width;\n updateContext.targetHeight = rt._height;\n refreshTaskSceneBindGroup(task, engine);\n buildBindings(task, engine, targetSignature);\n buildRenderPassDescriptor(task, rt);\n },\n execute(): number {\n return executePass(task, engine, targetSignature, updateContext);\n },\n dispose(): void {\n task._passes.length = 0;\n disposeRenderTarget(rt);\n task._opaqueBindings.length = 0;\n task._directBindings.length = 0;\n task._transparentBindings.length = 0;\n task._renderables.length = 0;\n task._opaqueBundles.length = 0;\n task._sceneUBO.destroy();\n },\n };\n return task;\n}\n\n/** Remove a mesh from this task's renderable + binding lists. Idempotent. */\nexport function removeMeshFromTask(task: RenderTask, mesh: object): void {\n let removed = false;\n for (let i = task._renderables.length - 1; i >= 0; i--) {\n if (task._renderables[i]!.mesh === mesh) {\n task._renderables.splice(i, 1);\n removed = true;\n }\n }\n for (const arr of [task._opaqueBindings, task._directBindings, task._transparentBindings]) {\n for (let i = arr.length - 1; i >= 0; i--) {\n if (arr[i]!.renderable.mesh === mesh) {\n arr.splice(i, 1);\n removed = true;\n }\n }\n }\n if (removed) {\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction resolvePendingMeshes(task: RenderTask, sc: SceneContext): void {\n if (task._pendingMeshes.length === 0) {\n return;\n }\n for (const { mesh, material } of task._pendingMeshes) {\n const buildGroup = material._buildGroup;\n const rebuild = buildGroup?._rebuildSingle;\n if (!rebuild) {\n throw new Error();\n }\n const renderable = rebuild(sc, mesh, material);\n if (!task._renderables.includes(renderable)) {\n task._renderables.push(renderable);\n }\n }\n task._pendingMeshes.length = 0;\n}\n\n/** Per-frame back-to-front sort for transparent bindings using the active camera. */\nfunction sortTransparentBindings(task: RenderTask, camera: Camera | null | undefined): void {\n const arr = task._transparentBindings;\n if (arr.length <= 1 || !camera) {\n return;\n }\n const v = getViewMatrix(camera);\n for (const b of arr) {\n const wc = b.renderable._worldCenter;\n b._sortDistance = wc ? wc[0]! * v[2]! + wc[1]! * v[6]! + wc[2]! * v[10]! + v[14]! : 0;\n }\n arr.sort((a, b) => b._sortDistance! - a._sortDistance! || a.renderable.order - b.renderable.order);\n}\n\n/** (Re)bucket task._renderables into bound lists. */\nfunction buildBindings(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature): void {\n const opaque = task._opaqueBindings;\n const direct = task._directBindings;\n const transparent = task._transparentBindings;\n opaque.length = 0;\n direct.length = 0;\n transparent.length = 0;\n for (const r of task._renderables) {\n const binding = r.bind(eng, targetSignature);\n if (r.isTransparent || r._transmissive) {\n transparent.push(binding);\n } else if (r._direct) {\n direct.push(binding);\n } else {\n opaque.push(binding);\n }\n }\n opaque.sort((a, b) => a.renderable.order - b.renderable.order);\n direct.sort((a, b) => a.renderable.order - b.renderable.order);\n task._opaqueBundles.length = 0;\n task._lastVersion = (task.scene as SceneContext)._renderableVersion;\n}\n\nfunction buildRenderPassDescriptor(task: RenderTask, rt: RenderTarget): void {\n task._colorAttachment.view = rt._colorView!;\n task._renderPassDescriptor.colorAttachments = rt._colorView ? [task._colorAttachment] : [];\n\n const depthView = rt._depthView;\n let depthAttachment: GPURenderPassDepthStencilAttachment | null = null;\n if (depthView) {\n depthAttachment = {\n view: depthView,\n depthClearValue: rt._descriptor._depthClearValue ?? 0,\n depthLoadOp: \"clear\",\n depthStoreOp: \"store\",\n };\n if (rt._descriptor.depthStencilFormat?.includes(\"stencil\")) {\n depthAttachment.stencilClearValue = 0;\n depthAttachment.stencilLoadOp = \"clear\";\n depthAttachment.stencilStoreOp = \"store\";\n }\n }\n\n task._renderPassDescriptor.depthStencilAttachment = depthAttachment ?? undefined;\n}\n\nfunction prepareRenderTaskPass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): void {\n const sc = task.scene as SceneContext;\n // Auto-resync when the source scene mutates.\n if (task._autoFromScene && task._lastVersion !== sc._renderableVersion) {\n task._renderables.length = 0;\n task._renderables.push(...sc._renderables);\n buildBindings(task, eng, targetSignature);\n }\n\n // Pre-pass work — runs before beginRenderPass. Updates the task-owned scene\n // UBO, scene-wide lights UBO, and per-binding UBOs. The scene bind group may\n // also need a refresh (lights buffer can be resized when glTF lights\n // extension raises MAX_LIGHTS after this task was first recorded).\n refreshTaskSceneBindGroup(task, eng);\n const camera = task._config.cam ?? sc.camera;\n sc._clusteredLightUpdater?.(camera, context.targetWidth, context.targetHeight);\n writePassSceneUBO(task, eng, sc, camera, targetSignature._flipY);\n refreshSceneLightsUBO(eng, sc);\n // Expose the active camera to per-binding `update()` calls. Some renderables\n // (e.g. transparent billboard systems) need it to compute view-space sort\n // depths during their update.\n (context as MutableDrawUpdateContext)._camera = camera;\n updateBindings(task._opaqueBindings, context);\n updateBindings(task._directBindings, context);\n updateBindings(task._transparentBindings, context);\n // Per-frame back-to-front sort for transparent bindings — must run AFTER\n // updateBindings so renderables that compute `_worldCenter` inside their\n // own `update()` (billboard systems) are seen with current values.\n sortTransparentBindings(task, camera);\n}\n\nfunction executePass(task: RenderTask, eng: EngineContext, targetSignature: RenderTargetSignature, context: DrawUpdateContext): number {\n const sc = task.scene;\n const sampleCount = targetSignature._sampleCount;\n prepareRenderTaskPass(task, eng, targetSignature, context);\n const att = task._colorAttachment;\n const cfg = task._config;\n const swapchain = cfg.rt._descriptor.resolveToSwapchain === true;\n if (cfg.rt._colorView || swapchain) {\n att.clearValue = task._autoFromScene ? sc.clearColor : cfg.clrColor!;\n att.loadOp = cfg.clr ? \"clear\" : \"load\";\n }\n if (swapchain) {\n const swapView = eng._swapchainView;\n if (sampleCount > 1) {\n att.resolveTarget = swapView;\n } else {\n att.view = swapView;\n }\n }\n if (task._executeWithTransmission) {\n return task._executeWithTransmission(sampleCount);\n }\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n const draws = executePassBody(task, pass);\n pass.end();\n return draws;\n}\n\n/** Body of the registered `RenderPass`. Receives the live render-pass encoder\n * and issues all draws (viewport/scissor, group(0) bind, opaque bundle replay,\n * then direct-draws non-transparent direct + transparent). Returns the draw count. */\nfunction executePassBody(task: RenderTask, pass: GPURenderPassEncoder): number {\n const eng = task.engine as EngineContext;\n const cfg = task._config;\n const rt = cfg.rt;\n const scene = task.scene as SceneContext;\n const opaqueBindings = task._opaqueBindings;\n const opaqueBundles = task._opaqueBundles;\n const sceneBG = task._sceneBG;\n\n const camera = cfg.cam ?? scene.camera;\n const v = camera?.viewport;\n if (v) {\n const rw = rt._width;\n const rh = rt._height;\n const x = Math.floor(v.x * rw);\n const y = Math.floor((1 - v.y - v.height) * rh);\n const w = Math.ceil((v.x + v.width) * rw) - x;\n const h = Math.ceil((1 - v.y) * rh) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n }\n // Scene bind group (group 0) is task-owned and identical for every draw in this pass.\n pass.setBindGroup(0, sceneBG);\n\n // Opaque: cached render bundle. Invalidated by scene mutation (_renderableVersion)\n // or visibility version (_vis). The bundle records group(0) at its start so it can\n // be replayed standalone (executeBundles inherits no inherited state).\n if (task._lastVersion !== scene._renderableVersion || task._lastVis !== _vis || opaqueBundles.length === 0) {\n const desc = rt._descriptor;\n const be = eng._device.createRenderBundleEncoder({\n colorFormats: desc.colorFormat ? [desc.colorFormat] : [],\n depthStencilFormat: desc.depthStencilFormat,\n sampleCount: desc.sampleCount ?? 1,\n });\n be.setBindGroup(0, sceneBG);\n drawList(be, opaqueBindings, eng);\n opaqueBundles[0] = be.finish();\n task._lastVersion = scene._renderableVersion;\n task._lastVis = _vis;\n }\n let draws = opaqueBindings.length;\n pass.executeBundles(opaqueBundles);\n // executeBundles invalidates pass bind-group state — rebind group 0 before further draws.\n pass.setBindGroup(0, sceneBG);\n draws += drawList(pass, task._directBindings, eng);\n draws += drawList(pass, task._transparentBindings, eng);\n return draws;\n}\n\nfunction refreshTaskSceneBindGroup(task: RenderTask, eng: EngineContext): void {\n const lightsUBO = ensureSceneLightState(eng, task.scene as SceneContext)._buffer;\n if (lightsUBO === task._lightsUBO) {\n return;\n }\n task._lightsUBO = lightsUBO;\n task._sceneBG = eng._device.createBindGroup({\n layout: getSceneBindGroupLayout(eng),\n entries: [\n { binding: 0, resource: { buffer: task._sceneUBO } },\n { binding: 1, resource: { buffer: lightsUBO } },\n ],\n });\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n}\n\n/** Write the canonical SceneUniforms struct to the task-owned scene UBO.\n * Bails before touching scratch/GPU when all inputs are unchanged. */\nfunction writePassSceneUBO(task: RenderTask, eng: EngineContext, scene: SceneContext, camera: Camera | null, flipY?: boolean): void {\n if (!camera) {\n return;\n }\n\n const v = camera.viewport;\n const rt = task._config.rt;\n const aspect = (task._config.cs ? eng.canvas.width / eng.canvas.height : rt._width / rt._height) * (v ? v.width / v.height : 1);\n const fog = scene.fog;\n const envTextures = scene._envTextures;\n const img = scene.imageProcessing;\n const envRotationY = scene.envRotationY || 0;\n const wv = camera.worldMatrixVersion;\n const s = task._su;\n if (s[0] === camera && s[1] === fog && s[2] === wv && s[3] === aspect && s[4] === envRotationY && s[5] === img.exposure && s[6] === img.contrast) {\n return;\n }\n s[0] = camera;\n s[1] = fog;\n s[2] = wv;\n s[3] = aspect;\n s[4] = envRotationY;\n s[5] = img.exposure;\n s[6] = img.contrast;\n\n const data = task._suData;\n data.fill(0);\n\n const viewProj = getViewProjectionMatrix(camera, aspect);\n const viewMat = getViewMatrix(camera);\n const wm = camera.worldMatrix;\n\n // SCENE_UBO float offsets (see shaders/scene-uniforms.wgsl):\n // viewProjection = 0 view = 16 vEyePosition = 32\n // envRotationY = 36 vSphericalL00 = 40 exposureLinear = 76\n // contrast = 77 lodGenerationScale = 78 vFogInfos = 80\n // vFogColor = 84 clipPlane = 88\n data.set(viewProj, 0);\n // Y-flip for offscreen passes — negate row 1 of the projection (the multiplied\n // view*proj matrix). Row 1 of a column-major mat4 lives at indices 1,5,9,13.\n if (flipY) {\n data[1] = -data[1]!;\n data[5] = -data[5]!;\n data[9] = -data[9]!;\n data[13] = -data[13]!;\n }\n data.set(viewMat, 16);\n data[32] = wm[12]!;\n data[33] = wm[13]!;\n data[34] = wm[14]!;\n\n if (fog) {\n data[80] = fog.mode;\n data[81] = fog.start;\n data[82] = fog.end;\n data[83] = fog.density;\n data[84] = fog.color[0]!;\n data[85] = fog.color[1]!;\n data[86] = fog.color[2]!;\n }\n data[87] = eng.canvas.width;\n\n data[36] = envRotationY;\n if (envTextures?.sphericalHarmonics) {\n data.set(envTextures.sphericalHarmonics, 40);\n }\n\n data[76] = img.exposure;\n data[77] = img.contrast;\n data[78] = envTextures?.lodGenerationScale ?? 0.8;\n data[79] = +img.toneMappingEnabled;\n data[37] = eng.canvas.height;\n if (scene.clipPlane) {\n data[88] = scene.clipPlane[0];\n data[89] = scene.clipPlane[1];\n data[90] = scene.clipPlane[2];\n data[91] = scene.clipPlane[3];\n }\n eng._device.queue.writeBuffer(task._sceneUBO, 0, data as Float32Array<ArrayBuffer>);\n}\n\nfunction updateBindings(list: readonly DrawBinding[], context: DrawUpdateContext): void {\n for (const b of list) {\n b.update?.(context);\n }\n}\n\n/** Iterate DrawBindings, deduping setPipeline. */\nfunction drawList(enc: GPURenderPassEncoder | GPURenderBundleEncoder, list: readonly DrawBinding[], engine: EngineContext): number {\n let lp: GPURenderPipeline | null = null;\n let draws = 0;\n for (const b of list) {\n const mesh = b.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (b.pipeline !== lp) {\n enc.setPipeline(b.pipeline);\n lp = b.pipeline;\n }\n draws += b.draw(enc, engine);\n }\n return draws;\n}\n","import type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport { _vis, isRenderingContextRegistered, registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { LightBase } from \"../light/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { disposeMeshGpu } from \"../mesh/mesh-dispose.js\";\nimport type { AnimationGroup } from \"../animation/animation-group.js\";\nimport type { ShadowGenerator } from \"../shadow/shadow-generator.js\";\nimport type { FogConfig } from \"../material/standard/standard-material.js\";\nimport type { Renderable, PrePassRenderable, SceneUniformUpdater, MeshGroupBuilder } from \"../render/renderable.js\";\nimport type { TransformNode } from \"./transform-node.js\";\nimport type { SceneNode } from \"./scene-node.js\";\nimport type { EnvironmentTextures } from \"../loader-env/load-env.js\";\nimport type { FrameGraph } from \"../frame-graph/frame-graph.js\";\nimport { createFrameGraph, _appendTask } from \"../frame-graph/frame-graph.js\";\nimport { createRenderTask } from \"../frame-graph/render-task.js\";\nimport { createRenderTarget } from \"../engine/render-target.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\nimport type { SceneLightGpuState } from \"../render/lights-ubo.js\";\nimport type { ClusteredLightContainer } from \"../light/clustered.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\n\n/** Image processing configuration. */\nexport interface ImageProcessingConfig {\n exposure: number;\n contrast: number;\n toneMappingEnabled: boolean;\n /** \"standard\" (BJS TONEMAPPING_STANDARD, default) or \"aces\" (BJS TONEMAPPING_ACES). */\n toneMappingType?: \"standard\" | \"aces\";\n}\n\n/** A clipping plane expressed as the coefficients `[a, b, c, d]` of `a·x + b·y + c·z + d`. */\nexport type ClipPlane = readonly [number, number, number, number];\n\n/** Top-level scene context — pure state, no attached methods. */\nexport interface SceneContext extends RenderingContext {\n readonly engine: EngineContext;\n clearColor: GPUColorDict;\n camera: Camera | null;\n lights: LightBase[];\n imageProcessing: ImageProcessingConfig;\n\n /** All meshes added to the scene (standard + PBR). */\n meshes: Mesh[];\n\n /** Animation groups loaded from glTF or created manually. */\n animationGroups: AnimationGroup[];\n\n /** Fog configuration. Null = no fog. */\n fog: FogConfig | null;\n\n /** Scene clip plane as (normal.x, normal.y, normal.z, d). Matches Babylon.js Plane `dot(worldPosition, plane) > 0` discard semantics. */\n clipPlane: ClipPlane | null;\n\n /** Shadow generators registered on this scene. */\n shadowGenerators: ShadowGenerator[];\n\n /** Background material primaryColor (linear RGB). Default from Babylon createDefaultEnvironment. */\n environmentPrimaryColor?: [number, number, number];\n\n /** Environment cubemap Y rotation in radians. */\n envRotationY?: number;\n\n /** Fixed delta time in ms for deterministic animation. 0 = use real rAF delta. */\n fixedDeltaMs: number;\n\n /** All renderables in this scene. The active frame-graph tasks bucket them\n * (opaque / direct / transparent) at bind time based on `isTransparent`, `_direct`, and `_transmissive`. */\n /** @internal */\n _renderables: Renderable[];\n /** @internal Pre-pass work (shadow maps, compute, etc.). */\n _prePasses: PrePassRenderable[];\n /** GaussianSplatting meshes attached to this scene. Populated by\n * `attachGaussianSplattingMesh`. Scene-core stays GS-agnostic apart from\n * this opaque registry (used by `gpu-picker` to iterate GS meshes without\n * scanning `_renderables`). */\n /** @internal */\n _gsMeshes: GaussianSplattingMesh[];\n /** @internal Scene uniform updaters (one per shared UBO). */\n _uniformUpdaters: SceneUniformUpdater[];\n /** @internal Per-frame callbacks run before rendering (animation, physics, etc.). */\n _beforeRender: ((deltaMs: number) => void)[];\n /** @internal Deferred builders — registered by loaders/factories, run once at startEngine(). */\n _deferredBuilders: (() => void | Promise<void>)[];\n /** @internal Mesh group registry — maps builder to its mesh list (internal bookkeeping). */\n _groups: Map<MeshGroupBuilder, Mesh[]>;\n\n // ─── Dispose infrastructure ────────────────────────────────\n /** @internal Shared cleanup callbacks (scene UBOs, lights UBOs, etc.). Registered by builders. */\n _disposables: (() => void)[];\n /** @internal Per-mesh cleanup callbacks (mesh UBOs, bind groups). For material swap + dispose. */\n _meshDisposables: Map<Mesh, (() => void)[]>;\n /** @internal Meshes whose material was changed via setter — drained before each render frame. */\n _materialSwapQueue: Mesh[];\n /** @internal Monotonic counter bumped when the renderable list changes (add/remove/rebuild). */\n _renderableVersion: number;\n /** @internal Lazily-loaded processor; populated on first material reassignment. */\n _processSwaps?: (scene: SceneContext) => void;\n /** True once the initial deferred build (buildScene) has run. Meshes added after\n * this point are materialized via the per-frame swap drain rather than the\n * boot-only deferred-builder path. */\n /** @internal */\n _built: boolean;\n\n // ─── Stashed internal state (typed to avoid `as any` casts) ────\n /** @internal */\n _envTextures?: EnvironmentTextures;\n /** @internal Scene-owned shared LightsUniforms UBO state (group 0 binding 1). */\n _lightGpuState?: SceneLightGpuState;\n\n /** Frame graph driving this scene's rendering. Created eagerly by\n * `createSceneContext` with a default `RenderTask` that mirrors\n * `_renderables` into the swapchain. User code may add additional tasks\n * (offscreen RTTs, post-FX, UI overlays, etc.). */\n /** @internal */\n _frameGraph: FrameGraph;\n\n /** @internal Optional clustered point-light container. Only populated by the clustered-light extension API. */\n _clusteredLightContainer?: ClusteredLightContainer;\n /** @internal Updates clustered light cells for the camera used by the current render pass. */\n _clusteredLightUpdater?: (camera: Camera | null | undefined, targetWidth: number, targetHeight: number) => void;\n}\n\n/** Options passed to the scene-context factory. */\nexport interface SceneContextOptions {\n defaultRenderTask?: boolean;\n}\n\n/** Queue a mesh for renderable (re)build on the next frame's material-swap drain.\n * Shared by the material setter (runtime material change) and addToScene (runtime\n * mesh add). Lazily loads the swap processor so scenes that never mutate at runtime\n * don't pull it into their bundle. */\nfunction enqueueMaterialSwap(scene: SceneContext, mesh: Mesh): void {\n const mi = mesh as Mesh;\n if (mi._materialDirty) {\n return;\n }\n mi._materialDirty = true;\n scene._materialSwapQueue.push(mesh);\n if (!scene._processSwaps) {\n void import(\"./scene-material-swap.js\").then((m) => {\n scene._processSwaps = m.processMaterialSwaps;\n });\n }\n}\n\n/** Install a property setter on mesh.material that sets _materialDirty\n * and pushes the mesh into the scene's swap queue for processing. */\nfunction installMaterialSetter(scene: SceneContext, mesh: Mesh): void {\n let _mat = mesh.material;\n Object.defineProperty(mesh, \"material\", {\n get() {\n return _mat;\n },\n set(v) {\n if (v !== _mat) {\n _mat = v;\n enqueueMaterialSwap(scene, mesh);\n }\n },\n configurable: true,\n enumerable: true,\n });\n}\n\n/** Create an empty scene context bound to the given engine. */\nexport function createSceneContext(engine: EngineContext, options?: SceneContextOptions): SceneContext {\n const eng = engine as EngineContext;\n\n // Closures below capture `ctx` by-reference via this object.\n const ctxLocal: Omit<SceneContext, \"_frameGraph\"> = {\n engine,\n clearColor: { r: 0.2, g: 0.2, b: 0.3, a: 1.0 },\n camera: null,\n lights: [],\n meshes: [],\n animationGroups: [],\n fog: null,\n clipPlane: null,\n shadowGenerators: [],\n imageProcessing: { exposure: 1.0, contrast: 1.0, toneMappingEnabled: false },\n _renderables: [],\n _prePasses: [],\n _gsMeshes: [],\n _uniformUpdaters: [],\n fixedDeltaMs: 0,\n _beforeRender: [],\n _deferredBuilders: [],\n _groups: new Map(),\n _disposables: [],\n _meshDisposables: new Map(),\n _materialSwapQueue: [],\n _renderableVersion: 0,\n _built: false,\n _drawCallsPre: 0,\n\n _update(): void {\n const d = ctx.fixedDeltaMs > 0 ? ctx.fixedDeltaMs : eng._currentDelta;\n const encoder = eng._currentEncoder;\n let draws = 0;\n for (const cb of ctx._beforeRender) {\n cb(d);\n }\n if (ctx._materialSwapQueue.length > 0) {\n ctx._processSwaps?.(ctx);\n }\n for (const pp of ctx._prePasses) {\n draws += pp.execute(encoder, eng);\n }\n for (const u of ctx._uniformUpdaters) {\n u.update(eng);\n }\n ctx._drawCallsPre = draws;\n },\n _record(): number {\n return ctx._frameGraph.execute();\n },\n _resize(): void {\n // Canvas backing-store changed: rebuild the frame graph so canvas-sized\n // render targets get re-allocated at the new pixel size before the next record.\n ctx._frameGraph.build();\n },\n };\n\n const ctx = ctxLocal as SceneContext;\n // Eagerly attach the frame graph + a default swapchain render-pass task. The\n // graph drives all GPU work for this scene; user code can add more tasks\n // (offscreen RTTs, post-FX, UI overlays) before/after.\n const fg = createFrameGraph(eng);\n ctx._frameGraph = fg;\n if (options?.defaultRenderTask !== false) {\n const swapRT = createRenderTarget({\n label: \"scene-swapchain\",\n colorFormat: eng.format,\n depthStencilFormat: \"depth24plus-stencil8\",\n sampleCount: eng.msaaSamples,\n size: \"canvas\",\n resolveToSwapchain: true,\n });\n _appendTask(\n fg,\n createRenderTask(\n {\n name: \"scene\",\n rt: swapRT,\n clrColor: ctx.clearColor,\n },\n eng,\n ctx\n )\n );\n }\n ctx._disposables.push(() => fg.dispose());\n return ctx;\n}\n\n/** Register a callback to run before each rendered frame. */\nexport function onBeforeRender(scene: SceneContext, cb: (deltaMs: number) => void): void {\n (scene as SceneContext)._beforeRender.unshift(cb);\n}\n\n/** Register a callback to run when `disposeScene` is called. Used to tie\n * user-owned GPU resources (e.g. a `SpriteRenderer`) to the scene's lifetime. */\nexport function onSceneDispose(scene: SceneContext, cb: () => void): void {\n (scene as SceneContext)._disposables.push(cb);\n}\n\n/** Get the scene's frame graph. Always non-null — created in `createSceneContext`. */\nexport function getFrameGraph(scene: SceneContext): FrameGraph {\n return (scene as SceneContext)._frameGraph;\n}\n\nexport interface DeferredSceneRenderables {\n renderables: readonly Renderable[];\n dispose?: () => void;\n}\n\n/** @internal Register optional scene-hosted render work without teaching `addToScene` about the feature. */\nexport function addDeferredSceneRenderables(\n scene: SceneContext,\n build: (engine: EngineContext, scene: SceneContext) => DeferredSceneRenderables | Promise<DeferredSceneRenderables>\n): void {\n const ctx = scene as SceneContext;\n ctx._deferredBuilders.push(async () => {\n const built = await build(ctx.engine as EngineContext, ctx);\n ctx._renderables.push(...built.renderables);\n if (built.dispose) {\n ctx._disposables.push(built.dispose);\n }\n });\n}\n\n/**\n * Adds an entity to the scene, dispatching on its type. Asset containers are unpacked and\n * each contained entity added recursively; meshes, lights, cameras, transform nodes, and\n * shadow generators are registered in their respective scene collections.\n * @param scene - The owning scene (pillar 4b: entities never reference the scene themselves).\n * @param entity - The entity (or asset container) to add.\n */\nexport function addToScene(scene: SceneContext, entity: Mesh | LightBase | Camera | ShadowGenerator | TransformNode | AssetContainer): void {\n const ctx = scene as SceneContext;\n // AssetContainer from loadGltf / loadBabylon — process each field present\n if (\"entities\" in entity) {\n const result = entity as AssetContainer;\n for (const e of result.entities) {\n addToScene(scene, e);\n }\n if (result.clearColor) {\n ctx.clearColor = result.clearColor;\n }\n if (result.camera && !ctx.camera) {\n ctx.camera = result.camera;\n }\n if (result.animationGroups?.length) {\n const engine = ctx.engine as EngineContext;\n const groups = result.animationGroups;\n ctx.animationGroups.push(...groups);\n ctx._beforeRender.push((deltaMs: number) => {\n for (const g of groups) {\n if (!g._stopped && g._ctrl) {\n g._ctrl.tick(deltaMs, engine);\n }\n }\n });\n }\n return;\n }\n if (\"_gpu\" in entity && \"material\" in entity) {\n const mesh = entity as unknown as Mesh;\n ctx.meshes.push(mesh);\n installMaterialSetter(ctx, mesh);\n const build = mesh.material?._buildGroup;\n if (build) {\n let group = ctx._groups.get(build);\n if (!group) {\n group = [];\n ctx._groups.set(build, group);\n ctx._deferredBuilders.push(async () => {\n const result = await build(ctx, group!);\n ctx._renderables.push(...result.renderables);\n if (result.updater) {\n ctx._uniformUpdaters.push(result.updater);\n }\n });\n }\n group.push(mesh);\n // Added after the initial build: the deferred builder for this group has\n // already run (and only runs at boot), so materialize this mesh's renderable\n // through the per-frame material-swap drain instead.\n if (ctx._built) {\n enqueueMaterialSwap(ctx, mesh);\n }\n }\n } else if (\"lightType\" in entity) {\n ctx.lights.push(entity as LightBase);\n }\n // Recurse into children of meshes, lights, cameras — set parent links\n const kids = (entity as unknown as SceneNode).children;\n if (kids?.length) {\n for (const child of kids) {\n (child as unknown as SceneNode).parent = entity as unknown as SceneNode;\n addToScene(scene, child);\n }\n }\n}\n\n/** Release all GPU resources owned by this scene. */\nexport function disposeScene(scene: SceneContext): void {\n const ctx = scene as SceneContext;\n unregisterRenderingContext(ctx.engine, ctx);\n for (const fn of ctx._disposables) {\n fn();\n }\n for (const fns of ctx._meshDisposables.values()) {\n for (const fn of fns) {\n fn();\n }\n }\n ctx._meshDisposables.clear();\n for (const mesh of ctx.meshes) {\n disposeMeshGpu(mesh);\n }\n ctx.meshes.length = 0;\n ctx._renderables.length = 0;\n ctx._prePasses.length = 0;\n ctx._gsMeshes.length = 0;\n ctx._uniformUpdaters.length = 0;\n ctx._beforeRender.length = 0;\n ctx._deferredBuilders.length = 0;\n ctx._disposables.length = 0;\n ctx._materialSwapQueue.length = 0;\n ctx.lights.length = 0;\n ctx.animationGroups.length = 0;\n ctx.shadowGenerators.length = 0;\n ctx.camera = null;\n}\n\n/** @internal Run all deferred builders (called by registerScene's boot step before the first frame). */\nexport async function buildScene(scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n while (ctx._deferredBuilders.length > 0) {\n const builders = [...ctx._deferredBuilders];\n ctx._deferredBuilders = [];\n await Promise.all(builders.map(async (b) => b()));\n }\n for (const mesh of ctx._materialSwapQueue) {\n (mesh as Mesh)._materialDirty = false;\n }\n ctx._materialSwapQueue.length = 0;\n ctx._renderableVersion++;\n ctx._built = true;\n}\n\n/**\n * Register a scene with the engine. Builds deferred work, sorts renderables by order,\n * and adds the scene to the engine's render list in overlay order.\n */\nexport async function registerScene(engine: EngineContext, scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n if (isRenderingContextRegistered(engine, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if ((engine as EngineContext)._renderingContexts.length > 0) {\n (await import(\"./swapchain-overlay.js\")).configureSwapchainOverlayScene(engine as EngineContext, ctx);\n }\n registerRenderingContext(engine, ctx);\n}\n\n/**\n * Register a scene with the engine and install the scene-owned shadow frame-graph task.\n * Use only for scenes that generate shadow maps.\n */\nexport async function registerSceneWithShadowSupport(engine: EngineContext, scene: SceneContext): Promise<void> {\n const ctx = scene as SceneContext;\n if (isRenderingContextRegistered(engine, ctx)) {\n return;\n }\n await buildScene(scene);\n ctx._renderables.sort(byOrder);\n await ensureShadowTask(engine as EngineContext, ctx);\n await Promise.all(ctx._frameGraph._tasks.map((task) => task._preload?.()).filter((preload): preload is Promise<void> => preload !== undefined));\n ctx._frameGraph.build();\n if ((engine as EngineContext)._renderingContexts.length > 0) {\n (await import(\"./swapchain-overlay.js\")).configureSwapchainOverlayScene(engine as EngineContext, ctx);\n }\n registerRenderingContext(engine, ctx);\n}\n\nconst byOrder = (a: Renderable, b: Renderable): number => a.order - b.order;\n\nasync function ensureShadowTask(engine: EngineContext, scene: SceneContext): Promise<void> {\n const { createShadowTask } = await import(\"../frame-graph/shadow-task.js\");\n scene._frameGraph._tasks.unshift(createShadowTask(engine, scene));\n}\n\n/** Remove a previously-registered scene. Idempotent. Does not dispose scene resources. */\nexport function unregisterScene(engine: EngineContext, scene: SceneContext): void {\n unregisterRenderingContext(engine, scene as SceneContext);\n}\n","import type { Mat4 } from \"./types.js\";\n\n/** Create a new identity Mat4. */\nexport function mat4Identity(): Mat4 {\n const m = new Float32Array(16) as Mat4;\n m[0] = 1;\n m[5] = 1;\n m[10] = 1;\n m[15] = 1;\n return m;\n}\n","import type { Mat4, Vec3 } from \"./types.js\";\nimport { mat4Identity } from \"./mat4-identity.js\";\n\n/** LookAt matrix (right-handed). Matches Babylon.js Matrix.LookAtLHToRef with LH convention. */\nexport function mat4LookAtLH(eye: Vec3, target: Vec3, up: Vec3): Mat4 {\n // Babylon.js uses LEFT-HANDED coordinate system\n const zAxis = { x: target.x - eye.x, y: target.y - eye.y, z: target.z - eye.z };\n const zLen = Math.sqrt(zAxis.x * zAxis.x + zAxis.y * zAxis.y + zAxis.z * zAxis.z);\n if (zLen < 1e-10) {\n return mat4Identity();\n }\n const invZ = 1 / zLen;\n zAxis.x *= invZ;\n zAxis.y *= invZ;\n zAxis.z *= invZ;\n\n // xAxis = cross(up, zAxis)\n const xAxis = {\n x: up.y * zAxis.z - up.z * zAxis.y,\n y: up.z * zAxis.x - up.x * zAxis.z,\n z: up.x * zAxis.y - up.y * zAxis.x,\n };\n const xLen = Math.sqrt(xAxis.x * xAxis.x + xAxis.y * xAxis.y + xAxis.z * xAxis.z);\n if (xLen < 1e-10) {\n return mat4Identity();\n }\n const invX = 1 / xLen;\n xAxis.x *= invX;\n xAxis.y *= invX;\n xAxis.z *= invX;\n\n // yAxis = cross(zAxis, xAxis)\n const yAxis = {\n x: zAxis.y * xAxis.z - zAxis.z * xAxis.y,\n y: zAxis.z * xAxis.x - zAxis.x * xAxis.z,\n z: zAxis.x * xAxis.y - zAxis.y * xAxis.x,\n };\n\n return new Float32Array([\n xAxis.x,\n yAxis.x,\n zAxis.x,\n 0,\n xAxis.y,\n yAxis.y,\n zAxis.y,\n 0,\n xAxis.z,\n yAxis.z,\n zAxis.z,\n 0,\n -(xAxis.x * eye.x + xAxis.y * eye.y + xAxis.z * eye.z),\n -(yAxis.x * eye.x + yAxis.y * eye.y + yAxis.z * eye.z),\n -(zAxis.x * eye.x + zAxis.y * eye.y + zAxis.z * eye.z),\n 1,\n ]) as Mat4;\n}\n","import type { Vec3 } from \"./types.js\";\n\nexport const Vec3Up: Readonly<Vec3> = { x: 0, y: 1, z: 0 };\n","/** Shared version-based lazy world matrix computation.\n *\n * Each entity provides only getLocalMatrix(). This module handles:\n * - version tracking (_worldVersion bumped by own TRS changes and ancestor motion)\n * - caching and staleness detection (_cachedWorld nulled on any change)\n * - PUSH dirty propagation: a transform write invalidates the node AND all of its\n * descendants up front, so per-frame consumers can read worldMatrixVersion in\n * O(1) (a plain field read) instead of walking the parent chain.\n *\n * Ancestor-only motion (e.g. animating a parent transform node) must bump a\n * descendant's worldMatrixVersion so per-frame consumers re-upload its UBO.\n * Rather than have each node PULL up its parent chain on every read, this module\n * keeps its own child registry (driven by the reliably-called `parent` setter, NOT\n * the host's `children` array which loaders/setParent maintain inconsistently) and\n * PUSHES invalidation down on every local change or reparent. Reads are O(1) (a\n * plain field read); writers pay an O(subtree) push. This is a clear win for the\n * common case (few movers, many readers) and never worse than the old pull walk.\n *\n * Foreign parents — an IWorldMatrixProvider that is not tagged with our state\n * symbol (e.g. a user-supplied object) — cannot be pushed to because we never see\n * their writes. For those we keep a cheap PULL fallback that polls the parent's\n * public version on read. All in-engine hosts (mesh, scene node, camera, light,\n * Gaussian-splatting mesh) ARE tagged, so engine hierarchies are pure push.\n *\n * Zero entity imports — depends only on Mat4 and mat4Multiply. */\n\nimport type { Mat4 } from \"../math/types.js\";\nimport type { IWorldMatrixProvider } from \"./parentable.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\n\nexport interface WorldMatrixAccessors {\n /** Getter — returns lazily computed world matrix. */\n getWorldMatrix(): Mat4;\n /** Getter — returns current version. */\n getWorldMatrixVersion(): number;\n /** Call when own TRS changes. Invalidates cache + subtree, forces recompute. */\n markLocalDirty(): void;\n /** Reference to parent — set directly. */\n parent: IWorldMatrixProvider | null;\n /** @internal Push: mark this node and its whole subtree dirty (clean-guarded). */\n _invalidate(): void;\n /** @internal Register a same-module child so future invalidations reach it. */\n _addChild(child: WorldMatrixAccessors): void;\n /** @internal Deregister a child (reparent away). */\n _removeChild(child: WorldMatrixAccessors): void;\n}\n\nconst WM_STATE = Symbol(\"wmState\");\n\n/** Tag a host object (mesh, scene node, camera, light, …) with its world-matrix\n * state so children can register for push invalidation and call its accessor\n * closures directly, bypassing the host's property getters. */\nexport function attachWorldMatrixState(host: object, state: WorldMatrixAccessors): void {\n (host as unknown as Record<symbol, unknown>)[WM_STATE] = state;\n}\n\nfunction peekWorldMatrixState(p: IWorldMatrixProvider | null): WorldMatrixAccessors | null {\n if (p === null) {\n return null;\n }\n const s = (p as unknown as Record<symbol, unknown>)[WM_STATE];\n return (s as WorldMatrixAccessors | undefined) ?? null;\n}\n\n/**\n * Create world matrix state for any entity type.\n *\n * @param getLocalMatrix - Entity-specific function that returns the local (pre-parent)\n * transform matrix. Called only when the cache is stale.\n */\nexport function createWorldMatrixState(getLocalMatrix: () => Mat4): WorldMatrixAccessors {\n let _worldVersion = 0;\n let _lastSeenParentVersion = -1;\n let _cachedWorld: Mat4 | null = null;\n const _ownedWorld = new Float32Array(16) as Mat4;\n let _parent: IWorldMatrixProvider | null = null;\n let _parentState: WorldMatrixAccessors | null = null;\n const _children: WorldMatrixAccessors[] = [];\n\n // Mark this node — and, transitively, its whole subtree — dirty, bumping the\n // version so per-frame consumers (which gate UBO uploads on worldMatrixVersion)\n // re-upload. Propagation is eager and unconditional: consumers may never read a\n // pure transform node's world matrix, so a \"skip if already dirty\" guard would\n // strand its descendants on a stale version when an ancestor moves every frame.\n // Caching is still lazy — getWorldMatrix recomputes only when _cachedWorld is\n // null — so reads stay cheap; only writers pay the O(subtree) push.\n function invalidate(): void {\n _cachedWorld = null;\n _worldVersion++;\n for (const child of _children) {\n child._invalidate();\n }\n }\n\n // Foreign parent (not tagged with our symbol): we never observe its writes, so\n // poll its public version on read and push a subtree invalidation when it moved.\n function pollForeignParent(): void {\n const pv = (_parent as IWorldMatrixProvider).worldMatrixVersion;\n if (pv !== _lastSeenParentVersion) {\n _lastSeenParentVersion = pv;\n invalidate();\n }\n }\n\n const state: WorldMatrixAccessors = {\n get parent(): IWorldMatrixProvider | null {\n return _parent;\n },\n set parent(p: IWorldMatrixProvider | null) {\n if (p === _parent) {\n return;\n }\n if (_parentState !== null) {\n _parentState._removeChild(state);\n }\n _parent = p;\n _parentState = peekWorldMatrixState(p);\n if (_parentState !== null) {\n _parentState._addChild(state);\n }\n _lastSeenParentVersion = -1;\n // Reparenting changes our world transform → dirty us and the subtree.\n invalidate();\n },\n\n markLocalDirty(): void {\n invalidate();\n },\n\n getWorldMatrix(): Mat4 {\n if (_parentState === null && _parent !== null) {\n pollForeignParent();\n }\n if (_cachedWorld !== null) {\n return _cachedWorld;\n }\n const local = getLocalMatrix();\n if (_parent !== null) {\n const pw = _parent.worldMatrix;\n mat4MultiplyInto(_ownedWorld as Float32Array, 0, pw as Float32Array, 0, local as Float32Array, 0);\n _cachedWorld = _ownedWorld;\n } else {\n _cachedWorld = local;\n }\n return _cachedWorld;\n },\n\n getWorldMatrixVersion(): number {\n if (_parentState === null && _parent !== null) {\n pollForeignParent();\n }\n return _worldVersion;\n },\n\n _invalidate(): void {\n invalidate();\n },\n\n _addChild(child: WorldMatrixAccessors): void {\n _children.push(child);\n },\n\n _removeChild(child: WorldMatrixAccessors): void {\n const i = _children.indexOf(child);\n if (i >= 0) {\n _children.splice(i, 1);\n }\n },\n };\n\n return state;\n}\n","/** ObservableVec3 — a 3-component vector with setters that notify on change.\n * Used for Mesh position/rotation/scaling so the render system\n * can detect transform changes via a version counter.\n * V8 inlines trivial getters/setters — zero overhead vs raw properties. */\n\nimport type { Vec3 } from \"./types.js\";\n\nexport class ObservableVec3 implements Vec3 {\n private _x: number;\n private _y: number;\n private _z: number;\n private readonly _onDirty: () => void;\n\n constructor(x: number, y: number, z: number, onDirty: () => void) {\n this._x = x;\n this._y = y;\n this._z = z;\n this._onDirty = onDirty;\n }\n\n get x(): number {\n return this._x;\n }\n set x(v: number) {\n if (this._x !== v) {\n this._x = v;\n this._onDirty();\n }\n }\n\n get y(): number {\n return this._y;\n }\n set y(v: number) {\n if (this._y !== v) {\n this._y = v;\n this._onDirty();\n }\n }\n\n get z(): number {\n return this._z;\n }\n set z(v: number) {\n if (this._z !== v) {\n this._z = v;\n this._onDirty();\n }\n }\n\n /** Bulk set — one dirty notification instead of three. */\n set(x: number, y: number, z: number): void {\n this._x = x;\n this._y = y;\n this._z = z;\n this._onDirty();\n }\n\n /** Copy values from another vector. */\n copyFrom(v: Vec3): void {\n this.set(v.x, v.y, v.z);\n }\n\n /** Copy into a Float32Array at offset. */\n toArray(out: Float32Array, offset = 0): void {\n out[offset] = this._x;\n out[offset + 1] = this._y;\n out[offset + 2] = this._z;\n }\n}\n","import type { Camera, NormalizedViewport } from \"./camera.js\";\nimport type { Vec3, Mat4 } from \"../math/types.js\";\nimport { mat4LookAtLH } from \"../math/mat4-look-at-lh.js\";\nimport { Vec3Up } from \"../math/vec3-up.js\";\nimport type { IWorldMatrixProvider, IParentable } from \"../scene/parentable.js\";\nimport { createWorldMatrixState, attachWorldMatrixState } from \"../scene/world-matrix-state.js\";\nimport { ObservableVec3 } from \"../math/observable-vec3.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\n\n/** ArcRotateCamera — orbits around a target point.\n * Uses Babylon.js convention: left-handed, alpha=rotation around Y, beta=elevation.\n * Plain data + methods. Does NOT know about the scene.\n *\n * Push-based dirty tracking: alpha/beta/radius use Object.defineProperty,\n * target uses ObservableVec3. Changes call wm.markLocalDirty() immediately.\n *\n * Inertia follows the Babylon.js model: input handlers accumulate per-frame\n * offsets (inertialAlphaOffset, etc.) which are applied and exponentially\n * decayed each frame by the controls module. */\nexport interface ArcRotateCamera extends Camera, IWorldMatrixProvider, IParentable {\n alpha: number;\n beta: number;\n radius: number;\n target: Vec3;\n fov: number;\n nearPlane: number;\n farPlane: number;\n viewport?: NormalizedViewport;\n children: SceneNode[];\n\n /** Inertia coefficient for rotation and zoom (0 = instant stop, 0.9 = default, 1 = no decay). */\n inertia: number;\n /** Inertia coefficient for panning (0 = instant stop, 0.9 = default). */\n panningInertia: number;\n\n /** Per-frame inertial offsets — accumulated by input, applied & decayed each frame. */\n inertialAlphaOffset: number;\n inertialBetaOffset: number;\n inertialRadiusOffset: number;\n inertialPanningX: number;\n inertialPanningY: number;\n\n parent: IWorldMatrixProvider | null;\n readonly worldMatrix: Mat4;\n readonly worldMatrixVersion: number;\n}\n\n/** Create a bare ArcRotateCamera with given params. Pure data, no scene knowledge. */\nexport function createArcRotateCamera(alpha: number, beta: number, radius: number, target: Vec3): ArcRotateCamera {\n function localEyePosition(): Vec3 {\n const cosA = Math.cos(cam.alpha),\n sinA = Math.sin(cam.alpha);\n const cosB = Math.cos(cam.beta);\n let sinB = Math.sin(cam.beta);\n if (sinB === 0) {\n sinB = 0.0001;\n }\n return {\n x: cam.target.x + cam.radius * cosA * sinB,\n y: cam.target.y + cam.radius * cosB,\n z: cam.target.z + cam.radius * sinA * sinB,\n };\n }\n\n function cameraLocalWorldMatrix(): Mat4 {\n const eye = localEyePosition();\n const v = mat4LookAtLH(eye, cam.target, Vec3Up);\n // Transpose upper 3×3 of view = camera-to-world rotation; translation = eye.\n return new Float32Array([v[0]!, v[4]!, v[8]!, 0, v[1]!, v[5]!, v[9]!, 0, v[2]!, v[6]!, v[10]!, 0, eye.x, eye.y, eye.z, 1]) as Mat4;\n }\n\n const wm = createWorldMatrixState(cameraLocalWorldMatrix);\n const onDirty = (): void => wm.markLocalDirty();\n\n const scalars = { alpha, beta, radius };\n\n const cam: ArcRotateCamera = {\n alpha: 0 as number, // placeholder — overridden by defineProperty below\n beta: 0 as number,\n radius: 0 as number,\n target: new ObservableVec3(target.x, target.y, target.z, onDirty) as unknown as Vec3,\n fov: 0.8,\n nearPlane: 0.1,\n farPlane: 1000,\n children: [] as SceneNode[],\n\n inertia: 0.9,\n panningInertia: 0.9,\n inertialAlphaOffset: 0,\n inertialBetaOffset: 0,\n inertialRadiusOffset: 0,\n inertialPanningX: 0,\n inertialPanningY: 0,\n\n get parent() {\n return wm.parent;\n },\n set parent(v) {\n wm.parent = v;\n },\n get worldMatrix() {\n return wm.getWorldMatrix();\n },\n get worldMatrixVersion() {\n return wm.getWorldMatrixVersion();\n },\n };\n\n // Push-based dirty tracking for scalar camera params that affect worldMatrix.\n for (const key of [\"alpha\", \"beta\", \"radius\"] as const) {\n Object.defineProperty(cam, key, {\n get: () => scalars[key],\n set: (v: number) => {\n if (scalars[key] !== v) {\n scalars[key] = v;\n onDirty();\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n\n // Tag so children parented to this camera get push invalidation (O(1) reads).\n attachWorldMatrixState(cam, wm);\n\n return cam;\n}\n","import type { Vec3 } from \"./types.js\";\n\nexport function vec3(x: number, y: number, z: number): Vec3 {\n return { x, y, z };\n}\n","import type { SceneContext } from \"./scene-core.js\";\nimport type { ArcRotateCamera } from \"../camera/arc-rotate.js\";\nimport { createArcRotateCamera } from \"../camera/arc-rotate.js\";\nimport { vec3 } from \"../math/vec3-ctor.js\";\n\n/** Create an ArcRotateCamera framed to fit all loaded meshes, assign it to scene.\n * Only the scene knows its contents — auto-framing logic lives here.\n * Matches Babylon.js createDefaultCameraOrLight(true, true, true). */\nexport function createDefaultCamera(scene: SceneContext): ArcRotateCamera {\n // Compute world AABB across all meshes with bounds\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n for (const m of scene.meshes) {\n const boundMin = m.boundMin;\n const boundMax = m.boundMax;\n if (!boundMin || !boundMax) {\n continue;\n }\n if (m.visible === false) {\n continue;\n }\n if (boundMin[0]! < minX) {\n minX = boundMin[0]!;\n }\n if (boundMin[1]! < minY) {\n minY = boundMin[1]!;\n }\n if (boundMin[2]! < minZ) {\n minZ = boundMin[2]!;\n }\n if (boundMax[0]! > maxX) {\n maxX = boundMax[0]!;\n }\n if (boundMax[1]! > maxY) {\n maxY = boundMax[1]!;\n }\n if (boundMax[2]! > maxZ) {\n maxZ = boundMax[2]!;\n }\n }\n\n // Babylon formula: radius = worldSize.length() * 1.5\n const sx = maxX - minX,\n sy = maxY - minY,\n sz = maxZ - minZ;\n const diag = Math.sqrt(sx * sx + sy * sy + sz * sz);\n let radius = diag * 1.5;\n let center = vec3(minX + sx * 0.5, minY + sy * 0.5, minZ + sz * 0.5);\n\n if (!isFinite(radius) || radius === 0) {\n radius = 1;\n center = vec3(0, 0, 0);\n }\n\n // Babylon defaults: alpha = -π/2, beta = π/2\n const cam = createArcRotateCamera(-(Math.PI / 2), Math.PI / 2, radius, center);\n cam.nearPlane = radius * 0.01;\n cam.farPlane = radius * 1000;\n\n scene.camera = cam;\n return cam;\n}\n","import type { SceneContext } from \"./scene-core.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { disposeMeshGpu } from \"../mesh/mesh-dispose.js\";\nimport { removeMeshFromTask } from \"../frame-graph/render-task.js\";\nimport type { RenderTask } from \"../frame-graph/render-task.js\";\n\n/** Remove a mesh from the scene and destroy its GPU resources.\n * Standalone function for tree-shaking — only included when actually used. */\nexport function removeFromScene(scene: SceneContext, mesh: Mesh): void {\n const fns = scene._meshDisposables.get(mesh);\n // Whether this call actually mutated scene state — used to gate the renderable\n // version bump so a no-op removal (mesh never registered) doesn't needlessly\n // invalidate the cached opaque bundle.\n let didMutate = false;\n if (fns) {\n didMutate = true;\n for (const fn of fns) {\n fn();\n }\n scene._meshDisposables.delete(mesh);\n }\n const mi2 = scene.meshes.indexOf(mesh);\n if (mi2 >= 0) {\n scene.meshes.splice(mi2, 1);\n didMutate = true;\n }\n const i = scene._renderables.findIndex((r) => r.mesh === mesh);\n if (i >= 0) {\n scene._renderables.splice(i, 1);\n didMutate = true;\n }\n // Invalidate any auto-mirroring render task so it rebuilds its binding lists +\n // cached opaque bundle without this mesh BEFORE its GPU buffers (vertex data +\n // per-packet system UBO) are touched again. Done whenever the mesh actually\n // belonged to the scene — NOT gated on owning a standalone renderable: meshes\n // sharing a material at the initial scene build are merged into one combined\n // renderable whose `mesh` is undefined, yet their now-destroyed buffers are\n // still referenced by that renderable's update()/draw() and the cached bundle.\n // Mirrors the version bump done on add (material-swap) and initial build.\n if (didMutate) {\n scene._renderableVersion++;\n }\n // Drop from the material group registry so a later full rebuild (e.g. device-lost\n // recovery) doesn't try to re-materialize a disposed mesh.\n const build = mesh.material?._buildGroup;\n const group = build ? scene._groups.get(build) : undefined;\n if (group) {\n const gi = group.indexOf(mesh);\n if (gi >= 0) {\n group.splice(gi, 1);\n }\n }\n // Drop any pending swap-queue entry (mesh added then removed before the drain).\n const qi = scene._materialSwapQueue.indexOf(mesh);\n if (qi >= 0) {\n scene._materialSwapQueue.splice(qi, 1);\n }\n mesh._materialDirty = false;\n // Deregister from the world-matrix push registry so a long-lived parent stops\n // retaining/traversing this disposed child on every invalidation. (The parent→\n // child reference is new with the push model; reparent already deregisters, but\n // removal does not go through the parent setter otherwise.)\n mesh.parent = null;\n // Frame-graph eviction: the scene always has a frame graph (created in\n // createSceneContext). Walk its render-pass tasks and drop any binding whose\n // source mesh matches. Tasks identified by having a `_config` field\n // (RenderTask shape).\n for (const task of scene._frameGraph._tasks) {\n if (\"_config\" in (task as object)) {\n removeMeshFromTask(task as RenderTask, mesh);\n }\n }\n disposeMeshGpu(mesh);\n}\n","/** Mesh/node visibility toggle. Public entry point is `setMeshVisible`\n * (barrel-exported); also used internally by the KHR_node_visibility loader\n * and KHR_animation_pointer writer.\n *\n * This helper is the sole place that bumps the module-scoped visibility\n * epoch (see `visibility-epoch.ts`). The bump invalidates the cached opaque\n * render bundle so a hidden mesh actually stops drawing — a bare\n * `node.visible = …` field write does NOT, by design, so the hot SceneNode\n * write path stays a plain field assignment and bundle invalidation is O(1). */\n\nimport type { SceneNode } from \"./scene-node.js\";\nimport { bumpVisibilityEpoch } from \"../engine/engine.js\";\n\n/** Set `visible` on `node` and all descendants (via `node.children`). glTF\n * KHR_node_visibility specifies that children inherit their parent's\n * invisibility — we materialize this at set-time so the render hot-path\n * only has to check a single boolean per mesh. */\nexport function setSubtreeVisible(node: SceneNode, v: boolean): void {\n cascade(node, v);\n bumpVisibilityEpoch();\n}\n\nfunction cascade(node: SceneNode, v: boolean): void {\n node.visible = v;\n const kids = node.children;\n for (let i = 0; i < kids.length; i++) {\n cascade(kids[i]!, v);\n }\n}\n","/**\n * Pass — the base interface every frame-graph pass implements.\n *\n * Modelled on Babylon.js' `IFrameGraphPass`. A `Task` records one or more\n * passes during `Task.record()` (via the public `addRenderPass(...)` action,\n * etc.), and the shared `_executeTask()` helper iterates `task._passes`\n * calling `pass._execute()`. Today the only concrete pass type is `RenderPass`;\n * future compute / copy / object-list passes will share this same shape.\n *\n * Lifecycle:\n * - `_initialize()` runs once after all tasks have finished recording, so\n * a pass can defer descriptor construction until any RT textures it\n * depends on are built. RenderPass uses this to assemble its cached\n * `GPURenderPassDescriptor`.\n * - `_execute()` runs once per frame from `_executeTask()` and performs this\n * pass's concrete GPU work. It returns the number of draw calls issued\n * (passed back up to the engine's per-frame draw counter).\n * - `_dispose()` frees any pass-owned GPU/CPU state.\n *\n * Conventions:\n * - Pure-state interface, no methods on the user-facing surface beyond\n * the lifecycle hooks. Configuration goes through standalone functions\n * (e.g. `addPassDependencies`, `setRenderPassRenderTarget`).\n */\n\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { Task } from \"./task.js\";\n\n/** Body of a render pass — receives the live render-pass encoder and returns\n * the number of draws issued. */\nexport type RenderPassExecuteFunc = (pass: GPURenderPassEncoder) => number;\n\n/** Base interface every frame-graph pass implements: a named unit of GPU work with `_initialize` / `_execute` / `_dispose` lifecycle hooks. */\nexport interface Pass {\n readonly name: string;\n\n /** @internal The task that owns this pass. Set on creation via `createRenderPass`. */\n _parentTask: Task;\n\n /** Render targets (textures) this pass references. Used (later) by the\n * texture manager to compute lifetimes / aliasing. Lifted from BJS'\n * `FrameGraphRenderPass` so future compute / copy / object-list passes\n * share the same surface without re-introducing it per pass type. */\n /** @internal */\n _dependencies: Set<RenderTarget>;\n\n /** @internal Body of the pass (issues GPU work). Set via `setRenderPassExecuteFunc`. */\n _executeFunc: RenderPassExecuteFunc | null;\n /** @internal Optional per-frame preparation that runs before `_executeFunc`. */\n _beforeExecute: (() => void) | null;\n\n /** Called once after every task has recorded. Use to build caches that\n * depend on RT textures being allocated (RenderPass builds its\n * `GPURenderPassDescriptor` here). May be a no-op. */\n /** @internal */\n _initialize(): void;\n\n /** Called once per frame by `_executeTask()`. Performs this pass's concrete\n * GPU work and returns the number of draw calls issued. */\n /** @internal */\n _execute(): number;\n\n /** @internal Free pass-owned GPU/CPU state. Idempotent. */\n _dispose(): void;\n}\n\n/** Add one or more render-target dependencies to the pass. Idempotent\n * (Set semantics). Mirrors BJS `FrameGraphRenderPass.addDependencies`,\n * promoted onto the base `Pass` because every future pass type\n * (compute / copy / object-list) needs the same surface. */\nexport function addPassDependencies(pass: Pass, deps: RenderTarget | readonly RenderTarget[]): void {\n if (Array.isArray(deps)) {\n for (const dep of deps) {\n pass._dependencies.add(dep);\n }\n } else {\n pass._dependencies.add(deps as RenderTarget);\n }\n}\n\n/** Set the per-frame body of the pass. Mirrors BJS `setExecuteFunc`. */\nexport function setRenderPassExecuteFunc(pass: Pass, fn: RenderPassExecuteFunc): void {\n pass._executeFunc = fn;\n}\n\n/** Set optional per-frame preparation that runs before the pass body. */\nexport function setRenderPassBeforeExecute(pass: Pass, fn: () => void): void {\n pass._beforeExecute = fn;\n}\n","/**\n * RenderPass — a frame-graph pass that begins a render pass into its bound\n * `RenderTarget`, runs a user-supplied execute callback, then ends the pass.\n *\n * Modelled on Babylon.js' `FrameGraphRenderPass`, with two intentional\n * Lite-flavoured differences:\n * - No shared `FrameGraphRenderContext`. The pass owns its descriptor and\n * passes the live render-pass encoder directly to its base `_executeFunc`.\n * - No numeric `TextureHandle` indirection — `_renderTarget` /\n * `_renderTargetDepth` are `RenderTarget` references. The handle layer\n * lands later as part of texture virtualization; the call sites it will\n * touch are isolated to `setRenderPassRenderTarget` /\n * `setRenderPassRenderTargetDepth` and the `_initialize` body.\n *\n * Per-frame behavior (`_execute`):\n * 1. Patch the cached color attachment with this frame's `clearColor` /\n * `loadOp` and (in swapchain mode) the per-frame swap view.\n * 2. `enc = encoder.beginRenderPass(_renderPassDescriptor)`.\n * 3. `_executeFunc(enc)` issues the actual draws (or skipped if unset).\n * 4. `enc.end()`.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { addPassDependencies, type Pass } from \"./pass.js\";\nimport type { Task } from \"./task.js\";\n\n/** A frame-graph pass that begins a render pass into its bound `RenderTarget`, runs an execute callback, then ends the pass. */\nexport interface RenderPass extends Pass {\n /** @internal Color render target. `null` until set via `setRenderPassRenderTarget`. */\n _renderTarget: RenderTarget | null;\n\n /** Optional separate depth target. When `null`, the depth view is taken\n * from `_renderTarget` (today's combined-RT behavior). Mirrors BJS'\n * `setRenderTargetDepth`. */\n /** @internal */\n _renderTargetDepth: RenderTarget | null;\n\n /** Cached descriptor + attachments — built once in `_initialize`, then\n * patched per-frame in `_execute` for swapchain mode + clearColor +\n * loadOp. */\n /** @internal */\n _renderPassDescriptor: GPURenderPassDescriptor;\n /** @internal */\n _colorAttachment: GPURenderPassColorAttachment | null;\n /** @internal */\n _depthAttachment: GPURenderPassDepthStencilAttachment | null;\n\n /** Per-frame mutable state. RenderTask mirrors live scene state\n * (e.g. `scene.clearColor` for auto-filled tasks) into these fields\n * before iterating its passes. */\n clearColor: GPUColorDict;\n /** True → loadOp `\"clear\"`, false → `\"load\"` (overlay mode). */\n clear: boolean;\n\n /** @internal Cached at descriptor build — `_renderTarget.descriptor.resolveToSwapchain`. */\n _swapchain: boolean;\n /** @internal Cached at descriptor build — `_renderTarget.descriptor.sampleCount`. */\n _sampleCount: number;\n}\n\nconst DEFAULT_CLEAR_COLOR: GPUColorDict = { r: 0.2, g: 0.2, b: 0.3, a: 1.0 };\n\n/** Create a new render pass owned by `task` and append it to `task._passes`.\n * The pass is empty — the caller must wire its render target\n * (`setRenderPassRenderTarget`), execute body (`setRenderPassExecuteFunc`),\n * and clear state before the frame graph initializes / executes. */\nexport function createRenderPass(name: string, task: Task): RenderPass {\n const pass: RenderPass = {\n name,\n _parentTask: task,\n _dependencies: new Set<RenderTarget>(),\n _renderTarget: null,\n _renderTargetDepth: null,\n _renderPassDescriptor: { colorAttachments: [] },\n _colorAttachment: null,\n _depthAttachment: null,\n clearColor: { ...DEFAULT_CLEAR_COLOR },\n clear: true,\n _swapchain: false,\n _sampleCount: 1,\n _executeFunc: null,\n _beforeExecute: null,\n _initialize(): void {\n // Assemble the cached `GPURenderPassDescriptor` and color/depth\n // attachments from the bound RTs.\n const rt = pass._renderTarget;\n if (!rt) {\n throw new Error(`RenderPass \"${pass.name}\": render target not set`);\n }\n const swapchain = rt._descriptor.resolveToSwapchain === true;\n const colorView = rt._colorView;\n let colorAttachment: GPURenderPassColorAttachment | null = null;\n if (colorView || swapchain) {\n colorAttachment = {\n view: colorView!,\n loadOp: pass.clear ? \"clear\" : \"load\",\n storeOp: \"store\",\n clearValue: pass.clearColor,\n };\n }\n const depthRt = pass._renderTargetDepth ?? rt;\n const depthFormat = depthRt._descriptor.depthStencilFormat;\n const depthView = depthRt._depthView;\n const hasStencil = depthFormat ? depthFormat === \"depth24plus-stencil8\" || depthFormat === \"depth32float-stencil8\" || depthFormat === \"stencil8\" : false;\n let depthAttachment: GPURenderPassDepthStencilAttachment | null = null;\n if (depthView) {\n depthAttachment = {\n view: depthView,\n depthClearValue: depthRt._descriptor._depthClearValue ?? 0,\n depthLoadOp: \"clear\",\n depthStoreOp: \"store\",\n ...(hasStencil ? { stencilClearValue: 0, stencilLoadOp: \"clear\" as const, stencilStoreOp: \"store\" as const } : {}),\n };\n }\n pass._colorAttachment = colorAttachment;\n pass._depthAttachment = depthAttachment;\n pass._renderPassDescriptor = {\n label: pass.name,\n colorAttachments: colorAttachment ? [colorAttachment] : [],\n depthStencilAttachment: depthAttachment ?? undefined,\n };\n pass._swapchain = swapchain;\n pass._sampleCount = rt._descriptor.sampleCount ?? 1;\n },\n _execute(): number {\n const rt = pass._renderTarget;\n if (!rt) {\n return 0;\n }\n pass._beforeExecute?.();\n const eng = pass._parentTask.engine as EngineContext;\n const att = pass._colorAttachment;\n if (att) {\n att.clearValue = pass.clearColor;\n att.loadOp = pass.clear ? \"clear\" : \"load\";\n if (pass._swapchain) {\n const swapView = eng._swapchainView;\n if (pass._sampleCount > 1) {\n att.resolveTarget = swapView;\n } else {\n att.view = swapView;\n }\n }\n }\n const enc = eng._currentEncoder.beginRenderPass(pass._renderPassDescriptor);\n let draws = 0;\n if (pass._executeFunc) {\n draws = pass._executeFunc(enc);\n }\n enc.end();\n return draws;\n },\n _dispose(): void {\n pass._renderTarget = null;\n pass._renderTargetDepth = null;\n pass._colorAttachment = null;\n pass._depthAttachment = null;\n pass._renderPassDescriptor = { colorAttachments: [] };\n pass._executeFunc = null;\n pass._beforeExecute = null;\n pass._dependencies.clear();\n },\n };\n task._passes.push(pass);\n return pass;\n}\n\n/** Set the color render target. Mirrors BJS `setRenderTarget`. */\nexport function setRenderPassRenderTarget(pass: RenderPass, rt: RenderTarget): void {\n pass._renderTarget = rt;\n addPassDependencies(pass, rt);\n}\n\n/** Set an optional separate depth render target. Mirrors BJS\n * `setRenderTargetDepth`. When unset, depth comes from the color RT. */\nexport function setRenderPassRenderTargetDepth(pass: RenderPass, rt: RenderTarget): void {\n pass._renderTargetDepth = rt;\n addPassDependencies(pass, rt);\n}\n\n/** Set color clear/load state. `clear === true` → loadOp `\"clear\"`,\n * `false` → `\"load\"` (overlay mode — keeps previous attachment contents). */\nexport function setRenderPassClear(pass: RenderPass, clear: boolean, clearColor: GPUColorDict): void {\n pass.clear = clear;\n pass.clearColor = clearColor;\n}\n","import type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Task } from \"./task.js\";\nimport type { FrameGraph } from \"./frame-graph.js\";\nimport { _appendTask } from \"./frame-graph.js\";\nimport type { RenderPass } from \"./render-pass.js\";\nimport { createRenderPass } from \"./render-pass.js\";\n\nfunction isFrameGraph(value: unknown): value is FrameGraph {\n return typeof value === \"object\" && value !== null && \"_tasks\" in value;\n}\n\nfunction resolveFg(target: FrameGraph | SceneContext): FrameGraph {\n if (isFrameGraph(target)) {\n return target;\n }\n if (\"_frameGraph\" in target && isFrameGraph(target._frameGraph)) {\n return target._frameGraph;\n }\n throw new Error(\"FrameGraph target does not expose a frame graph.\");\n}\n\n/** Add a task at the END of execute order. Accepts the scene's frame graph directly,\n * or a SceneContext (the scene's default frame graph is used). */\nexport function addTask(target: FrameGraph | SceneContext, task: Task): void {\n _appendTask(resolveFg(target), task);\n}\n\n/** Insert a task at the START of user execute order. Built-in system tasks that must\n * precede all user work, such as the shadow adapter, keep their leading slot. */\nexport function addTaskAtStart(target: FrameGraph | SceneContext, task: Task): void {\n const fg = resolveFg(target);\n const firstUserTask = fg._tasks[0]?.name === \"shadow\" ? 1 : 0;\n fg._tasks.splice(firstUserTask, 0, task);\n}\n\n/** Insert a task BEFORE another task in execute order. Accepts a FrameGraph or a SceneContext. */\nexport function addTaskBefore(target: FrameGraph | SceneContext, task: Task, before: Task): void {\n const fg = resolveFg(target);\n const i = fg._tasks.indexOf(before);\n if (i < 0) {\n fg._tasks.push(task);\n } else {\n fg._tasks.splice(i, 0, task);\n }\n}\n\n/** Create a `RenderPass`, wire it to the task currently recording, and return\n * it. Must be called from inside `Task.record()` so the FG can associate the\n * new pass with the right task (mirrors BJS `frameGraph.addRenderPass`).\n *\n * Configure the returned pass with `setRenderPassRenderTarget`,\n * `setRenderPassExecuteFunc`, etc. before the FG finishes building. */\nexport function addRenderPass(target: FrameGraph | SceneContext, name: string): RenderPass {\n const fg = resolveFg(target);\n const task = fg._currentProcessedTask;\n if (!task) {\n throw new Error(`addRenderPass(\"${name}\"): no task is currently recording (called outside Task.record?)`);\n }\n return createRenderPass(name, task);\n}\n","import { registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport { createFrameGraph } from \"./frame-graph.js\";\nimport type { FrameGraph } from \"./frame-graph.js\";\n\n/** Options for a standalone frame-graph rendering context. */\nexport interface FrameGraphContextOptions {\n /** Label used for diagnostics and GPU resource naming. */\n name?: string;\n /** Context clear color metadata; individual tasks still control their own render-target clears. */\n clearColor?: GPUColorDict;\n /** Per-frame callback invoked before the frame graph executes; use it to update uniforms or other task inputs. */\n update?: (deltaMs: number) => void;\n}\n\n/** A scene-less rendering context driven directly by a FrameGraph. */\nexport interface FrameGraphContext extends RenderingContext {\n readonly name: string;\n readonly engine: EngineContext;\n readonly frameGraph: FrameGraph;\n clearColor: GPUColorDict;\n}\n\ninterface FrameGraphContextInternal extends FrameGraphContext {\n readonly _engine: EngineContext;\n _disposed: boolean;\n}\n\n/** Create a scene-less frame-graph context for fullscreen effects and post-process chains. */\nexport function createFrameGraphContext(engine: EngineContext, options?: FrameGraphContextOptions): FrameGraphContext {\n const eng = engine as EngineContext;\n const update = options?.update;\n const ctx: FrameGraphContextInternal = {\n name: options?.name ?? \"frame-graph\",\n engine,\n _engine: eng,\n frameGraph: createFrameGraph(eng),\n clearColor: options?.clearColor ?? { r: 0, g: 0, b: 0, a: 1 },\n _drawCallsPre: 0,\n _disposed: false,\n _update(): void {\n if (ctx._disposed) {\n return;\n }\n update?.(eng._currentDelta);\n },\n _record(): number {\n if (ctx._disposed) {\n return 0;\n }\n return ctx.frameGraph.execute();\n },\n _resize(): void {\n if (ctx._disposed) {\n return;\n }\n ctx.frameGraph.build();\n },\n };\n return ctx;\n}\n\n/** Build and register the standalone frame-graph context with its engine. */\nexport function registerFrameGraphContext(ctx: FrameGraphContext): void {\n const internal = ctx as FrameGraphContextInternal;\n if (internal._disposed) {\n return;\n }\n ctx.frameGraph.build();\n registerRenderingContext(internal._engine, ctx);\n}\n\n/** Unregister the standalone frame-graph context from its engine. */\nexport function unregisterFrameGraphContext(ctx: FrameGraphContext): void {\n const internal = ctx as FrameGraphContextInternal;\n unregisterRenderingContext(internal._engine, ctx);\n}\n\n/** Unregister and dispose all GPU resources owned by the standalone frame graph. */\nexport function disposeFrameGraphContext(ctx: FrameGraphContext): void {\n const internal = ctx as FrameGraphContextInternal;\n if (internal._disposed) {\n return;\n }\n unregisterFrameGraphContext(ctx);\n ctx.frameGraph.dispose();\n internal._disposed = true;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { Task } from \"./task.js\";\n\n/** Source of the color image to post-process: a texture, a render target, or a getter returning one (resolved each record). */\nexport type ImageProcessingSource = Texture2D | RenderTarget | (() => Texture2D | RenderTarget | null | undefined);\n\n/** Configuration for `createImageProcessingTask`: the color source to apply exposure/contrast/tone-mapping to. */\nexport interface ImageProcessingTaskConfig {\n name?: string;\n source: ImageProcessingSource;\n}\n\ninterface ImageProcessingState {\n pipeline: GPURenderPipeline;\n bindGroup: GPUBindGroup;\n params: GPUBuffer;\n}\n\n/**\n * Create a frame-graph task that applies the scene's image-processing settings\n * (exposure, contrast, tone mapping) to a color source and draws it to the swapchain.\n * @param config - The color source to process.\n * @param engine - The owning engine.\n * @param scene - The scene whose `imageProcessing` settings drive the effect.\n * @returns The task to add to the frame graph.\n */\nexport function createImageProcessingTask(config: ImageProcessingTaskConfig, engine: EngineContext, scene: SceneContext): Task {\n let state: ImageProcessingState | null = null;\n const task: Task = {\n name: config.name ?? \"image-processing\",\n engine,\n scene,\n _passes: [],\n record(): void {\n disposeImageProcessingState(state);\n state = createImageProcessingState(engine, config.source);\n },\n execute(): number {\n if (!state) {\n return 0;\n }\n const img = scene.imageProcessing as { exposure: number; contrast: number; toneMappingEnabled: boolean | number };\n const data = new Float32Array([img.exposure, img.contrast, img.toneMappingEnabled === true ? 1 : 0, 0]);\n engine._device.queue.writeBuffer(state.params, 0, data);\n const pass = engine._currentEncoder.beginRenderPass({\n colorAttachments: [\n {\n view: engine._swapchainView,\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: scene.clearColor,\n },\n ],\n });\n pass.setPipeline(state.pipeline);\n pass.setBindGroup(0, state.bindGroup);\n pass.draw(3);\n pass.end();\n return 1;\n },\n dispose(): void {\n disposeImageProcessingState(state);\n state = null;\n this._passes.length = 0;\n },\n };\n return task;\n}\n\nfunction createImageProcessingState(engine: EngineContext, source: ImageProcessingSource): ImageProcessingState {\n const texture = resolveImageProcessingTexture(source);\n if (!texture) {\n throw new Error(\"Image processing source has no color texture\");\n }\n const device = engine._device;\n const sampleCount = (texture as { sampleCount?: number }).sampleCount ?? 1;\n const multisampled = sampleCount > 1;\n const params = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });\n const bgl = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: multisampled ? \"unfilterable-float\" : \"float\", multisampled } },\n ],\n });\n const common = `struct P{e:f32,c:f32,t:f32,p:f32}\n@group(0)@binding(0)var<uniform> p:P;\n@vertex fn vs(@builtin(vertex_index)i:u32)->@builtin(position) vec4f{var a=array<vec2f,3>(vec2f(-1,-3),vec2f(3,1),vec2f(-1,1));return vec4f(a[i],0,1);}\nfn ip(r:vec4f)->vec4f{var c=r.rgb*p.e;\nif(p.t>0.5){c=1.0-exp2(-1.590579*c);}\nc=clamp(pow(max(c,vec3f(0)),vec3f(1/2.2)),vec3f(0),vec3f(1));\nlet h=c*c*(3.0-2.0*c);\nif(p.c<1.0){c=mix(vec3f(0.5),c,p.c);}else{c=mix(c,h,p.c-1.0);}\nreturn vec4f(max(c,vec3f(0)),r.a);}`;\n const textureDecl = multisampled ? `@group(0)@binding(1)var s:texture_multisampled_2d<f32>;` : `@group(0)@binding(1)var s:texture_2d<f32>;`;\n const fragment = multisampled\n ? `@fragment fn fs(@builtin(position) q:vec4f)->@location(0) vec4f{let d=textureDimensions(s);let px=clamp(vec2i(q.xy),vec2i(0),vec2i(d)-1);let n=textureNumSamples(s);var c=vec4f(0);for(var i=0u;i<n;i++){c+=ip(textureLoad(s,px,i));}return c/f32(n);}`\n : `@fragment fn fs(@builtin(position) q:vec4f)->@location(0) vec4f{let d=textureDimensions(s);return ip(textureLoad(s,clamp(vec2i(q.xy),vec2i(0),vec2i(d)-1),0));}`;\n const shader = device.createShaderModule({ code: `${common}${textureDecl}${fragment}` });\n const pipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [bgl] }),\n vertex: { module: shader, entryPoint: \"vs\" },\n fragment: { module: shader, entryPoint: \"fs\", targets: [{ format: engine.format }] },\n primitive: { topology: \"triangle-list\" },\n });\n const bindGroup = device.createBindGroup({\n layout: bgl,\n entries: [\n { binding: 0, resource: { buffer: params } },\n { binding: 1, resource: texture.createView() },\n ],\n });\n return { pipeline, bindGroup, params };\n}\n\nfunction resolveImageProcessingTexture(source: ImageProcessingSource): GPUTexture | null {\n const resolved = typeof source === \"function\" ? source() : source;\n if (!resolved) {\n return null;\n }\n if (\"_colorTexture\" in resolved) {\n return resolved._colorTexture;\n }\n return resolved.texture;\n}\n\nfunction disposeImageProcessingState(state: ImageProcessingState | null | undefined): void {\n state?.params.destroy();\n}\n","import type { Mesh } from \"../mesh/mesh.js\";\nimport type { ShadowGenerator } from \"../shadow/shadow-generator.js\";\n\nlet shadowTaskInputs: WeakMap<ShadowGenerator, readonly Mesh[]> | null = null;\nlet shadowTaskInputPreloader: ((shadowGenerator: ShadowGenerator, casterMeshes: readonly Mesh[]) => Promise<void>) | null = null;\n\nfunction getShadowTaskInputs(): WeakMap<ShadowGenerator, readonly Mesh[]> {\n shadowTaskInputs ??= new WeakMap<ShadowGenerator, readonly Mesh[]>();\n return shadowTaskInputs;\n}\n\n/** Register scene-owned shadow caster inputs for a generator. */\nexport function setShadowTaskCasterMeshes(shadowGenerator: ShadowGenerator, casterMeshes: readonly Mesh[]): void {\n getShadowTaskInputs().set(shadowGenerator, casterMeshes);\n if (shadowTaskInputPreloader) {\n void shadowTaskInputPreloader(shadowGenerator, casterMeshes);\n }\n}\n\n/** @internal */\nexport function _getShadowTaskCasterMeshes(shadowGenerator: ShadowGenerator): readonly Mesh[] | undefined {\n return shadowTaskInputs?.get(shadowGenerator);\n}\n\n/** @internal */\nexport function _setShadowTaskInputPreloader(preloader: (shadowGenerator: ShadowGenerator, casterMeshes: readonly Mesh[]) => Promise<void>): void {\n shadowTaskInputPreloader = preloader;\n}\n","/**\n * ShadowTask — scene-owned frame-graph dispatcher for shadow-map generation.\n *\n * Filter-specific renderer code is owned by each ShadowGenerator through\n * internal hooks, keeping this scheduler filter-agnostic.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { ShadowGenerator } from \"../shadow/shadow-generator.js\";\nimport type { Task } from \"./task.js\";\nimport { _getShadowTaskCasterMeshes, _setShadowTaskInputPreloader } from \"./shadow-inputs.js\";\n\n/** Scene-owned frame-graph task that schedules shadow-map generation across the scene's shadow generators. */\nexport interface ShadowTask extends Task {\n readonly name: \"shadow\";\n}\n\n/** @internal Create the scene-owned shadow scheduling adapter task. */\nexport function createShadowTask(engine: EngineContext, scene: SceneContext): ShadowTask {\n const shadowGenerators = new Set<ShadowGenerator>();\n _setShadowTaskInputPreloader(preloadShadowTaskInput);\n\n const task: ShadowTask = {\n name: \"shadow\",\n engine,\n scene,\n _passes: [],\n async _preload(): Promise<void> {\n const loads: Promise<void>[] = [];\n for (const light of scene.lights) {\n const sg = light.shadowGenerator;\n const casterMeshes = sg ? _getShadowTaskCasterMeshes(sg) : null;\n if (sg?._preloadShadowTask && casterMeshes) {\n shadowGenerators.add(sg);\n loads.push(sg._preloadShadowTask(casterMeshes));\n }\n }\n await Promise.all(loads);\n },\n record(): void {\n task._passes.length = 0;\n for (const light of scene.lights) {\n const sg = light.shadowGenerator;\n const casterMeshes = sg ? _getShadowTaskCasterMeshes(sg) : null;\n if (sg?._ensureShadowTaskState && casterMeshes) {\n shadowGenerators.add(sg);\n const state = sg._ensureShadowTaskState(engine, scene, casterMeshes);\n state._task.record();\n }\n }\n },\n execute(): number {\n let draws = 0;\n for (const light of scene.lights) {\n const sg = light.shadowGenerator;\n const casterMeshes = sg ? _getShadowTaskCasterMeshes(sg) : null;\n if (sg?._ensureShadowTaskState && sg._renderShadowMap && casterMeshes) {\n shadowGenerators.add(sg);\n const existing = sg._shadowTaskState ?? null;\n const state = sg._ensureShadowTaskState(engine, scene, casterMeshes);\n if (!existing || existing._casterMeshes !== casterMeshes) {\n state._task.record();\n }\n draws += sg._renderShadowMap(engine, state);\n }\n }\n return draws;\n },\n dispose(): void {\n task._passes.length = 0;\n for (const sg of shadowGenerators) {\n const state = sg._shadowTaskState;\n if (state) {\n state._task.dispose();\n sg._shadowTaskState = undefined;\n }\n }\n shadowGenerators.clear();\n },\n };\n return task;\n}\n\nasync function preloadShadowTaskInput(shadowGenerator: ShadowGenerator, casterMeshes: readonly Mesh[]): Promise<void> {\n await shadowGenerator._preloadShadowTask?.(casterMeshes);\n}\n","/**\n * GPU Resource Pool — ref-counted textures + deduplicated samplers.\n *\n * Texture ref counting: acquire increments, release decrements.\n * When count hits 0 the GPUTexture is destroyed.\n *\n * Sampler pool: identical descriptors return the same GPUSampler.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\n\n// ── Texture ref counting ─────────────────────────────────────\n\nlet _texRefs: WeakMap<GPUTexture, number> | null = null;\n\nfunction texRefs(): WeakMap<GPUTexture, number> {\n if (!_texRefs) {\n _texRefs = new WeakMap();\n }\n return _texRefs;\n}\n\n/** Increment ref count on a Texture2D. First acquire sets count to 1. */\nexport function acquireTexture(tex: Texture2D): void {\n const m = texRefs();\n m.set(tex.texture, (m.get(tex.texture) ?? 0) + 1);\n}\n\n/**\n * Decrement ref count on a Texture2D.\n * Calls `tex.texture.destroy()` when count reaches 0.\n * Returns true if the texture was destroyed.\n */\nexport function releaseTexture(tex: Texture2D): boolean {\n const m = texRefs();\n const c = (m.get(tex.texture) ?? 1) - 1;\n if (c <= 0) {\n tex.texture.destroy();\n m.delete(tex.texture);\n return true;\n }\n m.set(tex.texture, c);\n return false;\n}\n\n/** Increment ref count on a raw GPUTexture (for env textures). */\nexport function acquireGPUTexture(tex: GPUTexture): void {\n const m = texRefs();\n m.set(tex, (m.get(tex) ?? 0) + 1);\n}\n\n/** Decrement ref count on a raw GPUTexture. Destroys at 0. */\nexport function releaseGPUTexture(tex: GPUTexture): boolean {\n const m = texRefs();\n const c = (m.get(tex) ?? 1) - 1;\n if (c <= 0) {\n tex.destroy();\n m.delete(tex);\n return true;\n }\n m.set(tex, c);\n return false;\n}\n\n// ── Sampler deduplication ────────────────────────────────────\n\nlet _samplerCache: WeakMap<GPUDevice, Map<string, GPUSampler>> | null = null;\n\nfunction samplerKey(desc: GPUSamplerDescriptor): string {\n return `${desc.minFilter ?? \"nearest\"}:${desc.magFilter ?? \"nearest\"}:${desc.mipmapFilter ?? \"nearest\"}:${desc.addressModeU ?? \"clamp-to-edge\"}:${desc.addressModeV ?? \"clamp-to-edge\"}:${desc.addressModeW ?? \"clamp-to-edge\"}:${desc.maxAnisotropy ?? 1}`;\n}\n\n/** Get or create a deduplicated sampler. Same config → same GPUSampler. */\nexport function getOrCreateSampler(engine: EngineContext, desc: GPUSamplerDescriptor = {}): GPUSampler {\n const device = engine._device;\n if (!_samplerCache) {\n _samplerCache = new WeakMap();\n }\n let dc = _samplerCache.get(device);\n if (!dc) {\n dc = new Map();\n _samplerCache.set(device, dc);\n }\n const key = samplerKey(desc);\n let s = dc.get(key);\n if (!s) {\n s = device.createSampler(desc);\n dc.set(key, s);\n }\n return s;\n}\n\n/** Clear sampler cache for a device. */\nexport function clearSamplerCache(engine: EngineContext): void {\n const device = engine._device;\n _samplerCache?.delete(device);\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { getOrCreateSampler } from \"./gpu-pool.js\";\n\n// Static descriptors for the canned sampler helpers — declared once at module\n// scope so each call to getXxxSampler reuses the same object (no per-call alloc).\nconst _nearestDesc: GPUSamplerDescriptor = { magFilter: \"nearest\", minFilter: \"nearest\" };\nconst _bilinearDesc: GPUSamplerDescriptor = { magFilter: \"linear\", minFilter: \"linear\" };\nconst _trilinearDesc: GPUSamplerDescriptor = { magFilter: \"linear\", minFilter: \"linear\", mipmapFilter: \"linear\" };\n\n/** Nearest-neighbor sampler (mag/min: nearest, no mipmap). All other descriptor fields use WebGPU defaults. */\nexport function getNearestSampler(engine: EngineContext): GPUSampler {\n return getOrCreateSampler(engine, _nearestDesc);\n}\n\n/** Bilinear sampler (mag/min: linear, no mipmap). All other descriptor fields use WebGPU defaults. */\nexport function getBilinearSampler(engine: EngineContext): GPUSampler {\n return getOrCreateSampler(engine, _bilinearDesc);\n}\n\n/** Trilinear sampler (mag/min/mipmap: linear). All other descriptor fields use WebGPU defaults. */\nexport function getTrilinearSampler(engine: EngineContext): GPUSampler {\n return getOrCreateSampler(engine, _trilinearDesc);\n}\n","/**\n * Render-to-texture helper — eager allocation of a render target's GPU\n * textures so the color attachment, or depth attachment for depth-only targets,\n * can be exposed as a sampled texture BEFORE the frame graph is built.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getBilinearSampler, getNearestSampler } from \"../resource/samplers.js\";\nimport type { RenderTarget, RenderTargetDescriptor } from \"../engine/render-target.js\";\nimport { createRenderTarget, buildRenderTarget } from \"../engine/render-target.js\";\nimport type { Texture2D } from \"./texture-2d.js\";\n\n/** Eagerly allocate a render target's GPU textures and return a sampled-texture\n * view of the color attachment, or the depth attachment for depth-only targets.\n * Marks the RT so `buildRenderTarget` won't realloc.\n *\n * The descriptor's size MUST be fixed (not `\"canvas\"`) because the canvas size\n * may change before the frame graph builds, which would invalidate the eagerly-\n * created texture handle that downstream bind groups have already captured. */\nexport function createRenderTargetTexture(engine: EngineContext, descriptor: RenderTargetDescriptor): { rt: RenderTarget; texture: Texture2D } {\n if (descriptor.size === \"canvas\") {\n throw new Error(\"createRenderTargetTexture: descriptor.size must be a fixed { width, height }, not 'canvas'.\");\n }\n const rt = createRenderTarget(descriptor);\n buildRenderTarget(rt, engine);\n rt._eager = true;\n if (!rt._colorTexture || !rt._colorView) {\n if (!rt._depthTexture) {\n throw new Error(\"createRenderTargetTexture: render target has no color or depth texture (resolveToSwapchain with sampleCount=1?).\");\n }\n const texture: Texture2D = {\n texture: rt._depthTexture,\n view: rt._depthTexture.createView({ aspect: \"depth-only\" }),\n sampler: getNearestSampler(engine),\n width: descriptor.size.width,\n height: descriptor.size.height,\n invertY: false,\n _sampleType: \"depth\",\n };\n return { rt, texture };\n }\n const texture: Texture2D = {\n texture: rt._colorTexture,\n view: rt._colorView,\n sampler: getBilinearSampler(engine),\n width: descriptor.size.width,\n height: descriptor.size.height,\n invertY: false,\n };\n return { rt, texture };\n}\n","import { registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport type { RenderTarget, RenderTargetSignature } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget, targetSignatureKey } from \"../engine/render-target.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { Task } from \"../frame-graph/task.js\";\n\nconst DEFAULT_VERTEX_WGSL = `struct EffectVertexOutput{@builtin(position) position:vec4<f32>,@location(0) uv:vec2<f32>};\n@vertex fn effectFullscreenVertex(@builtin(vertex_index) vertexIndex:u32)->EffectVertexOutput{var positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-1.0),vec2<f32>(3.0,-1.0),vec2<f32>(-1.0,3.0));let p=positions[vertexIndex];var out:EffectVertexOutput;out.position=vec4<f32>(p,0.0,1.0);out.uv=p*0.5+vec2<f32>(0.5,0.5);return out;}`;\n\n/** Kind of GPU binding an effect exposes: a uniform buffer, a sampled texture, or a sampler. */\nexport type EffectBindingKind = \"uniform\" | \"texture\" | \"sampler\";\n\n/** Describes a single bind-group entry (binding slot, kind, and type details) for an effect wrapper. */\nexport interface EffectBindingLayout {\n name?: string;\n binding: number;\n kind: EffectBindingKind;\n visibility?: GPUShaderStageFlags;\n uniformByteLength?: number;\n textureSampleType?: GPUTextureSampleType;\n samplerType?: GPUSamplerBindingType;\n textureBinding?: string | number;\n}\n\n/** Configuration for `createEffectWrapper`: the fullscreen fragment shader plus optional vertex shader, bindings, and blend state. */\nexport interface EffectWrapperOptions {\n name?: string;\n fragmentWGSL: string;\n vertexWGSL?: string;\n bindings?: EffectBindingLayout[];\n blend?: GPUBlendState;\n}\n\ninterface EffectUniformSlot {\n readonly layout: EffectBindingLayout;\n buffer: GPUBuffer;\n byteLength: number;\n}\n\ninterface EffectTextureSlot {\n readonly layout: EffectBindingLayout;\n texture: Texture2D | null;\n}\n\n/** A reusable fullscreen effect: owns its shader module, bind-group layout, pipelines, and uniform/texture slots. */\nexport interface EffectWrapper {\n readonly name: string;\n readonly options: EffectWrapperOptions;\n}\n\ninterface EffectWrapperInternal extends EffectWrapper {\n _engine: EngineContext;\n _shader: GPUShaderModule | null;\n _bindGroupLayout: GPUBindGroupLayout | null;\n _pipelineLayout: GPUPipelineLayout | null;\n _bindGroup: GPUBindGroup | null;\n _bindGroupDirty: boolean;\n _pipelines: Map<string, GPURenderPipeline> | null;\n _uniforms: EffectUniformSlot[];\n _textures: EffectTextureSlot[];\n}\n\n/** Configuration for `createEffectRenderTask`: the effect to draw, its render target, and optional clear state. */\nexport interface EffectRenderTaskConfig {\n name: string;\n effect: EffectWrapper;\n target: RenderTarget;\n clear?: boolean;\n clearColor?: GPUColorDict;\n}\n\n/** A frame-graph task that renders an `EffectWrapper` as a fullscreen pass into an offscreen `RenderTarget`. */\nexport interface EffectRenderTask extends Task {\n readonly name: string;\n /** @internal */\n readonly _config: EffectRenderTaskConfig;\n /** @internal */\n readonly _rt: RenderTarget;\n}\n\ninterface EffectRenderTaskInternal extends EffectRenderTask {\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n}\n\n// ─── Direct swapchain renderer (no scene / frame graph required) ─────────────\n\n/** Options for `createEffectRenderer`. */\nexport interface EffectRendererOptions {\n /** Label for GPU resources. Defaults to the effect's own name. */\n name?: string;\n /** Whether to clear the swapchain before drawing. Defaults to `true`. */\n clear?: boolean;\n /** Clear colour. Defaults to opaque black. */\n clearColor?: GPUColorDict;\n /**\n * Per-frame callback invoked just before the effect is drawn, receiving the\n * frame delta in milliseconds. Use it to update uniforms (e.g. time, animation\n * state). This is the effect-path equivalent of a scene's `onBeforeRender`.\n */\n update?: (deltaMs: number) => void;\n}\n\n/**\n * `EffectRenderer` — a fullscreen-effect `RenderingContext` that draws\n * directly to the swapchain without a `SceneContext` or frame-graph task.\n * Use `registerEffectRenderer` / `unregisterEffectRenderer` to attach it to\n * an engine, then call `startEngine` as usual.\n *\n * For offscreen render-to-texture workflows (effect result consumed by a\n * scene material) continue to use `createEffectRenderTask` inside a scene\n * frame graph.\n */\nexport interface EffectRenderer extends RenderingContext {\n readonly name: string;\n}\n\ninterface EffectRendererInternal extends EffectRenderer {\n _engine: EngineContext;\n _effect: EffectWrapperInternal;\n _clear: boolean;\n _rt: RenderTarget;\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n _disposed: boolean;\n}\n\n/**\n * Create an `EffectWrapper` for the given engine, allocating uniform buffers and\n * texture slots from `options.bindings`.\n * @param engine - The engine that owns the GPU resources.\n * @param options - Shader source and binding layout for the effect.\n * @returns The new effect wrapper.\n */\nexport function createEffectWrapper(engine: EngineContext, options: EffectWrapperOptions): EffectWrapper {\n const eng = engine as EngineContext;\n const wrapper: EffectWrapperInternal = {\n name: options.name ?? \"effect-wrapper\",\n options,\n _engine: eng,\n _shader: null,\n _bindGroupLayout: null,\n _pipelineLayout: null,\n _bindGroup: null,\n _bindGroupDirty: true,\n _pipelines: null,\n _uniforms: [],\n _textures: [],\n };\n createBindingSlots(wrapper);\n return wrapper;\n}\n\n/**\n * Write data into the effect's uniform buffer(s). Pass a single buffer to write the\n * wrapper's only uniform slot, or a record keyed by binding name/index to write specific slots.\n * @param wrapper - The effect wrapper to update.\n * @param data - The uniform bytes, or a map of binding key to uniform bytes.\n */\nexport function setEffectUniforms(wrapper: EffectWrapper, data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): void {\n const internal = wrapper as EffectWrapperInternal;\n if (isBufferData(data)) {\n const slot = internal._uniforms[0];\n if (!slot) {\n throw new Error(\"setEffectUniforms: wrapper has no uniform binding.\");\n }\n writeUniformSlot(internal, slot, data);\n return;\n }\n for (const key of Object.keys(data)) {\n const slot = findUniformSlot(internal, key);\n if (!slot) {\n throw new Error(`setEffectUniforms: unknown uniform binding \"${key}\".`);\n }\n writeUniformSlot(internal, slot, data[key]!);\n }\n}\n\n/**\n * Bind a texture to one of the effect's texture slots, marking the bind group dirty so it is rebuilt.\n * @param wrapper - The effect wrapper to update.\n * @param bindingNameOrIndex - The texture binding's name or numeric index.\n * @param texture - The texture to bind.\n */\nexport function setEffectTexture(wrapper: EffectWrapper, bindingNameOrIndex: string | number, texture: Texture2D): void {\n const internal = wrapper as EffectWrapperInternal;\n const slot = findTextureSlot(internal, bindingNameOrIndex);\n if (!slot) {\n throw new Error(`setEffectTexture: unknown texture binding \"${String(bindingNameOrIndex)}\".`);\n }\n slot.texture = texture;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create a frame-graph task that draws an effect as a fullscreen pass into `config.target`.\n * @param config - The effect, target, and clear settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The render task to add to a frame graph.\n */\nexport function createEffectRenderTask(config: EffectRenderTaskConfig, engine: EngineContext, scene?: SceneContext): EffectRenderTask {\n const eng = engine as EngineContext;\n const effect = config.effect as EffectWrapperInternal;\n const rt = config.target;\n config.clearColor ??= { r: 0, g: 0, b: 0, a: 1 };\n const sampleCount = rt._descriptor.sampleCount ?? 1;\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.colorFormat,\n _sampleCount: sampleCount,\n };\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const task: EffectRenderTaskInternal = {\n name: config.name,\n _config: config,\n engine: eng,\n scene,\n _passes: [],\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: { label: config.name, colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n record(): void {\n buildRenderTarget(rt, eng);\n task._pipeline = getEffectPipeline(effect, task._targetSignature);\n task._bindGroup = getEffectBindGroup(effect);\n },\n execute(): number {\n const pipeline = task._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderTask \"${task.name}\" executed before record().`);\n }\n task._bindGroup = getEffectBindGroup(effect);\n applyColorAttachmentState(task._colorAttachment, rt, eng, task._config.clear !== false, task._config.clearColor!);\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (task._bindGroup) {\n pass.setBindGroup(0, task._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n dispose(): void {\n task._passes.length = 0;\n disposeRenderTarget(task._rt);\n task._pipeline = null;\n task._bindGroup = null;\n },\n };\n return task;\n}\n\n/** Destroy the uniform buffers and clear the cached pipelines, bind groups, and slots owned by the effect wrapper. */\nexport function disposeEffectWrapper(wrapper: EffectWrapper): void {\n const internal = wrapper as EffectWrapperInternal;\n for (const slot of internal._uniforms) {\n slot.buffer.destroy();\n }\n internal._uniforms.length = 0;\n internal._textures.length = 0;\n internal._pipelines?.clear();\n internal._pipelines = null;\n internal._shader = null;\n internal._bindGroupLayout = null;\n internal._pipelineLayout = null;\n internal._bindGroup = null;\n internal._bindGroupDirty = true;\n}\n\n/**\n * Create an `EffectRenderer` that draws `effect` as a fullscreen pass to the\n * swapchain each frame. The renderer owns a swapchain `RenderTarget` and\n * implements `RenderingContext` directly — no `SceneContext` is needed.\n *\n * Call `registerEffectRenderer` to start rendering, `unregisterEffectRenderer`\n * to pause, and `disposeEffectRenderer` to free GPU resources.\n */\nexport function createEffectRenderer(engine: EngineContext, effect: EffectWrapper, options?: EffectRendererOptions): EffectRenderer {\n const eng = engine as EngineContext;\n const ew = effect as EffectWrapperInternal;\n const name = options?.name ?? effect.name;\n const clear = options?.clear !== false;\n const clearColor: GPUColorDict = options?.clearColor ?? { r: 0, g: 0, b: 0, a: 1 };\n const update = options?.update;\n\n const rt = createRenderTarget({\n label: `${name}-swapchain`,\n colorFormat: eng.format,\n sampleCount: eng.msaaSamples,\n size: \"canvas\",\n resolveToSwapchain: true,\n });\n\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.colorFormat,\n _sampleCount: rt._descriptor.sampleCount ?? 1,\n };\n\n const colorAttachment: GPURenderPassColorAttachment = {\n view: undefined!,\n loadOp: \"clear\",\n storeOp: \"store\",\n };\n const renderPassDescriptor: GPURenderPassDescriptor = { label: name, colorAttachments: [colorAttachment] };\n\n const er: EffectRendererInternal = {\n name,\n clearColor,\n _drawCallsPre: 0,\n _engine: eng,\n _effect: ew,\n _clear: clear,\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: renderPassDescriptor,\n _colorAttachment: colorAttachment,\n _pipeline: null,\n _bindGroup: null,\n _disposed: false,\n _update(): void {\n update?.(eng._currentDelta);\n },\n _record(): number {\n if (er._disposed) {\n return 0;\n }\n ensureRtCanvasSize(er._rt, er._engine);\n applyColorAttachmentState(er._colorAttachment, er._rt, er._engine, er._clear, er.clearColor);\n const encoder = er._engine._currentEncoder;\n if (!encoder) {\n return 0;\n }\n const pipeline = er._pipeline;\n if (!pipeline) {\n throw new Error(`EffectRenderer \"${er.name}\" recorded before registerEffectRenderer().`);\n }\n const pass = encoder.beginRenderPass(er._renderPassDescriptor);\n pass.setPipeline(pipeline);\n if (er._bindGroup) {\n pass.setBindGroup(0, er._bindGroup);\n }\n pass.draw(3);\n pass.end();\n return 1;\n },\n _resize(): void {\n if (er._disposed) {\n return;\n }\n buildRenderTarget(er._rt, er._engine);\n },\n };\n return er;\n}\n\n/** Register the effect renderer with its engine. Idempotent — a second call is a no-op. */\nexport function registerEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n prepareEffectRenderer(internal);\n registerRenderingContext(internal._engine, er);\n}\n\n/** Unregister the effect renderer from its engine. No-op if not registered. */\nexport function unregisterEffectRenderer(er: EffectRenderer): void {\n unregisterRenderingContext((er as EffectRendererInternal)._engine, er);\n}\n\n/** Unregister and free all GPU resources owned by the renderer. */\nexport function disposeEffectRenderer(er: EffectRenderer): void {\n const internal = er as EffectRendererInternal;\n if (internal._disposed) {\n return;\n }\n unregisterEffectRenderer(er);\n disposeRenderTarget(internal._rt);\n internal._disposed = true;\n}\n\nfunction createBindingSlots(wrapper: EffectWrapperInternal): void {\n const layouts = [...(wrapper.options.bindings ?? [])].sort((a, b) => a.binding - b.binding);\n const seen = new Set<number>();\n for (const layout of layouts) {\n if (seen.has(layout.binding)) {\n throw new Error(`createEffectWrapper: duplicate binding ${layout.binding}.`);\n }\n seen.add(layout.binding);\n if (layout.kind === \"uniform\") {\n const byteLength = align4(layout.uniformByteLength ?? 16);\n const buffer = wrapper._engine._device.createBuffer({\n label: `${wrapper.name}-${layout.name ?? layout.binding}-ubo`,\n size: byteLength,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n wrapper._uniforms.push({ layout, buffer, byteLength });\n } else if (layout.kind === \"texture\") {\n wrapper._textures.push({ layout, texture: null });\n }\n }\n}\n\nfunction applyColorAttachmentState(att: GPURenderPassColorAttachment, rt: RenderTarget, eng: EngineContext, clear: boolean, clearColor: GPUColorDict): void {\n att.clearValue = clearColor;\n att.loadOp = clear ? \"clear\" : \"load\";\n if (rt._descriptor.resolveToSwapchain === true) {\n if ((rt._descriptor.sampleCount ?? 1) > 1) {\n att.view = rt._colorView!;\n att.resolveTarget = eng._swapchainView;\n } else {\n att.view = eng._swapchainView;\n att.resolveTarget = undefined;\n }\n } else {\n att.view = rt._colorView!;\n att.resolveTarget = undefined;\n }\n}\n\nfunction ensureRtCanvasSize(rt: RenderTarget, eng: EngineContext): void {\n if (rt._descriptor.size !== \"canvas\") {\n return;\n }\n if (rt._width === eng.canvas.width && rt._height === eng.canvas.height) {\n return;\n }\n buildRenderTarget(rt, eng);\n}\n\nfunction getEffectPipeline(wrapper: EffectWrapperInternal, targetSignature: RenderTargetSignature): GPURenderPipeline {\n const key = targetSignatureKey(targetSignature);\n if (!wrapper._pipelines) {\n wrapper._pipelines = new Map();\n }\n const hit = wrapper._pipelines.get(key);\n if (hit) {\n return hit;\n }\n const device = wrapper._engine._device;\n const pipeline = device.createRenderPipeline({\n label: `${wrapper.name}-${key}`,\n layout: getPipelineLayout(wrapper),\n vertex: { module: getShaderModule(wrapper), entryPoint: \"effectFullscreenVertex\" },\n fragment: {\n module: getShaderModule(wrapper),\n entryPoint: \"effectFragment\",\n targets: [{ format: targetSignature._colorFormat!, blend: wrapper.options.blend }],\n },\n primitive: { topology: \"triangle-list\" },\n multisample: { count: targetSignature._sampleCount },\n });\n wrapper._pipelines.set(key, pipeline);\n return pipeline;\n}\n\nfunction getShaderModule(wrapper: EffectWrapperInternal): GPUShaderModule {\n if (!wrapper._shader) {\n wrapper._shader = wrapper._engine._device.createShaderModule({\n label: wrapper.name,\n code: `${wrapper.options.vertexWGSL ?? DEFAULT_VERTEX_WGSL}\\n${wrapper.options.fragmentWGSL}`,\n });\n }\n return wrapper._shader;\n}\n\nfunction getPipelineLayout(wrapper: EffectWrapperInternal): GPUPipelineLayout {\n if (!wrapper._pipelineLayout) {\n wrapper._pipelineLayout = wrapper._engine._device.createPipelineLayout({\n label: `${wrapper.name}-pipeline-layout`,\n bindGroupLayouts: [getBindGroupLayout(wrapper)],\n });\n }\n return wrapper._pipelineLayout;\n}\n\nfunction getBindGroupLayout(wrapper: EffectWrapperInternal): GPUBindGroupLayout {\n if (!wrapper._bindGroupLayout) {\n const entries = (wrapper.options.bindings ?? [])\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindingLayoutEntry(layout));\n wrapper._bindGroupLayout = wrapper._engine._device.createBindGroupLayout({\n label: `${wrapper.name}-bgl`,\n entries,\n });\n }\n return wrapper._bindGroupLayout;\n}\n\nfunction bindingLayoutEntry(layout: EffectBindingLayout): GPUBindGroupLayoutEntry {\n const visibility = layout.visibility ?? GPUShaderStage.FRAGMENT;\n if (layout.kind === \"uniform\") {\n return { binding: layout.binding, visibility, buffer: { type: \"uniform\" } };\n }\n if (layout.kind === \"texture\") {\n return { binding: layout.binding, visibility, texture: { sampleType: layout.textureSampleType ?? \"float\" } };\n }\n return { binding: layout.binding, visibility, sampler: { type: layout.samplerType ?? \"filtering\" } };\n}\n\nfunction getEffectBindGroup(wrapper: EffectWrapperInternal): GPUBindGroup | null {\n const bindings = wrapper.options.bindings ?? [];\n if (bindings.length === 0) {\n return null;\n }\n if (!wrapper._bindGroupDirty && wrapper._bindGroup) {\n return wrapper._bindGroup;\n }\n const entries = bindings\n .slice()\n .sort((a, b) => a.binding - b.binding)\n .map((layout) => bindGroupEntry(wrapper, layout));\n wrapper._bindGroup = wrapper._engine._device.createBindGroup({\n label: `${wrapper.name}-bg`,\n layout: getBindGroupLayout(wrapper),\n entries,\n });\n wrapper._bindGroupDirty = false;\n return wrapper._bindGroup;\n}\n\nfunction prepareEffectRenderer(er: EffectRendererInternal): void {\n er._pipeline ??= getEffectPipeline(er._effect, er._targetSignature);\n er._bindGroup = getEffectBindGroup(er._effect);\n}\n\nfunction bindGroupEntry(wrapper: EffectWrapperInternal, layout: EffectBindingLayout): GPUBindGroupEntry {\n if (layout.kind === \"uniform\") {\n const slot = findUniformSlot(wrapper, layout.binding);\n if (!slot) {\n throw new Error(`Effect \"${wrapper.name}\" missing uniform binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: { buffer: slot.buffer, size: slot.byteLength } };\n }\n if (layout.kind === \"texture\") {\n const slot = findTextureSlot(wrapper, layout.binding);\n if (!slot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: slot.texture.view };\n }\n const textureSlot = layout.textureBinding != null ? findTextureSlot(wrapper, layout.textureBinding) : wrapper._textures[0];\n if (!textureSlot?.texture) {\n throw new Error(`Effect \"${wrapper.name}\" missing texture for sampler binding ${layout.binding}.`);\n }\n return { binding: layout.binding, resource: textureSlot.texture.sampler };\n}\n\nfunction findUniformSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectUniformSlot | undefined {\n return wrapper._uniforms.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction findTextureSlot(wrapper: EffectWrapperInternal, bindingNameOrIndex: string | number): EffectTextureSlot | undefined {\n return wrapper._textures.find((slot) => matchesBinding(slot.layout, bindingNameOrIndex));\n}\n\nfunction matchesBinding(layout: EffectBindingLayout, bindingNameOrIndex: string | number): boolean {\n if (typeof bindingNameOrIndex === \"number\") {\n return layout.binding === bindingNameOrIndex;\n }\n return layout.name === bindingNameOrIndex || String(layout.binding) === bindingNameOrIndex;\n}\n\nfunction writeUniformSlot(wrapper: EffectWrapperInternal, slot: EffectUniformSlot, data: ArrayBuffer | ArrayBufferView): void {\n const bytes = toBytes(data);\n if (bytes.byteLength > slot.byteLength) {\n throw new Error(`writeUniformSlot: ${bytes.byteLength} bytes exceeds uniform binding ${slot.layout.binding} size ${slot.byteLength}.`);\n }\n wrapper._engine._device.queue.writeBuffer(slot.buffer, 0, bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n if (data instanceof ArrayBuffer) {\n return new Uint8Array(data);\n }\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n}\n\nfunction isBufferData(data: ArrayBuffer | ArrayBufferView | Record<string | number, ArrayBuffer | ArrayBufferView>): data is ArrayBuffer | ArrayBufferView {\n return data instanceof ArrayBuffer || ArrayBuffer.isView(data);\n}\n\nfunction align4(value: number): number {\n return (value + 3) & ~3;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget, RenderTargetSignature } from \"../engine/render-target.js\";\nimport { buildRenderTarget, disposeRenderTarget, targetSignatureKey } from \"../engine/render-target.js\";\nimport type { Task } from \"../frame-graph/task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\nconst DEFAULT_VERTEX_WGSL = `struct EffectVertexOutput{@builtin(position) position:vec4<f32>,@location(0) uv:vec2<f32>};\n@vertex fn effectFullscreenVertex(@builtin(vertex_index) vertexIndex:u32)->EffectVertexOutput{var positions=array<vec2<f32>,3>(vec2<f32>(-1.0,-1.0),vec2<f32>(3.0,-1.0),vec2<f32>(-1.0,3.0));let p=positions[vertexIndex];var out:EffectVertexOutput;out.position=vec4<f32>(p,0.0,1.0);out.uv=p*0.5+vec2<f32>(0.5,0.5);return out;}`;\n\n/** Configuration for a lightweight fullscreen effect with exactly one uniform buffer at bind group 0 / binding 0. */\nexport interface UniformEffectWrapperOptions {\n name?: string;\n fragmentWGSL: string;\n vertexWGSL?: string;\n uniformByteLength: number;\n}\n\n/** Lightweight reusable fullscreen effect with a single uniform buffer and no texture or sampler bindings. */\nexport interface UniformEffectWrapper {\n readonly name: string;\n readonly options: UniformEffectWrapperOptions;\n}\n\ninterface UniformEffectWrapperInternal extends UniformEffectWrapper {\n _engine: EngineContext;\n _shader: GPUShaderModule | null;\n _bindGroupLayout: GPUBindGroupLayout | null;\n _pipelineLayout: GPUPipelineLayout | null;\n _bindGroup: GPUBindGroup | null;\n _uniformBuffer: GPUBuffer;\n _uniformByteLength: number;\n}\n\n/** Configuration for `createUniformEffectRenderTask`: the uniform effect to draw, its render target, and optional clear state. */\nexport interface UniformEffectRenderTaskConfig {\n name: string;\n effect: UniformEffectWrapper;\n target: RenderTarget;\n clear?: boolean;\n clearColor?: GPUColorDict;\n}\n\n/** A frame-graph task that draws a `UniformEffectWrapper` as a fullscreen pass into a render target. */\nexport interface UniformEffectRenderTask extends Task {\n readonly name: string;\n /** @internal */\n readonly _config: UniformEffectRenderTaskConfig;\n /** @internal */\n readonly _rt: RenderTarget;\n}\n\ninterface UniformEffectRenderTaskInternal extends UniformEffectRenderTask {\n _targetSignature: RenderTargetSignature;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n _pipeline: GPURenderPipeline | null;\n}\n\n/**\n * Create a lightweight fullscreen effect with exactly one uniform buffer at binding 0.\n * @param engine - The engine that owns the GPU resources.\n * @param options - Shader source and uniform-buffer byte length.\n * @returns The new uniform effect wrapper.\n */\nexport function createUniformEffectWrapper(engine: EngineContext, options: UniformEffectWrapperOptions): UniformEffectWrapper {\n const eng = engine as EngineContext;\n const byteLength = align4(options.uniformByteLength);\n return {\n name: options.name ?? \"uniform-effect-wrapper\",\n options,\n _engine: eng,\n _shader: null,\n _bindGroupLayout: null,\n _pipelineLayout: null,\n _bindGroup: null,\n _uniformBuffer: eng._device.createBuffer({\n label: `${options.name ?? \"uniform-effect-wrapper\"}-ubo`,\n size: byteLength,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n }),\n _uniformByteLength: byteLength,\n } as UniformEffectWrapperInternal;\n}\n\n/**\n * Write bytes into the uniform effect's single uniform buffer.\n * @param wrapper - The uniform effect wrapper to update.\n * @param data - Uniform bytes to upload.\n */\nexport function setUniformEffectUniforms(wrapper: UniformEffectWrapper, data: ArrayBuffer | ArrayBufferView): void {\n const internal = wrapper as UniformEffectWrapperInternal;\n const bytes = toBytes(data);\n if (bytes.byteLength > internal._uniformByteLength) {\n throw new Error(`setUniformEffectUniforms: ${bytes.byteLength} bytes exceeds uniform size ${internal._uniformByteLength}.`);\n }\n internal._engine._device.queue.writeBuffer(internal._uniformBuffer, 0, bytes.buffer, bytes.byteOffset, bytes.byteLength);\n}\n\n/**\n * Create a frame-graph task that draws a uniform-only effect as a fullscreen pass into `config.target`.\n * @param config - The effect, target, and clear settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The render task to add to a frame graph.\n */\nexport function createUniformEffectRenderTask(config: UniformEffectRenderTaskConfig, engine: EngineContext, scene?: SceneContext): UniformEffectRenderTask {\n const eng = engine as EngineContext;\n const effect = config.effect as UniformEffectWrapperInternal;\n const rt = config.target;\n config.clearColor ??= { r: 0, g: 0, b: 0, a: 1 };\n const sampleCount = rt._descriptor.sampleCount ?? 1;\n const targetSignature: RenderTargetSignature = {\n _colorFormat: rt._descriptor.colorFormat,\n _sampleCount: sampleCount,\n };\n const colorAttachment = { loadOp: \"clear\", storeOp: \"store\" } as GPURenderPassColorAttachment;\n const task: UniformEffectRenderTaskInternal = {\n name: config.name,\n _config: config,\n engine: eng,\n scene,\n _passes: [],\n _rt: rt,\n _targetSignature: targetSignature,\n _renderPassDescriptor: { label: config.name, colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n _pipeline: null,\n record(): void {\n buildRenderTarget(rt, eng);\n task._pipeline = getUniformEffectPipeline(effect, task._targetSignature);\n },\n execute(): number {\n const pipeline = task._pipeline;\n if (!pipeline) {\n throw new Error(`UniformEffectRenderTask \"${task.name}\" executed before record().`);\n }\n applyColorAttachmentState(task._colorAttachment, rt, eng, task._config.clear !== false, task._config.clearColor!);\n const pass = eng._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, getUniformEffectBindGroup(effect));\n pass.draw(3);\n pass.end();\n return 1;\n },\n dispose(): void {\n task._passes.length = 0;\n disposeRenderTarget(task._rt);\n task._pipeline = null;\n },\n };\n return task;\n}\n\n/** Destroy the uniform buffer and clear cached GPU objects owned by the uniform effect wrapper. */\nexport function disposeUniformEffectWrapper(wrapper: UniformEffectWrapper): void {\n const internal = wrapper as UniformEffectWrapperInternal;\n internal._uniformBuffer.destroy();\n internal._shader = null;\n internal._bindGroupLayout = null;\n internal._pipelineLayout = null;\n internal._bindGroup = null;\n}\n\nfunction applyColorAttachmentState(att: GPURenderPassColorAttachment, rt: RenderTarget, eng: EngineContext, clear: boolean, clearColor: GPUColorDict): void {\n att.clearValue = clearColor;\n att.loadOp = clear ? \"clear\" : \"load\";\n if (rt._descriptor.resolveToSwapchain === true) {\n if ((rt._descriptor.sampleCount ?? 1) > 1) {\n att.view = rt._colorView!;\n att.resolveTarget = eng._swapchainView;\n } else {\n att.view = eng._swapchainView;\n att.resolveTarget = undefined;\n }\n } else {\n att.view = rt._colorView!;\n att.resolveTarget = undefined;\n }\n}\n\nfunction getUniformEffectPipeline(wrapper: UniformEffectWrapperInternal, targetSignature: RenderTargetSignature): GPURenderPipeline {\n const device = wrapper._engine._device;\n return device.createRenderPipeline({\n label: `${wrapper.name}-${targetSignatureKey(targetSignature)}`,\n layout: getPipelineLayout(wrapper),\n vertex: { module: getShaderModule(wrapper), entryPoint: \"effectFullscreenVertex\" },\n fragment: {\n module: getShaderModule(wrapper),\n entryPoint: \"effectFragment\",\n targets: [{ format: targetSignature._colorFormat! }],\n },\n primitive: { topology: \"triangle-list\" },\n multisample: { count: targetSignature._sampleCount },\n });\n}\n\nfunction getShaderModule(wrapper: UniformEffectWrapperInternal): GPUShaderModule {\n if (!wrapper._shader) {\n wrapper._shader = wrapper._engine._device.createShaderModule({\n label: wrapper.name,\n code: `${wrapper.options.vertexWGSL ?? DEFAULT_VERTEX_WGSL}\\n${wrapper.options.fragmentWGSL}`,\n });\n }\n return wrapper._shader;\n}\n\nfunction getPipelineLayout(wrapper: UniformEffectWrapperInternal): GPUPipelineLayout {\n if (!wrapper._pipelineLayout) {\n wrapper._pipelineLayout = wrapper._engine._device.createPipelineLayout({\n label: `${wrapper.name}-pipeline-layout`,\n bindGroupLayouts: [getBindGroupLayout(wrapper)],\n });\n }\n return wrapper._pipelineLayout;\n}\n\nfunction getBindGroupLayout(wrapper: UniformEffectWrapperInternal): GPUBindGroupLayout {\n if (!wrapper._bindGroupLayout) {\n wrapper._bindGroupLayout = wrapper._engine._device.createBindGroupLayout({\n label: `${wrapper.name}-bgl`,\n entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } }],\n });\n }\n return wrapper._bindGroupLayout;\n}\n\nfunction getUniformEffectBindGroup(wrapper: UniformEffectWrapperInternal): GPUBindGroup {\n if (!wrapper._bindGroup) {\n wrapper._bindGroup = wrapper._engine._device.createBindGroup({\n label: `${wrapper.name}-bg`,\n layout: getBindGroupLayout(wrapper),\n entries: [{ binding: 0, resource: { buffer: wrapper._uniformBuffer, size: wrapper._uniformByteLength } }],\n });\n }\n return wrapper._bindGroup;\n}\n\nfunction toBytes(data: ArrayBuffer | ArrayBufferView): Uint8Array {\n if (data instanceof ArrayBuffer) {\n return new Uint8Array(data);\n }\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n}\n\nfunction align4(value: number): number {\n return (value + 3) & ~3;\n}\n","import type { NormalizedViewport } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget, RenderTargetDescriptor, RenderTargetSignature } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget, targetSignatureKey } from \"../engine/render-target.js\";\nimport { getBilinearSampler, getNearestSampler } from \"../resource/samplers.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Task } from \"./task.js\";\n\n/** Source sampling filter for a post-process pass. */\nexport type PostProcessSamplingMode = \"nearest\" | \"linear\";\n/** Output blend mode: `0` opaque, `1` additive, `2` premultiplied, `7` non-premultiplied alpha. */\nexport type PostProcessAlphaMode = 0 | 1 | 2 | 7;\n\nexport interface PostProcessShaderConfig {\n fragmentWGSL: string;\n vertexOutputWGSL?: string;\n vertexMainWGSL?: string;\n fragmentWrapperWGSL?: string;\n uniformWGSL?: string;\n uniformByteLength?: number;\n uniformBinding?: number;\n writeUniforms?: (data: Float32Array) => void;\n extraTextureWGSL?: string;\n extraTextures?: readonly RenderTarget[];\n}\n\n/** Shared user-facing settings for a post-process pass: source/target textures, sampling, alpha mode, viewport, and clear. */\nexport interface PostProcessTaskSettings {\n name?: string;\n sourceTexture: RenderTarget;\n sourceSamplingMode?: PostProcessSamplingMode;\n targetTexture?: RenderTarget | null;\n alphaMode?: PostProcessAlphaMode;\n viewport?: NormalizedViewport | null;\n /** Clear the target before drawing. Set false when several viewport passes share a target. */\n clear?: boolean;\n}\n\nexport interface PostProcessTaskConfig extends PostProcessTaskSettings {\n /** @internal */\n _shader: PostProcessShaderConfig;\n}\n\n/** A fullscreen post-process pass that samples a source texture, applies a fragment shader, and writes to an output target. */\nexport interface PostProcessTask extends Task, PostProcessTaskSettings {\n readonly name: string;\n sourceSamplingMode: PostProcessSamplingMode;\n targetTexture: RenderTarget | null;\n alphaMode: PostProcessAlphaMode;\n viewport: NormalizedViewport | null;\n clear: boolean;\n outputTexture: RenderTarget;\n /** Recompute and upload the pass's uniform buffer from current settings. Call after mutating effect parameters. */\n updateUniforms(): void;\n /** @internal */\n readonly _shader: PostProcessShaderConfig;\n}\n\ninterface PostProcessTaskInternal extends PostProcessTask {\n _internalTarget: RenderTarget | null;\n _internalTargetKey: string;\n _pipeline: GPURenderPipeline | null;\n _bindGroup: GPUBindGroup | null;\n _bindGroupLayout: GPUBindGroupLayout | null;\n _pipelineLayout: GPUPipelineLayout | null;\n _shaderModule: GPUShaderModule | null;\n _shaderModuleCode: string;\n _uniformBuffer: GPUBuffer | null;\n _uniformData: Float32Array | null;\n _renderPassDescriptor: GPURenderPassDescriptor;\n _colorAttachment: GPURenderPassColorAttachment;\n}\n\nconst fullscreenVertexWGSL = (\n outputFlipY: boolean,\n extraOutput: string,\n extraMain: string\n) => `struct PostProcessVertexOutput{@builtin(position) position:vec4f,@location(0) uv:vec2f${extraOutput}}\n@vertex fn postProcessVertex(@builtin(vertex_index) vertexIndex:u32)->PostProcessVertexOutput{var positions=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));let p=positions[vertexIndex];var out:PostProcessVertexOutput;out.position=vec4f(p,0,1);out.uv=vec2f(p.x*0.5+0.5,${outputFlipY ? \"0.5-p.y*0.5\" : \"p.y*0.5+0.5\"});${extraMain}return out;}`;\n\nconst SOURCE_WGSL = `@group(0) @binding(0) var sourceSampler:sampler;\n@group(0) @binding(1) var sourceTextureSampler:texture_2d<f32>;\nfn samplePostProcessSource(uv:vec2f)->vec4f{return textureSample(sourceTextureSampler,sourceSampler,uv);}\nfn readPostProcessSource(uv:vec2f)->vec4f{let dims=vec2f(textureDimensions(sourceTextureSampler));let p=clamp(floor(uv*dims)+vec2f(0.5),vec2f(0.5),dims-vec2f(0.5));return textureSampleLevel(sourceTextureSampler,sourceSampler,p/dims,0);}`;\n\nconst FRAGMENT_WRAPPER_WGSL = `@fragment fn postProcessFragment(input:PostProcessVertexOutput)->@location(0) vec4f{return applyPostProcess(samplePostProcessSource(input.uv),input.uv);}`;\n\nexport function createPostProcessTask(config: PostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): PostProcessTask {\n const source = config.sourceTexture;\n const internalTarget = config.targetTexture ? null : createInternalTarget(config.name ?? \"post-process\", source);\n const colorAttachment: GPURenderPassColorAttachment = {\n view: undefined!,\n loadOp: \"clear\",\n storeOp: \"store\",\n };\n const task: PostProcessTaskInternal = {\n name: config.name ?? \"post-process\",\n engine: engine,\n scene,\n _passes: [],\n sourceTexture: source,\n sourceSamplingMode: config.sourceSamplingMode ?? \"linear\",\n targetTexture: config.targetTexture ?? null,\n alphaMode: config.alphaMode ?? 0,\n viewport: config.viewport ?? null,\n clear: config.clear ?? true,\n outputTexture: config.targetTexture ?? internalTarget!,\n _shader: config._shader,\n _internalTarget: internalTarget,\n _internalTargetKey: internalTarget ? internalTargetKey(source) : \"\",\n _pipeline: null,\n _bindGroup: null,\n _bindGroupLayout: null,\n _pipelineLayout: null,\n _shaderModule: null,\n _shaderModuleCode: \"\",\n _uniformBuffer: null,\n _uniformData: null,\n _renderPassDescriptor: { label: config.name ?? \"post-process\", colorAttachments: [colorAttachment] },\n _colorAttachment: colorAttachment,\n record(): void {\n prepareOutputTarget(task);\n buildRenderTarget(task.outputTexture, engine);\n createPostProcessGpuState(task, engine);\n },\n execute(): number {\n applyColorAttachmentState(task._colorAttachment, task.outputTexture, engine, task.clear);\n const pass = engine._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n applyViewport(pass, task.viewport, task.outputTexture);\n pass.setPipeline(task._pipeline!);\n pass.setBindGroup(0, task._bindGroup!);\n pass.draw(3);\n pass.end();\n return 1;\n },\n updateUniforms(): void {\n writePostProcessUniforms(task, engine);\n },\n dispose(): void {\n task._passes.length = 0;\n task._uniformBuffer?.destroy();\n task._uniformBuffer = null;\n task._uniformData = null;\n task._pipeline = null;\n task._bindGroup = null;\n task._bindGroupLayout = null;\n task._pipelineLayout = null;\n task._shaderModule = null;\n task._shaderModuleCode = \"\";\n if (task._internalTarget) {\n disposeRenderTarget(task._internalTarget);\n }\n },\n };\n return task;\n}\n\nfunction createPostProcessGpuState(task: PostProcessTaskInternal, engine: EngineContext): void {\n const source = task.sourceTexture;\n if (!source._colorTexture || !source._colorView) {\n throw new Error(`PostProcessTask \"${task.name}\": sourceTexture has no color texture. Render the source to an offscreen RenderTarget before post-processing.`);\n }\n if ((source._descriptor.sampleCount ?? 1) !== 1) {\n throw new Error(`PostProcessTask \"${task.name}\": multisampled source textures are not supported. Use a sampleCount: 1 source RenderTarget.`);\n }\n const target = task.outputTexture;\n const colorFormat = target._descriptor.colorFormat;\n if (!colorFormat) {\n throw new Error(`PostProcessTask \"${task.name}\": outputTexture must have a colorFormat.`);\n }\n task._uniformBuffer ??= createUniformBuffer(task, engine);\n task._uniformData ??= createUniformData(task);\n writePostProcessUniforms(task, engine);\n\n const bgl = getBindGroupLayout(task, engine);\n task._pipelineLayout ??= engine._device.createPipelineLayout({ label: `${task.name}-pipeline-layout`, bindGroupLayouts: [bgl] });\n const signature: RenderTargetSignature = {\n _colorFormat: colorFormat,\n _sampleCount: target._descriptor.sampleCount ?? 1,\n };\n task._pipeline = engine._device.createRenderPipeline({\n label: `${task.name}-${targetSignatureKey(signature)}-${task.alphaMode}`,\n layout: task._pipelineLayout,\n vertex: { module: getShaderModule(task, engine), entryPoint: \"postProcessVertex\" },\n fragment: {\n module: getShaderModule(task, engine),\n entryPoint: \"postProcessFragment\",\n targets: [{ format: colorFormat, blend: alphaModeToBlend(task.alphaMode) }],\n },\n primitive: { topology: \"triangle-list\" },\n multisample: { count: signature._sampleCount },\n });\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: task.sourceSamplingMode === \"nearest\" ? getNearestSampler(engine) : getBilinearSampler(engine) },\n { binding: 1, resource: source._colorView },\n ];\n const extraTextures = task._shader.extraTextures ?? [];\n if (task._uniformBuffer) {\n entries.push({ binding: getUniformBinding(task), resource: { buffer: task._uniformBuffer } });\n }\n for (let i = 0; i < extraTextures.length; i++) {\n const texture = extraTextures[i]!;\n if (!texture._colorView) {\n throw new Error(`PostProcessTask \"${task.name}\": extra texture ${i} has no color texture.`);\n }\n entries.push({ binding: 2 + i, resource: texture._colorView });\n }\n task._bindGroup = engine._device.createBindGroup({\n label: `${task.name}-bind-group`,\n layout: bgl,\n entries,\n });\n}\n\nfunction prepareOutputTarget(task: PostProcessTaskInternal): void {\n const target = task.targetTexture;\n if (target) {\n task.outputTexture = target;\n return;\n }\n const key = internalTargetKey(task.sourceTexture);\n if (task._internalTarget && task._internalTargetKey === key) {\n task.outputTexture = task._internalTarget;\n return;\n }\n if (task._internalTarget) {\n disposeRenderTarget(task._internalTarget);\n }\n task._internalTarget = createInternalTarget(task.name, task.sourceTexture);\n task._internalTargetKey = key;\n task.outputTexture = task._internalTarget;\n}\n\nfunction createInternalTarget(name: string, source: RenderTarget): RenderTarget {\n const srcDesc = source._descriptor;\n if (!srcDesc.colorFormat) {\n throw new Error(`PostProcessTask \"${name}\": sourceTexture must have a colorFormat.`);\n }\n const desc: RenderTargetDescriptor = {\n label: `${name}-output`,\n colorFormat: srcDesc.colorFormat,\n sampleCount: 1,\n size: srcDesc.size,\n };\n return createRenderTarget(desc);\n}\n\nfunction internalTargetKey(source: RenderTarget): string {\n const desc = source._descriptor;\n const size = desc.size === \"canvas\" ? \"canvas\" : `${desc.size.width}x${desc.size.height}`;\n return `${desc.colorFormat ?? \"-\"}|${desc.sampleCount ?? 1}|${size}`;\n}\n\nfunction getBindGroupLayout(task: PostProcessTaskInternal, engine: EngineContext): GPUBindGroupLayout {\n const hasUniform = (task._shader.uniformByteLength ?? 0) > 0;\n if (task._bindGroupLayout) {\n return task._bindGroupLayout;\n }\n const entries: GPUBindGroupLayoutEntry[] = [\n { binding: 0, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } },\n ];\n const extraTextures = task._shader.extraTextures ?? [];\n for (let i = 0; i < extraTextures.length; i++) {\n entries.push({ binding: 2 + i, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } });\n }\n if (hasUniform) {\n entries.push({ binding: getUniformBinding(task), visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } });\n }\n task._bindGroupLayout = engine._device.createBindGroupLayout({ label: `${task.name}-bind-group-layout`, entries });\n return task._bindGroupLayout;\n}\n\nfunction getUniformBinding(task: PostProcessTaskInternal): number {\n return task._shader.uniformBinding ?? 2 + (task._shader.extraTextures?.length ?? 0);\n}\n\nfunction getShaderModule(task: PostProcessTaskInternal, engine: EngineContext): GPUShaderModule {\n const desc = task.outputTexture._descriptor;\n // Offscreen sources rendered without a projection flip match Babylon.js post-process sources;\n // compensate when sampling so derivative-dependent scene shading is not altered.\n const outputFlipY = (desc.flipY ?? desc.resolveToSwapchain !== true) || task.sourceTexture._descriptor.flipY === false;\n const code = `${fullscreenVertexWGSL(outputFlipY, task._shader.vertexOutputWGSL ?? \"\", task._shader.vertexMainWGSL ?? \"\")}\\n${SOURCE_WGSL}\\n${task._shader.extraTextureWGSL ?? \"\"}\\n${task._shader.uniformWGSL ?? \"\"}\\n${task._shader.fragmentWGSL}\\n${task._shader.fragmentWrapperWGSL ?? FRAGMENT_WRAPPER_WGSL}`;\n if (!task._shaderModule || task._shaderModuleCode !== code) {\n task._shaderModuleCode = code;\n task._shaderModule = engine._device.createShaderModule({\n label: task.name,\n code,\n });\n }\n return task._shaderModule;\n}\n\nfunction createUniformBuffer(task: PostProcessTaskInternal, engine: EngineContext): GPUBuffer | null {\n const size = align16(task._shader.uniformByteLength ?? 0);\n if (size === 0) {\n return null;\n }\n return engine._device.createBuffer({\n label: `${task.name}-uniforms`,\n size,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n}\n\nfunction createUniformData(task: PostProcessTaskInternal): Float32Array | null {\n const size = align16(task._shader.uniformByteLength ?? 0);\n return size === 0 ? null : new Float32Array(size / 4);\n}\n\nfunction writePostProcessUniforms(task: PostProcessTaskInternal, engine: EngineContext): void {\n if ((task._shader.uniformByteLength ?? 0) === 0) {\n return;\n }\n task._uniformData!.fill(0);\n task._shader.writeUniforms?.(task._uniformData!);\n engine._device.queue.writeBuffer(task._uniformBuffer!, 0, task._uniformData as Float32Array<ArrayBuffer>);\n}\n\nfunction applyColorAttachmentState(att: GPURenderPassColorAttachment, rt: RenderTarget, eng: EngineContext, clear: boolean): void {\n if (rt._descriptor.resolveToSwapchain === true) {\n if ((rt._descriptor.sampleCount ?? 1) > 1) {\n att.view = rt._colorView!;\n att.resolveTarget = eng._swapchainView;\n } else {\n att.view = eng._swapchainView;\n att.resolveTarget = undefined;\n }\n } else {\n att.view = rt._colorView!;\n att.resolveTarget = undefined;\n }\n att.loadOp = clear ? \"clear\" : \"load\";\n}\n\nfunction applyViewport(pass: GPURenderPassEncoder, viewport: NormalizedViewport | null, rt: RenderTarget): void {\n if (!viewport) {\n return;\n }\n const x = Math.floor(viewport.x * rt._width);\n const y = Math.floor((1 - viewport.y - viewport.height) * rt._height);\n const w = Math.ceil((viewport.x + viewport.width) * rt._width) - x;\n const h = Math.ceil((1 - viewport.y) * rt._height) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n}\n\nfunction alphaModeToBlend(mode: PostProcessAlphaMode): GPUBlendState | undefined {\n switch (mode) {\n case 1:\n return {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n };\n case 2:\n return {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n };\n case 7:\n return {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n };\n default:\n return undefined;\n }\n}\n\nfunction align16(value: number): number {\n return Math.ceil(value / 16) * 16;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskConfig } from \"../frame-graph/post-process-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/** Configuration for `createBlackAndWhitePostProcessTask`; `degree` is the desaturation strength (0 = color, 1 = full grayscale). */\nexport interface BlackAndWhitePostProcessTaskConfig extends Omit<PostProcessTaskConfig, \"_shader\"> {\n degree?: number;\n}\n\n/** A post-process task that desaturates the image toward grayscale by `degree`. */\nexport interface BlackAndWhitePostProcessTask extends PostProcessTask {\n degree: number;\n}\n\nconst BLACK_AND_WHITE_UNIFORM_WGSL = `struct BlackAndWhiteParams{degree:f32,p0:f32,p1:f32,p2:f32}\n@group(0) @binding(2) var<uniform> blackAndWhiteParams:BlackAndWhiteParams;`;\n\nconst BLACK_AND_WHITE_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let luminance=dot(color.rgb,vec3f(0.3,0.59,0.11));let gray=vec3f(luminance);return vec4f(mix(color.rgb,gray,clamp(blackAndWhiteParams.degree,0,1)),color.a);}`;\n\n/**\n * Create a post-process task that blends the image toward grayscale.\n * @param config - Source/target settings and desaturation `degree`.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The black-and-white post-process task.\n */\nexport function createBlackAndWhitePostProcessTask(config: BlackAndWhitePostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): BlackAndWhitePostProcessTask {\n const params = { degree: config.degree ?? 1 };\n const task = createPostProcessTask(\n {\n name: config.name ?? \"black-and-white\",\n sourceTexture: config.sourceTexture,\n sourceSamplingMode: config.sourceSamplingMode,\n targetTexture: config.targetTexture,\n alphaMode: config.alphaMode,\n viewport: config.viewport,\n clear: config.clear,\n _shader: {\n uniformWGSL: BLACK_AND_WHITE_UNIFORM_WGSL,\n uniformByteLength: 16,\n writeUniforms(data) {\n data[0] = params.degree;\n },\n fragmentWGSL: BLACK_AND_WHITE_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n ) as BlackAndWhitePostProcessTask;\n Object.defineProperty(task, \"degree\", {\n get: () => params.degree,\n set: (value: number) => {\n params.degree = value;\n },\n });\n return task;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskConfig } from \"../frame-graph/post-process-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/** Configuration for `createAnaglyphPostProcessTask`; `leftTexture` is the left-eye image combined with the source (right eye). */\nexport interface AnaglyphPostProcessTaskConfig extends Omit<PostProcessTaskConfig, \"_shader\"> {\n leftTexture: RenderTarget;\n}\n\n/** A post-process task that combines a left-eye and right-eye image into a red/cyan anaglyph 3D image. */\nexport interface AnaglyphPostProcessTask extends PostProcessTask {\n leftTexture: RenderTarget;\n}\n\nconst ANAGLYPH_EXTRA_TEXTURE_WGSL = `@group(0) @binding(2) var leftTextureSampler:texture_2d<f32>;`;\n\nconst ANAGLYPH_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let l=textureSampleLevel(leftTextureSampler,sourceSampler,clamp(uv,vec2f(0),vec2f(1)),0);let left=vec4f(1,l.g,l.b,1);let right=vec4f(color.r,1,1,1);return vec4f(right.rgb*left.rgb,1);}`;\n\n/**\n * Create a post-process task that merges a left-eye texture with the source (right eye) into a red/cyan anaglyph.\n * @param config - Source/target settings and the left-eye `leftTexture`.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The anaglyph post-process task.\n */\nexport function createAnaglyphPostProcessTask(config: AnaglyphPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): AnaglyphPostProcessTask {\n const task = createPostProcessTask(\n {\n name: config.name ?? \"anaglyph\",\n sourceTexture: config.sourceTexture,\n sourceSamplingMode: config.sourceSamplingMode,\n targetTexture: config.targetTexture,\n alphaMode: config.alphaMode,\n viewport: config.viewport,\n clear: config.clear,\n _shader: {\n extraTextureWGSL: ANAGLYPH_EXTRA_TEXTURE_WGSL,\n extraTextures: [config.leftTexture],\n fragmentWGSL: ANAGLYPH_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n ) as AnaglyphPostProcessTask;\n task.leftTexture = config.leftTexture;\n return task;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { createPostProcessTask, type PostProcessShaderConfig, type PostProcessTask, type PostProcessTaskConfig } from \"../frame-graph/post-process-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\nexport interface PostProcessVec2 {\n x: number;\n y: number;\n}\n\n/** Configuration for `createBlurPostProcessTask`; `direction` is the blur axis and `kernel` the sample-window size in pixels. */\nexport interface BlurPostProcessTaskConfig extends Omit<PostProcessTaskConfig, \"_shader\"> {\n direction?: PostProcessVec2;\n kernel?: number;\n}\n\n/** A separable Gaussian blur post-process pass along a single `direction`. */\nexport interface BlurPostProcessTask extends PostProcessTask {\n direction: PostProcessVec2;\n kernel: number;\n}\n\nconst MAX_VERTEX_BLUR_SAMPLES = 8;\n\nconst BLUR_UNIFORM_WGSL = `struct BlurParams{delta:vec2f,p0:f32,p1:f32}\n@group(0) @binding(2) var<uniform> blurParams:BlurParams;`;\n\ninterface BlurSample {\n offset: number;\n weight: number;\n}\n\nfunction nearestBestKernel(kernel: number): number {\n const value = Math.max(1, Math.round(kernel));\n for (const k of [value, value - 1, value + 1, value - 2, value + 2]) {\n if (k > 0 && k % 2 !== 0 && Math.floor(k / 2) % 2 === 0) {\n return Math.max(k, 3);\n }\n }\n return Math.max(value, 3);\n}\n\nfunction gaussianWeight(x: number): number {\n const sigma = 1 / 3;\n return Math.exp(-(x * x) / (2 * sigma * sigma)) / (Math.sqrt(2 * Math.PI) * sigma);\n}\n\nfunction getOptimizedBlurSamples(kernel: number): BlurSample[] {\n const n = nearestBestKernel(kernel);\n const centerIndex = (n - 1) / 2;\n const offsets: number[] = [];\n const weights: number[] = [];\n let totalWeight = 0;\n for (let i = 0; i < n; i++) {\n const weight = gaussianWeight((i / (n - 1)) * 2 - 1);\n offsets[i] = i - centerIndex;\n weights[i] = weight;\n totalWeight += weight;\n }\n for (let i = 0; i < weights.length; i++) {\n weights[i]! /= totalWeight;\n }\n const samples: BlurSample[] = [];\n for (let i = 0; i <= centerIndex; i += 2) {\n const j = Math.min(i + 1, Math.floor(centerIndex));\n if (i === j) {\n samples.push({ offset: offsets[i]!, weight: weights[i]! });\n continue;\n }\n const sharedCell = j === centerIndex;\n const weight = weights[i]! + weights[j]! * (sharedCell ? 0.5 : 1);\n const offset = offsets[i]! + 1 / (1 + weights[i]! / weights[j]!);\n if (offset === 0) {\n samples.push({ offset: offsets[i]!, weight: weights[i]! }, { offset: offsets[i + 1]!, weight: weights[i + 1]! });\n } else {\n samples.push({ offset, weight }, { offset: -offset, weight });\n }\n }\n return samples;\n}\n\nfunction wgslFloat(value: number): string {\n return value.toFixed(7).replace(/0+$/, \"\").replace(/\\.$/, \".0\");\n}\n\nfunction updateBlurShader(shader: PostProcessShaderConfig, kernel: number): void {\n const samples = getOptimizedBlurSamples(kernel);\n const varyingCount = Math.min(samples.length, MAX_VERTEX_BLUR_SAMPLES);\n shader.vertexOutputWGSL = \"\";\n shader.vertexMainWGSL = \"\";\n for (let i = 0; i < varyingCount; i++) {\n shader.vertexOutputWGSL += `,@location(${i + 1}) sampleCoord${i}:vec2f`;\n shader.vertexMainWGSL += `out.sampleCoord${i}=out.uv+blurParams.delta*${wgslFloat(samples[i]!.offset)};`;\n }\n let body = \"var blend=vec4f(0);\";\n for (let i = 0; i < varyingCount; i++) {\n body += `blend+=textureSample(sourceTextureSampler,sourceSampler,input.sampleCoord${i})*${wgslFloat(samples[i]!.weight)};`;\n }\n for (let i = varyingCount; i < samples.length; i++) {\n const sample = samples[i]!;\n body += `blend+=samplePostProcessSource(input.uv+blurParams.delta*${wgslFloat(sample.offset)})*${wgslFloat(sample.weight)};`;\n }\n body += \"return blend;\";\n shader.fragmentWGSL = \"\";\n shader.fragmentWrapperWGSL = `@fragment fn postProcessFragment(input:PostProcessVertexOutput)->@location(0) vec4f{${body}}`;\n}\n\n/**\n * Create a separable Gaussian blur post-process task. Apply twice (horizontal then vertical) for a full 2D blur.\n * @param config - Blur direction, kernel size, and source/target settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The blur post-process task.\n */\nexport function createBlurPostProcessTask(config: BlurPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): BlurPostProcessTask {\n const params = { direction: config.direction ?? { x: 1, y: 0 }, kernel: config.kernel ?? 9 };\n const shader: PostProcessShaderConfig = {\n uniformWGSL: BLUR_UNIFORM_WGSL,\n uniformByteLength: 16,\n writeUniforms(data) {\n const width = Math.max(1, task.outputTexture._width || config.sourceTexture._width);\n const height = Math.max(1, task.outputTexture._height || config.sourceTexture._height);\n data[0] = params.direction.x / width;\n data[1] = params.direction.y / height;\n },\n fragmentWGSL: \"\",\n };\n updateBlurShader(shader, params.kernel);\n const task = createPostProcessTask(\n {\n name: config.name ?? \"blur\",\n sourceTexture: config.sourceTexture,\n sourceSamplingMode: config.sourceSamplingMode,\n targetTexture: config.targetTexture,\n alphaMode: config.alphaMode,\n viewport: config.viewport,\n clear: config.clear,\n _shader: shader,\n },\n engine,\n scene\n ) as BlurPostProcessTask;\n const baseUpdateUniforms = task.updateUniforms;\n let shaderKernel = params.kernel;\n task.updateUniforms = () => {\n if (shaderKernel !== params.kernel) {\n shaderKernel = params.kernel;\n updateBlurShader(task._shader, params.kernel);\n task.record();\n }\n baseUpdateUniforms();\n };\n Object.defineProperties(task, {\n direction: {\n get: () => params.direction,\n set: (value: PostProcessVec2) => {\n params.direction = value;\n },\n },\n kernel: {\n get: () => params.kernel,\n set: (value: number) => {\n params.kernel = value;\n },\n },\n });\n return task;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskConfig } from \"../frame-graph/post-process-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/** Configuration for `createExtractHighlightsPostProcessTask`: luminance `threshold` and `exposure` applied before thresholding. */\nexport interface ExtractHighlightsPostProcessTaskConfig extends Omit<PostProcessTaskConfig, \"_shader\"> {\n threshold?: number;\n exposure?: number;\n}\n\n/** A post-process task that keeps only pixels whose luminance exceeds `threshold` and zeroes the rest. */\nexport interface ExtractHighlightsPostProcessTask extends PostProcessTask {\n threshold: number;\n exposure: number;\n}\n\nconst TO_GAMMA_SPACE = 1 / 2.2;\n\nconst EXTRACT_HIGHLIGHTS_UNIFORM_WGSL = `struct ExtractHighlightsParams{threshold:f32,exposure:f32,p0:f32,p1:f32}\n@group(0) @binding(2) var<uniform> extractHighlightsParams:ExtractHighlightsParams;`;\n\nconst EXTRACT_HIGHLIGHTS_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let luma=dot(vec3f(0.2126,0.7152,0.0722),color.rgb*extractHighlightsParams.exposure);return vec4f(step(extractHighlightsParams.threshold,luma)*color.rgb,color.a);}`;\n\n/**\n * Create a post-process task that isolates bright highlights above a luminance threshold (used as the first stage of bloom).\n * @param config - Threshold/exposure parameters and source/target settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The extract-highlights post-process task.\n */\nexport function createExtractHighlightsPostProcessTask(\n config: ExtractHighlightsPostProcessTaskConfig,\n engine: EngineContext,\n scene?: SceneContext\n): ExtractHighlightsPostProcessTask {\n const params = {\n threshold: config.threshold ?? 0.9,\n exposure: config.exposure ?? 1,\n };\n const task = createPostProcessTask(\n {\n name: config.name ?? \"extract-highlights\",\n sourceTexture: config.sourceTexture,\n sourceSamplingMode: config.sourceSamplingMode,\n targetTexture: config.targetTexture,\n alphaMode: config.alphaMode,\n viewport: config.viewport,\n clear: config.clear,\n _shader: {\n uniformWGSL: EXTRACT_HIGHLIGHTS_UNIFORM_WGSL,\n uniformByteLength: 16,\n writeUniforms(data) {\n data[0] = Math.pow(params.threshold, TO_GAMMA_SPACE);\n data[1] = params.exposure;\n },\n fragmentWGSL: EXTRACT_HIGHLIGHTS_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n ) as ExtractHighlightsPostProcessTask;\n Object.defineProperties(task, {\n threshold: {\n get: () => params.threshold,\n set: (value: number) => {\n params.threshold = value;\n },\n },\n exposure: {\n get: () => params.exposure,\n set: (value: number) => {\n params.exposure = value;\n },\n },\n });\n return task;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskConfig } from \"../frame-graph/post-process-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\nexport interface PostProcessVec2 {\n x: number;\n y: number;\n}\n\n/** Configuration for `createChromaticAberrationPostProcessTask`: shift `aberrationAmount`, `direction`, `radialIntensity`, and `centerPosition`. */\nexport interface ChromaticAberrationPostProcessTaskConfig extends Omit<PostProcessTaskConfig, \"_shader\"> {\n aberrationAmount?: number;\n direction?: PostProcessVec2;\n radialIntensity?: number;\n centerPosition?: PostProcessVec2;\n}\n\n/** A post-process task that offsets the red/green/blue channels to simulate lens chromatic aberration. */\nexport interface ChromaticAberrationPostProcessTask extends PostProcessTask {\n aberrationAmount: number;\n direction: PostProcessVec2;\n radialIntensity: number;\n centerPosition: PostProcessVec2;\n}\n\nconst CHROMATIC_ABERRATION_UNIFORM_WGSL = `struct ChromaticAberrationParams{chromatic_aberration:f32,screen_width:f32,screen_height:f32,radialIntensity:f32,direction:vec2f,centerPosition:vec2f}\n@group(0) @binding(2) var<uniform> chromaticAberrationParams:ChromaticAberrationParams;`;\n\nconst CHROMATIC_ABERRATION_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let centered=uv-chromaticAberrationParams.centerPosition;var dir=chromaticAberrationParams.direction;if(dir.x==0.0&&dir.y==0.0){dir=normalize(centered);}let radius=sqrt(dot(centered,centered));let amount=chromaticAberrationParams.chromatic_aberration*pow(radius,chromaticAberrationParams.radialIntensity);let shift=amount*dir/vec2f(chromaticAberrationParams.screen_width,chromaticAberrationParams.screen_height);let r=samplePostProcessSource(vec2f(uv.x+shift.x*-0.3,uv.y+shift.y*-0.3*0.5));let g=samplePostProcessSource(uv);let b=samplePostProcessSource(vec2f(uv.x+shift.x*0.3,uv.y+shift.y*0.3*0.5));return vec4f(r.r,g.g,b.b,clamp(r.a+g.a+b.a,0,1));}`;\n\n/**\n * Create a post-process task that simulates chromatic aberration by shifting color channels outward from a center point.\n * @param config - Aberration parameters and source/target settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The chromatic-aberration post-process task.\n */\nexport function createChromaticAberrationPostProcessTask(\n config: ChromaticAberrationPostProcessTaskConfig,\n engine: EngineContext,\n scene?: SceneContext\n): ChromaticAberrationPostProcessTask {\n const params = {\n aberrationAmount: config.aberrationAmount ?? 30,\n screenWidth: 1,\n screenHeight: 1,\n direction: config.direction ?? { x: 0.707, y: 0.707 },\n radialIntensity: config.radialIntensity ?? 0,\n centerPosition: config.centerPosition ?? { x: 0.5, y: 0.5 },\n };\n const task = createPostProcessTask(\n {\n name: config.name ?? \"chromatic-aberration\",\n sourceTexture: config.sourceTexture,\n sourceSamplingMode: config.sourceSamplingMode,\n targetTexture: config.targetTexture,\n alphaMode: config.alphaMode,\n viewport: config.viewport,\n clear: config.clear,\n _shader: {\n uniformWGSL: CHROMATIC_ABERRATION_UNIFORM_WGSL,\n uniformByteLength: 32,\n writeUniforms(data) {\n data[0] = params.aberrationAmount;\n data[1] = params.screenWidth;\n data[2] = params.screenHeight;\n data[3] = params.radialIntensity;\n data[4] = params.direction.x;\n data[5] = params.direction.y;\n data[6] = params.centerPosition.x;\n data[7] = params.centerPosition.y;\n },\n fragmentWGSL: CHROMATIC_ABERRATION_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n ) as ChromaticAberrationPostProcessTask;\n const record = task.record;\n task.record = () => {\n params.screenWidth = task.sourceTexture._width;\n params.screenHeight = task.sourceTexture._height;\n record();\n };\n Object.defineProperties(task, {\n aberrationAmount: {\n get: () => params.aberrationAmount,\n set: (value: number) => {\n params.aberrationAmount = value;\n },\n },\n direction: {\n get: () => params.direction,\n set: (value: PostProcessVec2) => {\n params.direction = value;\n },\n },\n radialIntensity: {\n get: () => params.radialIntensity,\n set: (value: number) => {\n params.radialIntensity = value;\n },\n },\n centerPosition: {\n get: () => params.centerPosition,\n set: (value: PostProcessVec2) => {\n params.centerPosition = value;\n },\n },\n });\n return task;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget, RenderTargetDescriptor } from \"../engine/render-target.js\";\nimport { createRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskSettings } from \"../frame-graph/post-process-task.js\";\nimport type { Task } from \"../frame-graph/task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createBlurPostProcessTask, type BlurPostProcessTask } from \"./blur.js\";\nimport { createExtractHighlightsPostProcessTask, type ExtractHighlightsPostProcessTask } from \"./extract-highlights.js\";\n\n/** Configuration for `createBloomPostProcessTask`: highlight `threshold`/`exposure`, blur `kernel`, merge `weight`, and `bloomScale`. */\nexport interface BloomPostProcessTaskConfig extends PostProcessTaskSettings {\n weight?: number;\n kernel?: number;\n threshold?: number;\n exposure?: number;\n bloomScale?: number;\n}\n\n/** A composite post-process task that extracts highlights, blurs them, and merges the glow back over the source image. */\nexport interface BloomPostProcessTask extends Task, PostProcessTaskSettings {\n readonly name: string;\n sourceTexture: RenderTarget;\n targetTexture: RenderTarget | null;\n outputTexture: RenderTarget;\n weight: number;\n kernel: number;\n threshold: number;\n exposure: number;\n readonly bloomScale: number;\n /** Recompute and upload the uniforms of all sub-passes (extract, blur X/Y, merge) from current settings. */\n updateUniforms(): void;\n}\n\ninterface BloomTaskInternal extends BloomPostProcessTask {\n _extract: ExtractHighlightsPostProcessTask;\n _blurX: BlurPostProcessTask;\n _blurY: BlurPostProcessTask;\n _merge: PostProcessTask;\n _extractTarget: RenderTarget;\n _blurXTarget: RenderTarget;\n _blurYTarget: RenderTarget;\n}\n\nconst BLOOM_MERGE_EXTRA_TEXTURE_WGSL = `@group(0) @binding(2) var bloomBlur:texture_2d<f32>;`;\n\nconst BLOOM_MERGE_UNIFORM_WGSL = `struct BloomMergeParams{weight:f32,p0:f32,p1:f32,p2:f32}\n@group(0) @binding(3) var<uniform> bloomMergeParams:BloomMergeParams;`;\n\nconst BLOOM_MERGE_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let blurred=textureSampleLevel(bloomBlur,sourceSampler,clamp(uv,vec2f(0),vec2f(1)),0).rgb;return vec4f(color.rgb+blurred*bloomMergeParams.weight,color.a);}`;\n\nconst scaledKernel = (kernel: number, scale: number): number => kernel * scale;\n\n/**\n * Create a bloom post-process task by chaining highlight extraction, separable blur, and a merge pass.\n * @param config - Bloom parameters and source/target settings.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene. Omit for scene-less standalone frame graphs.\n * @returns The bloom post-process task.\n */\nexport function createBloomPostProcessTask(config: BloomPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): BloomPostProcessTask {\n const eng = engine as EngineContext;\n const params = {\n sourceTexture: config.sourceTexture,\n targetTexture: config.targetTexture ?? null,\n sourceSamplingMode: config.sourceSamplingMode ?? \"linear\",\n alphaMode: config.alphaMode ?? 0,\n viewport: config.viewport ?? null,\n clear: config.clear ?? true,\n weight: config.weight ?? 0.25,\n kernel: config.kernel ?? 64,\n threshold: config.threshold ?? 0.2,\n exposure: config.exposure ?? 1,\n bloomScale: config.bloomScale ?? 0.5,\n };\n const name = config.name ?? \"bloom\";\n const extractTarget = createScaledBloomTarget(`${name}-extract-output`, params.sourceTexture, params.bloomScale, eng);\n const blurXTarget = createScaledBloomTarget(`${name}-blur-x-output`, params.sourceTexture, params.bloomScale, eng);\n const blurYTarget = createScaledBloomTarget(`${name}-blur-y-output`, params.sourceTexture, params.bloomScale, eng);\n\n const extract = createExtractHighlightsPostProcessTask(\n {\n name: `${name}-extract-highlights`,\n sourceTexture: params.sourceTexture,\n sourceSamplingMode: \"linear\",\n targetTexture: extractTarget,\n threshold: params.threshold,\n exposure: params.exposure,\n },\n engine,\n scene\n );\n const blurX = createBlurPostProcessTask(\n {\n name: `${name}-blur-x`,\n sourceTexture: extractTarget,\n sourceSamplingMode: \"linear\",\n targetTexture: blurXTarget,\n direction: { x: 1, y: 0 },\n kernel: scaledKernel(params.kernel, params.bloomScale),\n },\n engine,\n scene\n );\n const blurY = createBlurPostProcessTask(\n {\n name: `${name}-blur-y`,\n sourceTexture: blurXTarget,\n sourceSamplingMode: \"linear\",\n targetTexture: blurYTarget,\n direction: { x: 0, y: 1 },\n kernel: scaledKernel(params.kernel, params.bloomScale),\n },\n engine,\n scene\n );\n const merge = createPostProcessTask(\n {\n name: `${name}-merge`,\n sourceTexture: params.sourceTexture,\n sourceSamplingMode: params.sourceSamplingMode,\n targetTexture: params.targetTexture,\n alphaMode: params.alphaMode,\n viewport: params.viewport,\n clear: params.clear,\n _shader: {\n extraTextureWGSL: BLOOM_MERGE_EXTRA_TEXTURE_WGSL,\n extraTextures: [blurYTarget],\n uniformWGSL: BLOOM_MERGE_UNIFORM_WGSL,\n uniformBinding: 3,\n uniformByteLength: 16,\n writeUniforms(data) {\n data[0] = params.weight;\n },\n fragmentWGSL: BLOOM_MERGE_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n );\n\n const task: BloomTaskInternal = {\n name,\n engine: eng,\n scene,\n _passes: [],\n sourceTexture: params.sourceTexture,\n sourceSamplingMode: params.sourceSamplingMode,\n targetTexture: params.targetTexture,\n alphaMode: params.alphaMode,\n viewport: params.viewport,\n clear: params.clear,\n outputTexture: merge.outputTexture,\n _extract: extract,\n _blurX: blurX,\n _blurY: blurY,\n _merge: merge,\n _extractTarget: extractTarget,\n _blurXTarget: blurXTarget,\n _blurYTarget: blurYTarget,\n record(): void {\n resizeScaledBloomTarget(task._extractTarget, params.sourceTexture, params.bloomScale, eng);\n resizeScaledBloomTarget(task._blurXTarget, params.sourceTexture, params.bloomScale, eng);\n resizeScaledBloomTarget(task._blurYTarget, params.sourceTexture, params.bloomScale, eng);\n extract.record();\n blurX.record();\n blurY.record();\n merge.record();\n task.outputTexture = merge.outputTexture;\n },\n execute(): number {\n return (extract.execute?.() ?? 0) + (blurX.execute?.() ?? 0) + (blurY.execute?.() ?? 0) + (merge.execute?.() ?? 0);\n },\n updateUniforms(): void {\n extract.updateUniforms();\n blurX.updateUniforms();\n blurY.updateUniforms();\n merge.updateUniforms();\n },\n dispose(): void {\n extract.dispose();\n blurX.dispose();\n blurY.dispose();\n merge.dispose();\n disposeRenderTarget(task._extractTarget);\n disposeRenderTarget(task._blurXTarget);\n disposeRenderTarget(task._blurYTarget);\n },\n get weight() {\n return params.weight;\n },\n set weight(value: number) {\n params.weight = value;\n },\n get kernel() {\n return params.kernel;\n },\n set kernel(value: number) {\n params.kernel = value;\n blurX.kernel = scaledKernel(value, params.bloomScale);\n blurY.kernel = scaledKernel(value, params.bloomScale);\n },\n get threshold() {\n return extract.threshold;\n },\n set threshold(value: number) {\n params.threshold = value;\n extract.threshold = value;\n },\n get exposure() {\n return extract.exposure;\n },\n set exposure(value: number) {\n params.exposure = value;\n extract.exposure = value;\n },\n get bloomScale() {\n return params.bloomScale;\n },\n };\n Object.defineProperties(task, {\n sourceTexture: {\n get: () => params.sourceTexture,\n set: (value: RenderTarget) => {\n params.sourceTexture = value;\n extract.sourceTexture = value;\n merge.sourceTexture = value;\n },\n },\n sourceSamplingMode: {\n get: () => params.sourceSamplingMode,\n set: (value: \"nearest\" | \"linear\") => {\n params.sourceSamplingMode = value;\n merge.sourceSamplingMode = value;\n },\n },\n targetTexture: {\n get: () => params.targetTexture,\n set: (value: RenderTarget | null) => {\n params.targetTexture = value;\n merge.targetTexture = value;\n task.outputTexture = merge.outputTexture;\n },\n },\n alphaMode: {\n get: () => params.alphaMode,\n set: (value: 0 | 1 | 2 | 7) => {\n params.alphaMode = value;\n merge.alphaMode = value;\n },\n },\n viewport: {\n get: () => params.viewport,\n set: (value) => {\n params.viewport = value;\n merge.viewport = value;\n },\n },\n clear: {\n get: () => params.clear,\n set: (value: boolean) => {\n params.clear = value;\n merge.clear = value;\n },\n },\n });\n return task;\n}\n\nfunction createScaledBloomTarget(label: string, source: RenderTarget, scale: number, engine: EngineContext): RenderTarget {\n const srcDesc = source._descriptor;\n if (!srcDesc.colorFormat) {\n throw new Error(`BloomPostProcessTask \"${label}\": sourceTexture must have a colorFormat.`);\n }\n const sourceSize = resolveSourceSize(source, engine);\n return createRenderTarget({\n label,\n colorFormat: srcDesc.colorFormat,\n sampleCount: 1,\n size: {\n width: Math.max(1, Math.floor(sourceSize.width * scale)),\n height: Math.max(1, Math.floor(sourceSize.height * scale)),\n },\n });\n}\n\nfunction resizeScaledBloomTarget(target: RenderTarget, source: RenderTarget, scale: number, engine: EngineContext): void {\n const colorFormat = source._descriptor.colorFormat;\n if (!colorFormat) {\n throw new Error(`BloomPostProcessTask \"${target._descriptor.label ?? \"target\"}\": sourceTexture must have a colorFormat.`);\n }\n const sourceSize = resolveSourceSize(source, engine);\n target._descriptor.colorFormat = colorFormat;\n target._descriptor.size = {\n width: Math.max(1, Math.floor(sourceSize.width * scale)),\n height: Math.max(1, Math.floor(sourceSize.height * scale)),\n };\n}\n\nfunction resolveSourceSize(source: RenderTarget, engine: EngineContext): { width: number; height: number } {\n if (source._width > 0 && source._height > 0) {\n return { width: source._width, height: source._height };\n }\n const desc: RenderTargetDescriptor = source._descriptor;\n if (desc.size === \"canvas\") {\n return { width: engine.canvas.width, height: engine.canvas.height };\n }\n return desc.size;\n}\n","import type { ArcRotateCamera } from \"./arc-rotate.js\";\nimport type { SceneContext } from \"../scene/scene.js\";\n\n/**\n * Attach orbit/zoom/pan controls to an ArcRotateCamera.\n * Matches Babylon.js ArcRotateCameraPointersInput behavior with inertia:\n * - Left-drag: rotate (alpha/beta) with momentum\n * - Right-drag: pan (shift target) with momentum\n * - Wheel: zoom (radius) with momentum\n * - Pinch: zoom (touch, direct — no inertia)\n *\n * Input handlers accumulate into the camera's inertial offset properties.\n * Inertia is applied each frame via scene._beforeRender (single RAF loop).\n *\n * Camera stays plain data — this function reads/writes its properties.\n * Returns a cleanup function to remove all listeners and the beforeRender hook.\n */\nexport function attachControl(camera: ArcRotateCamera, canvas: HTMLCanvasElement, scene?: SceneContext): () => void {\n const angularSensibility = 1000; // Babylon default\n const panningSensibility = 50; // Babylon default (pixels per unit)\n const wheelPrecision = 3; // Babylon default\n\n const ROTATION_EPSILON = 0.001;\n const RADIUS_EPSILON = 0.001;\n const PANNING_EPSILON = 0.0001;\n\n let isDragging = false;\n let isPanning = false;\n let lastX = 0;\n let lastY = 0;\n let animFrameId = 0;\n\n // Touch state for pinch-zoom\n const activeTouches = new Map<number, { x: number; y: number }>();\n let pinchStartDist = 0;\n let pinchStartRadius = 0;\n\n function onPointerDown(e: PointerEvent): void {\n canvas.setPointerCapture(e.pointerId);\n lastX = e.clientX;\n lastY = e.clientY;\n\n if (e.button === 0) {\n isDragging = true;\n isPanning = false;\n } else if (e.button === 2) {\n isDragging = false;\n isPanning = true;\n }\n }\n\n function onPointerMove(e: PointerEvent): void {\n if (!isDragging && !isPanning) {\n return;\n }\n\n const dx = e.clientX - lastX;\n const dy = e.clientY - lastY;\n lastX = e.clientX;\n lastY = e.clientY;\n\n if (isDragging) {\n camera.inertialAlphaOffset -= dx / angularSensibility;\n camera.inertialBetaOffset -= dy / angularSensibility;\n }\n\n if (isPanning) {\n camera.inertialPanningX += -dx / panningSensibility;\n camera.inertialPanningY += dy / panningSensibility;\n }\n }\n\n function onPointerUp(e: PointerEvent): void {\n canvas.releasePointerCapture(e.pointerId);\n isDragging = false;\n isPanning = false;\n }\n\n function onWheel(e: WheelEvent): void {\n e.preventDefault();\n // Scale by current radius for logarithmic zoom feel\n camera.inertialRadiusOffset -= (e.deltaY * camera.radius) / (wheelPrecision * 1000);\n }\n\n function onContextMenu(e: Event): void {\n e.preventDefault();\n }\n\n function onTouchStart(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const touch = e.changedTouches[i]!;\n activeTouches.set(touch.identifier, { x: touch.clientX, y: touch.clientY });\n }\n if (activeTouches.size === 2) {\n const iter = activeTouches.values();\n const p0 = iter.next().value!;\n const p1 = iter.next().value!;\n pinchStartDist = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n pinchStartRadius = camera.radius;\n }\n }\n\n function onTouchMove(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n const touch = e.changedTouches[i]!;\n activeTouches.set(touch.identifier, { x: touch.clientX, y: touch.clientY });\n }\n if (activeTouches.size === 2) {\n const iter = activeTouches.values();\n const p0 = iter.next().value!;\n const p1 = iter.next().value!;\n const dist = Math.hypot(p1.x - p0.x, p1.y - p0.y);\n if (pinchStartDist > 0) {\n camera.radius = pinchStartRadius * (pinchStartDist / dist);\n camera.radius = Math.max(0.01, camera.radius);\n }\n }\n }\n\n function onTouchEnd(e: TouchEvent): void {\n for (let i = 0; i < e.changedTouches.length; i++) {\n activeTouches.delete(e.changedTouches[i]!.identifier);\n }\n }\n\n /** Per-frame: apply inertial offsets to camera properties and decay them. */\n function applyInertia(): void {\n // --- Rotation inertia ---\n if (camera.inertialAlphaOffset !== 0 || camera.inertialBetaOffset !== 0) {\n camera.alpha += camera.inertialAlphaOffset;\n camera.beta += camera.inertialBetaOffset;\n\n const eps = 0.01;\n camera.beta = Math.max(eps, Math.min(Math.PI - eps, camera.beta));\n\n camera.inertialAlphaOffset *= camera.inertia;\n camera.inertialBetaOffset *= camera.inertia;\n\n if (Math.abs(camera.inertialAlphaOffset) < ROTATION_EPSILON) {\n camera.inertialAlphaOffset = 0;\n }\n if (Math.abs(camera.inertialBetaOffset) < ROTATION_EPSILON) {\n camera.inertialBetaOffset = 0;\n }\n }\n\n // --- Zoom inertia ---\n if (camera.inertialRadiusOffset !== 0) {\n camera.radius -= camera.inertialRadiusOffset;\n camera.radius = Math.max(0.01, camera.radius);\n\n camera.inertialRadiusOffset *= camera.inertia;\n\n if (Math.abs(camera.inertialRadiusOffset) < RADIUS_EPSILON) {\n camera.inertialRadiusOffset = 0;\n }\n }\n\n // --- Panning inertia ---\n if (camera.inertialPanningX !== 0 || camera.inertialPanningY !== 0) {\n const cosA = Math.cos(camera.alpha);\n const sinA = Math.sin(camera.alpha);\n const rightX = -sinA;\n const rightZ = cosA;\n const panScale = camera.radius * 0.001;\n\n // Mutate in-place via ObservableVec3 — avoids object allocation per frame.\n // Individual setters each call onDirty (just version++), but that's cheaper than reallocating.\n camera.target.x += rightX * camera.inertialPanningX * panScale;\n camera.target.y += camera.inertialPanningY * panScale;\n camera.target.z += rightZ * camera.inertialPanningX * panScale;\n\n camera.inertialPanningX *= camera.panningInertia;\n camera.inertialPanningY *= camera.panningInertia;\n\n if (Math.abs(camera.inertialPanningX) < PANNING_EPSILON) {\n camera.inertialPanningX = 0;\n }\n if (Math.abs(camera.inertialPanningY) < PANNING_EPSILON) {\n camera.inertialPanningY = 0;\n }\n }\n\n // Only self-reschedule in fallback mode (own RAF loop)\n if (!scene) {\n animFrameId = requestAnimationFrame(applyInertia);\n }\n }\n\n if (scene) {\n // Hook into the engine's render loop — single RAF chain\n scene._beforeRender.push(applyInertia);\n } else {\n // Fallback: own RAF loop (for callers that don't pass scene)\n animFrameId = requestAnimationFrame(applyInertia);\n }\n\n const listeners: [string, EventListener, AddEventListenerOptions?][] = [\n [\"pointerdown\", onPointerDown as EventListener],\n [\"pointermove\", onPointerMove as EventListener],\n [\"pointerup\", onPointerUp as EventListener],\n [\"wheel\", onWheel as EventListener, { passive: false }],\n [\"contextmenu\", onContextMenu as EventListener],\n [\"touchstart\", onTouchStart as EventListener, { passive: true }],\n [\"touchmove\", onTouchMove as EventListener, { passive: true }],\n [\"touchend\", onTouchEnd as EventListener],\n ];\n for (const [ev, h, opts] of listeners) {\n canvas.addEventListener(ev, h, opts);\n }\n\n return () => {\n if (animFrameId) {\n cancelAnimationFrame(animFrameId);\n }\n if (scene) {\n const idx = scene._beforeRender.indexOf(applyInertia);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n }\n for (const [ev, h] of listeners) {\n canvas.removeEventListener(ev, h);\n }\n };\n}\n","import type { Camera } from \"./camera.js\";\nimport type { Vec3, Mat4 } from \"../math/types.js\";\nimport { mat4LookAtLH } from \"../math/mat4-look-at-lh.js\";\nimport { Vec3Up } from \"../math/vec3-up.js\";\nimport type { IWorldMatrixProvider, IParentable } from \"../scene/parentable.js\";\nimport { createWorldMatrixState, attachWorldMatrixState } from \"../scene/world-matrix-state.js\";\nimport { ObservableVec3 } from \"../math/observable-vec3.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\n\n/** FreeCamera — positioned in world space, looking at a target point.\n * Matches Babylon.js FreeCamera: position + target, left-handed.\n * Plain data + methods. Does NOT know about the scene.\n *\n * Push-based dirty tracking: position and target use ObservableVec3,\n * _yaw/_pitch use Object.defineProperty. */\nexport interface FreeCamera extends Camera, IWorldMatrixProvider, IParentable {\n position: ObservableVec3;\n target: ObservableVec3;\n /** Movement speed. Default 2.0 (matches BJS). */\n speed: number;\n /** Mouse rotation sensitivity (higher = less sensitive). Default 2000 (matches BJS). */\n angularSensitivity: number;\n /** Inertia damping factor (0 = instant stop, 0.9 = smooth). Default 0.9 (matches BJS). */\n inertia: number;\n parent: IWorldMatrixProvider | null;\n readonly worldMatrix: Mat4;\n readonly worldMatrixVersion: number;\n /** @internal */\n _yaw: number;\n /** @internal */\n _pitch: number;\n}\n\n/** Create a FreeCamera at the given position looking at target. Pure data, no scene knowledge. */\nexport function createFreeCamera(position: Vec3, target: Vec3): FreeCamera {\n // Compute initial yaw/pitch from position→target direction\n const dx = target.x - position.x;\n const dy = target.y - position.y;\n const dz = target.z - position.z;\n\n const _localMat = new Float32Array(16) as Mat4;\n\n function cameraLocalWorldMatrix(): Mat4 {\n const view = mat4LookAtLH(cam.position, cam.target, Vec3Up);\n // Camera-to-world = transpose upper 3×3 of view + eye position\n _localMat[0] = view[0]!;\n _localMat[1] = view[4]!;\n _localMat[2] = view[8]!;\n _localMat[3] = 0;\n _localMat[4] = view[1]!;\n _localMat[5] = view[5]!;\n _localMat[6] = view[9]!;\n _localMat[7] = 0;\n _localMat[8] = view[2]!;\n _localMat[9] = view[6]!;\n _localMat[10] = view[10]!;\n _localMat[11] = 0;\n _localMat[12] = cam.position.x;\n _localMat[13] = cam.position.y;\n _localMat[14] = cam.position.z;\n _localMat[15] = 1;\n return _localMat;\n }\n\n const wm = createWorldMatrixState(cameraLocalWorldMatrix);\n const onDirty = () => wm.markLocalDirty();\n\n let _yaw = Math.atan2(dx, dz);\n let _pitch = Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));\n\n const cam: FreeCamera = {\n position: new ObservableVec3(position.x, position.y, position.z, onDirty),\n target: new ObservableVec3(target.x, target.y, target.z, onDirty),\n fov: 0.8,\n nearPlane: 1,\n farPlane: 10000,\n speed: 2.0,\n angularSensitivity: 2000,\n inertia: 0.9,\n children: [] as SceneNode[],\n\n get parent() {\n return wm.parent;\n },\n set parent(v) {\n wm.parent = v;\n },\n get worldMatrix() {\n return wm.getWorldMatrix();\n },\n get worldMatrixVersion() {\n return wm.getWorldMatrixVersion();\n },\n } as FreeCamera;\n\n // Push-based dirty for yaw/pitch\n Object.defineProperty(cam, \"_yaw\", {\n get() {\n return _yaw;\n },\n set(v: number) {\n if (_yaw !== v) {\n _yaw = v;\n onDirty();\n }\n },\n configurable: true,\n enumerable: true,\n });\n Object.defineProperty(cam, \"_pitch\", {\n get() {\n return _pitch;\n },\n set(v: number) {\n if (_pitch !== v) {\n _pitch = v;\n onDirty();\n }\n },\n configurable: true,\n enumerable: true,\n });\n\n // Tag so children parented to this camera get push invalidation (O(1) reads).\n attachWorldMatrixState(cam, wm);\n\n return cam;\n}\n","import type { FreeCamera } from \"./free-camera.js\";\nimport type { SceneContext } from \"../scene/scene.js\";\n\n/**\n * Attach keyboard + mouse controls to a FreeCamera.\n * Matches Babylon.js FreeCamera input behavior:\n * - Mouse drag or pointer-lock: look around (yaw/pitch)\n * - Arrow keys / WASD: move forward/back/strafe\n * - PageUp/PageDown or Space/Shift: move up/down\n * - Inertia: movement decays smoothly (camera.inertia, default 0.9)\n * - Frame-rate independent: uses deltaTime from render loop\n *\n * Camera stays plain data — this function reads/writes its properties.\n * Returns a cleanup function to remove all listeners and the beforeRender hook.\n */\nexport function attachFreeControl(camera: FreeCamera, canvas: HTMLCanvasElement, scene?: SceneContext): () => void {\n // ─── Accumulator state (like BJS cameraDirection / cameraRotation) ───\n let cdX = 0,\n cdY = 0,\n cdZ = 0; // camera direction accumulator (local space)\n let crX = 0,\n crY = 0; // camera rotation accumulator (pitch, yaw)\n\n let isDragging = false;\n let lastPX = 0;\n let lastPY = 0;\n const keys = new Set<string>();\n\n // ─── Mouse / pointer ─────────────────────────────────────────────────\n function onPointerDown(e: PointerEvent): void {\n if (e.button === 0 || e.button === 1 || e.button === 2) {\n canvas.setPointerCapture(e.pointerId);\n isDragging = true;\n lastPX = e.clientX;\n lastPY = e.clientY;\n }\n }\n\n function onPointerMove(e: PointerEvent): void {\n if (!isDragging) {\n return;\n }\n const dx = e.clientX - lastPX;\n const dy = e.clientY - lastPY;\n lastPX = e.clientX;\n lastPY = e.clientY;\n\n // Add to rotation accumulator (same as BJS: divide by angularSensitivity)\n crY += dx / camera.angularSensitivity;\n crX += dy / camera.angularSensitivity;\n }\n\n function onPointerUp(e: PointerEvent): void {\n canvas.releasePointerCapture(e.pointerId);\n isDragging = false;\n }\n\n function onContextMenu(e: Event): void {\n e.preventDefault();\n }\n\n // ─── Keyboard ────────────────────────────────────────────────────────\n function onKeyDown(e: KeyboardEvent): void {\n keys.add(e.code);\n }\n\n function onKeyUp(e: KeyboardEvent): void {\n keys.delete(e.code);\n }\n\n // ─── Per-frame update (receives deltaMs from engine render loop) ─────\n function update(deltaMs: number): void {\n // BJS speed formula: speed * sqrt(deltaTime / (fps * 100))\n // Simplified: fps ≈ 1000/deltaMs, so deltaTime/(fps*100) = deltaMs^2 / 100000\n const dt = Math.max(deltaMs, 1);\n const moveSpeed = camera.speed * Math.sqrt((dt * dt) / 100000);\n\n // Accumulate keyboard input into camera direction (local space)\n if (keys.has(\"KeyW\") || keys.has(\"ArrowUp\")) {\n cdZ += moveSpeed;\n }\n if (keys.has(\"KeyS\") || keys.has(\"ArrowDown\")) {\n cdZ -= moveSpeed;\n }\n if (keys.has(\"KeyA\") || keys.has(\"ArrowLeft\")) {\n cdX -= moveSpeed;\n }\n if (keys.has(\"KeyD\") || keys.has(\"ArrowRight\")) {\n cdX += moveSpeed;\n }\n if (keys.has(\"Space\") || keys.has(\"PageUp\")) {\n cdY += moveSpeed;\n }\n if (keys.has(\"ShiftLeft\") || keys.has(\"ShiftRight\") || keys.has(\"PageDown\")) {\n cdY -= moveSpeed;\n }\n\n // Only apply movement/rotation if there's actual input to apply\n const hasMovement = cdX !== 0 || cdY !== 0 || cdZ !== 0;\n const hasRotation = crX !== 0 || crY !== 0;\n\n if (hasRotation) {\n camera._yaw += crY;\n camera._pitch -= crX;\n const maxPitch = Math.PI / 2 - 0.01;\n camera._pitch = Math.max(-maxPitch, Math.min(maxPitch, camera._pitch));\n }\n\n if (hasMovement) {\n // Transform local direction → world space using camera orientation\n const cosY = Math.cos(camera._yaw);\n const sinY = Math.sin(camera._yaw);\n const cosP = Math.cos(camera._pitch);\n const sinP = Math.sin(camera._pitch);\n // Forward/back moves in the camera's look direction (includes pitch)\n camera.position.x += sinY * cosP * cdZ + cosY * cdX;\n camera.position.y += sinP * cdZ + cdY;\n camera.position.z += cosY * cosP * cdZ - sinY * cdX;\n }\n\n // Update target from yaw/pitch only when camera moved or rotated\n if (hasMovement || hasRotation) {\n const cosY = Math.cos(camera._yaw);\n const sinY = Math.sin(camera._yaw);\n const cosP = Math.cos(camera._pitch);\n camera.target.set(camera.position.x + sinY * cosP, camera.position.y + Math.sin(camera._pitch), camera.position.z + cosY * cosP);\n }\n\n // Apply inertia (decay accumulators)\n const inertia = camera.inertia;\n const moveEpsilon = camera.speed * 0.001;\n const rotEpsilon = camera.speed * 0.001;\n cdX *= inertia;\n cdY *= inertia;\n cdZ *= inertia;\n crX *= inertia;\n crY *= inertia;\n // Clamp to zero when below epsilon\n if (Math.abs(cdX) < moveEpsilon) {\n cdX = 0;\n }\n if (Math.abs(cdY) < moveEpsilon) {\n cdY = 0;\n }\n if (Math.abs(cdZ) < moveEpsilon) {\n cdZ = 0;\n }\n if (Math.abs(crX) < rotEpsilon) {\n crX = 0;\n }\n if (Math.abs(crY) < rotEpsilon) {\n crY = 0;\n }\n }\n\n // ─── Register / cleanup ──────────────────────────────────────────────\n if (scene) {\n scene._beforeRender.push(update);\n }\n\n canvas.addEventListener(\"pointerdown\", onPointerDown);\n canvas.addEventListener(\"pointermove\", onPointerMove);\n canvas.addEventListener(\"pointerup\", onPointerUp);\n canvas.addEventListener(\"contextmenu\", onContextMenu);\n canvas.addEventListener(\"keydown\", onKeyDown);\n canvas.addEventListener(\"keyup\", onKeyUp);\n if (!canvas.hasAttribute(\"tabindex\")) {\n canvas.tabIndex = 0;\n }\n\n return () => {\n if (scene) {\n const idx = scene._beforeRender.indexOf(update);\n if (idx >= 0) {\n scene._beforeRender.splice(idx, 1);\n }\n }\n canvas.removeEventListener(\"pointerdown\", onPointerDown);\n canvas.removeEventListener(\"pointermove\", onPointerMove);\n canvas.removeEventListener(\"pointerup\", onPointerUp);\n canvas.removeEventListener(\"contextmenu\", onContextMenu);\n canvas.removeEventListener(\"keydown\", onKeyDown);\n canvas.removeEventListener(\"keyup\", onKeyUp);\n };\n}\n","/** Shared light base — world matrix state + dirty callback used by all light factories.\n * Eliminates boilerplate repeated across hemispheric, directional, point, and spot lights. */\n\nimport type { Mat4 } from \"../math/types.js\";\nimport type { IWorldMatrixProvider } from \"../scene/parentable.js\";\nimport { createWorldMatrixState, attachWorldMatrixState, type WorldMatrixAccessors } from \"../scene/world-matrix-state.js\";\n\nexport { ObservableVec3 } from \"../math/observable-vec3.js\";\n\n/** Monotonically increasing version counter — bumped whenever any UBO-relevant\n * property changes (position, direction, intensity, color, range, etc.).\n * Shared across all lights created from the same createLightBase call. */\nexport interface LightVersionState {\n /** @internal */\n _lightVersion: number;\n bump(): void;\n}\n\n/** Create the world-matrix state + dirty callback shared by all light types.\n * Returns `lvs` — a version state that callers bump when non-position properties change. */\nexport function createLightBase(getLocalMatrix: () => Mat4): { wm: WorldMatrixAccessors; onDirty: () => void; lvs: LightVersionState } {\n const wm = createWorldMatrixState(getLocalMatrix);\n const lvs: LightVersionState = {\n _lightVersion: 0,\n bump() {\n lvs._lightVersion++;\n },\n };\n const onDirty = () => {\n wm.markLocalDirty();\n lvs._lightVersion++;\n };\n return { wm, onDirty, lvs };\n}\n\n/** Mixin world-matrix accessors (parent, worldMatrix, worldMatrixVersion) onto a light object.\n * Also adds _lightVersion from the LightVersionState.\n * Returns the same object reference typed as R (defineProperties adds the accessors at runtime). */\nexport function applyWorldMatrixAccessors<R>(target: object, wm: WorldMatrixAccessors, lvs?: LightVersionState): R {\n Object.defineProperties(target, {\n parent: {\n get() {\n return wm.parent;\n },\n set(v: IWorldMatrixProvider | null) {\n wm.parent = v;\n },\n enumerable: true,\n configurable: true,\n },\n worldMatrix: {\n get() {\n return wm.getWorldMatrix();\n },\n enumerable: true,\n configurable: true,\n },\n worldMatrixVersion: {\n get() {\n return wm.getWorldMatrixVersion();\n },\n enumerable: true,\n configurable: true,\n },\n });\n if (lvs) {\n Object.defineProperty(target, \"_lightVersion\", {\n get() {\n return lvs._lightVersion;\n },\n enumerable: false,\n configurable: true,\n });\n }\n // Tag so children parented to this light get push invalidation (O(1) reads).\n attachWorldMatrixState(target, wm);\n return target as R;\n}\n","/** Shared light matrix helper — builds a local matrix from a direction vector + optional position. */\n\nimport type { Mat4 } from \"../math/types.js\";\n\n/** Build a local matrix from a direction vector + optional position.\n * Column 2 = forward (normalized direction), column 0 = right, column 1 = up. */\nexport function localMatrixFromDirection(dx: number, dy: number, dz: number, px = 0, py = 0, pz = 0, out?: Mat4): Mat4 {\n const flen = Math.sqrt(dx * dx + dy * dy + dz * dz) || 1;\n const fx = dx / flen,\n fy = dy / flen,\n fz = dz / flen;\n\n // Right = normalize(cross(worldUp, forward))\n let rx = -fz,\n rz = fx;\n const ry = 0;\n const rlen = Math.sqrt(rx * rx + ry * ry + rz * rz) || 1;\n rx /= rlen;\n rz /= rlen;\n\n // Up = cross(forward, right)\n const ux = fy * rz - fz * ry,\n uy = fz * rx - fx * rz,\n uz = fx * ry - fy * rx;\n\n const m = out ?? (new Float32Array(16) as Mat4);\n m[0] = rx;\n m[1] = ry;\n m[2] = rz;\n m[3] = 0;\n m[4] = ux;\n m[5] = uy;\n m[6] = uz;\n m[7] = 0;\n m[8] = fx;\n m[9] = fy;\n m[10] = fz;\n m[11] = 0;\n m[12] = px;\n m[13] = py;\n m[14] = pz;\n m[15] = 1;\n return m;\n}\n","/** Hemispheric light data.\n * Push-based dirty tracking via ObservableVec3. */\n\nimport type { LightBase } from \"./types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { createLightBase, applyWorldMatrixAccessors, ObservableVec3 } from \"./light-base.js\";\nimport { localMatrixFromDirection } from \"./light-matrix.js\";\nimport type { Mat4 } from \"../math/types.js\";\n\nexport interface HemisphericLight extends LightBase {\n readonly lightType: \"hemispheric\";\n direction: ObservableVec3;\n intensity: number;\n diffuseColor: [number, number, number];\n specularColor: [number, number, number];\n groundColor: [number, number, number];\n}\n\n/** Create a hemispheric light. Returns plain data — caller adds to scene.\n * Matches Babylon.js HemisphericLight behavior. */\nexport function createHemisphericLight(direction: [number, number, number] = [0, 1, 0], intensity: number = 1.0): HemisphericLight {\n const _localMatrix = new Float32Array(16) as Mat4;\n const { wm, onDirty, lvs } = createLightBase(() => localMatrixFromDirection(light.direction.x, light.direction.y, light.direction.z, 0, 0, 0, _localMatrix));\n\n const light = applyWorldMatrixAccessors<HemisphericLight>(\n {\n lightType: \"hemispheric\" as const,\n children: [] as SceneNode[],\n direction: new ObservableVec3(direction[0], direction[1], direction[2], onDirty),\n intensity,\n diffuseColor: [1, 1, 1] as [number, number, number],\n specularColor: [1, 1, 1] as [number, number, number],\n groundColor: [0, 0, 0] as [number, number, number],\n\n _writeLightUbo: (data: Float32Array, offset: number) => {\n const o = offset;\n const w = light.worldMatrix;\n // Direction = worldMatrix column 2\n data[o] = w[8]!;\n data[o + 1] = w[9]!;\n data[o + 2] = w[10]!;\n data[o + 3] = 3;\n data[o + 4] = light.diffuseColor[0] * light.intensity;\n data[o + 5] = light.diffuseColor[1] * light.intensity;\n data[o + 6] = light.diffuseColor[2] * light.intensity;\n data[o + 8] = light.specularColor[0] * light.intensity;\n data[o + 9] = light.specularColor[1] * light.intensity;\n data[o + 10] = light.specularColor[2] * light.intensity;\n data[o + 12] = light.groundColor[0] * light.intensity;\n data[o + 13] = light.groundColor[1] * light.intensity;\n data[o + 14] = light.groundColor[2] * light.intensity;\n },\n },\n wm,\n lvs\n );\n return light;\n}\n","import type { Mat4 } from \"./types.js\";\nimport { mat4Identity } from \"./mat4-identity.js\";\n\n/** Create a translation matrix. */\nexport function mat4Translation(x: number, y: number, z: number): Mat4 {\n const out = mat4Identity();\n out[12] = x;\n out[13] = y;\n out[14] = z;\n return out;\n}\n","/** PointLight — position-based light with falloff.\n * Plain data, no scene knowledge (pillar 4b).\n * Push-based dirty tracking via ObservableVec3. */\n\nimport type { LightBase } from \"./types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { mat4Translation } from \"../math/mat4-translation.js\";\nimport { createLightBase, applyWorldMatrixAccessors, ObservableVec3 } from \"./light-base.js\";\n\nexport interface PointLight extends LightBase {\n readonly lightType: \"point\";\n position: ObservableVec3;\n diffuse: [number, number, number];\n specular: [number, number, number];\n intensity: number;\n range: number;\n}\n\n/**\n * Creates a point light that emits in all directions from `position` with distance falloff.\n * @param position - World-space position of the light.\n * @param intensity - Scalar multiplier applied to the light's diffuse and specular contribution.\n * @returns Plain `PointLight` data to be added to a scene via `addToScene`.\n */\nexport function createPointLight(position: [number, number, number], intensity = 1.0): PointLight {\n const { wm, onDirty, lvs } = createLightBase(() => mat4Translation(light.position.x, light.position.y, light.position.z));\n\n const light = applyWorldMatrixAccessors<PointLight>(\n {\n lightType: \"point\" as const,\n children: [] as SceneNode[],\n position: new ObservableVec3(position[0], position[1], position[2], onDirty),\n diffuse: [1, 1, 1] as [number, number, number],\n specular: [1, 1, 1] as [number, number, number],\n intensity,\n range: Number.MAX_VALUE,\n\n _writeLightUbo: (data: Float32Array, offset: number) => {\n const o = offset;\n const w = light.worldMatrix;\n data[o] = w[12]!;\n data[o + 1] = w[13]!;\n data[o + 2] = w[14]!;\n data[o + 3] = 0;\n data[o + 4] = light.diffuse[0] * light.intensity;\n data[o + 5] = light.diffuse[1] * light.intensity;\n data[o + 6] = light.diffuse[2] * light.intensity;\n data[o + 7] = light.range;\n data[o + 8] = light.specular[0] * light.intensity;\n data[o + 9] = light.specular[1] * light.intensity;\n data[o + 10] = light.specular[2] * light.intensity;\n },\n },\n wm,\n lvs\n );\n return light;\n}\n","/** DirectionalLight — plain data (pillar 4b: no scene reference).\n * Push-based dirty tracking via ObservableVec3. */\n\nimport type { LightBase } from \"./types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { createLightBase, applyWorldMatrixAccessors, ObservableVec3 } from \"./light-base.js\";\nimport { localMatrixFromDirection } from \"./light-matrix.js\";\nimport type { Mat4 } from \"../math/types.js\";\n\nexport interface DirectionalLight extends LightBase {\n readonly lightType: \"directional\";\n direction: ObservableVec3;\n position: ObservableVec3;\n diffuse: [number, number, number];\n specular: [number, number, number];\n intensity: number;\n}\n\n/**\n * Creates a directional light shining along `direction` (a parallel light source, like the sun).\n * @param direction - World-space direction the light travels along.\n * @param intensity - Scalar multiplier applied to the light's diffuse and specular contribution.\n * @returns Plain `DirectionalLight` data to be added to a scene via `addToScene`.\n */\nexport function createDirectionalLight(direction: [number, number, number], intensity = 1): DirectionalLight {\n const _localMatrix = new Float32Array(16) as Mat4;\n const { wm, onDirty, lvs } = createLightBase(() =>\n localMatrixFromDirection(light.direction.x, light.direction.y, light.direction.z, light.position.x, light.position.y, light.position.z, _localMatrix)\n );\n\n const light = applyWorldMatrixAccessors<DirectionalLight>(\n {\n lightType: \"directional\" as const,\n children: [] as SceneNode[],\n direction: new ObservableVec3(direction[0], direction[1], direction[2], onDirty),\n position: new ObservableVec3(0, 0, 0, onDirty),\n diffuse: [1, 1, 1] as [number, number, number],\n specular: [1, 1, 1] as [number, number, number],\n intensity,\n\n _writeLightUbo: (data: Float32Array, offset: number) => {\n const o = offset;\n const w = light.worldMatrix;\n // Direction = worldMatrix column 2\n data[o] = w[8]!;\n data[o + 1] = w[9]!;\n data[o + 2] = w[10]!;\n data[o + 3] = 1;\n data[o + 4] = light.diffuse[0] * light.intensity;\n data[o + 5] = light.diffuse[1] * light.intensity;\n data[o + 6] = light.diffuse[2] * light.intensity;\n data[o + 7] = Number.MAX_VALUE;\n data[o + 8] = light.specular[0] * light.intensity;\n data[o + 9] = light.specular[1] * light.intensity;\n data[o + 10] = light.specular[2] * light.intensity;\n },\n },\n wm,\n lvs\n );\n return light;\n}\n","/** SpotLight — cone-shaped light with position, direction, angle, and exponent falloff.\n * Plain data, no scene knowledge (pillar 4b).\n * Push-based dirty tracking via ObservableVec3. */\n\nimport type { LightBase } from \"./types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { createLightBase, applyWorldMatrixAccessors, ObservableVec3 } from \"./light-base.js\";\nimport { localMatrixFromDirection } from \"./light-matrix.js\";\nimport type { Mat4 } from \"../math/types.js\";\n\nexport interface SpotLight extends LightBase {\n readonly lightType: \"spot\";\n position: ObservableVec3;\n direction: ObservableVec3;\n /** Full cone angle in radians. */\n angle: number;\n /** Falloff exponent — higher = sharper spotlight. */\n exponent: number;\n diffuse: [number, number, number];\n specular: [number, number, number];\n intensity: number;\n range: number;\n}\n\n/**\n * Creates a spot light: a cone of light from `position` aimed along `direction`.\n * @param position - World-space position of the light.\n * @param direction - World-space direction the cone points along.\n * @param angle - Full cone angle in radians.\n * @param exponent - Falloff exponent; higher values produce a sharper edge.\n * @param intensity - Scalar multiplier applied to the light's diffuse and specular contribution.\n * @returns Plain `SpotLight` data to be added to a scene via `addToScene`.\n */\nexport function createSpotLight(position: [number, number, number], direction: [number, number, number], angle: number, exponent: number, intensity = 1.0): SpotLight {\n const _localMatrix = new Float32Array(16) as Mat4;\n const { wm, onDirty, lvs } = createLightBase(() =>\n localMatrixFromDirection(light.direction.x, light.direction.y, light.direction.z, light.position.x, light.position.y, light.position.z, _localMatrix)\n );\n\n // Pre-compute cosHalfAngle; updated via Object.defineProperty when angle changes\n let _angle = angle;\n let _cosHalfAngle = Math.cos(angle * 0.5);\n\n const light = applyWorldMatrixAccessors<SpotLight>(\n {\n lightType: \"spot\" as const,\n children: [] as SceneNode[],\n position: new ObservableVec3(position[0], position[1], position[2], onDirty),\n direction: new ObservableVec3(direction[0], direction[1], direction[2], onDirty),\n angle: 0 as number, // placeholder — overridden by defineProperty below\n exponent,\n diffuse: [1, 1, 1] as [number, number, number],\n specular: [1, 1, 1] as [number, number, number],\n intensity,\n range: Number.MAX_VALUE,\n\n _writeLightUbo: (data: Float32Array, offset: number) => {\n const o = offset;\n const w = light.worldMatrix;\n // Position = worldMatrix column 3\n data[o] = w[12]!;\n data[o + 1] = w[13]!;\n data[o + 2] = w[14]!;\n data[o + 3] = 2;\n data[o + 4] = light.diffuse[0] * light.intensity;\n data[o + 5] = light.diffuse[1] * light.intensity;\n data[o + 6] = light.diffuse[2] * light.intensity;\n data[o + 7] = light.range;\n data[o + 8] = light.specular[0] * light.intensity;\n data[o + 9] = light.specular[1] * light.intensity;\n data[o + 10] = light.specular[2] * light.intensity;\n data[o + 11] = light.exponent;\n // Direction = worldMatrix column 2\n data[o + 12] = w[8]!;\n data[o + 13] = w[9]!;\n data[o + 14] = w[10]!;\n data[o + 15] = _cosHalfAngle;\n },\n },\n wm,\n lvs\n );\n\n // Push-based dirty tracking for angle — recompute cosHalfAngle on change\n Object.defineProperty(light, \"angle\", {\n get() {\n return _angle;\n },\n set(v: number) {\n if (v !== _angle) {\n _angle = v;\n _cosHalfAngle = Math.cos(v * 0.5);\n lvs.bump();\n }\n },\n configurable: true,\n enumerable: true,\n });\n\n return light;\n}\n","/** Compose TRS directly into a Float32Array at offset (zero allocation). */\nexport function mat4ComposeInto(\n dst: Float32Array,\n off: number,\n tx: number,\n ty: number,\n tz: number,\n qx: number,\n qy: number,\n qz: number,\n qw: number,\n sx: number,\n sy: number,\n sz: number\n): void {\n const xx = qx * qx,\n yy = qy * qy,\n zz = qz * qz;\n const xy = qx * qy,\n xz = qx * qz,\n yz = qy * qz;\n const wx = qw * qx,\n wy = qw * qy,\n wz = qw * qz;\n dst[off] = (1 - 2 * (yy + zz)) * sx;\n dst[off + 1] = 2 * (xy + wz) * sx;\n dst[off + 2] = 2 * (xz - wy) * sx;\n dst[off + 3] = 0;\n dst[off + 4] = 2 * (xy - wz) * sy;\n dst[off + 5] = (1 - 2 * (xx + zz)) * sy;\n dst[off + 6] = 2 * (yz + wx) * sy;\n dst[off + 7] = 0;\n dst[off + 8] = 2 * (xz + wy) * sz;\n dst[off + 9] = 2 * (yz - wx) * sz;\n dst[off + 10] = (1 - 2 * (xx + yy)) * sz;\n dst[off + 11] = 0;\n dst[off + 12] = tx;\n dst[off + 13] = ty;\n dst[off + 14] = tz;\n dst[off + 15] = 1;\n}\n","import type { Mat4 } from \"./types.js\";\nimport { mat4ComposeInto } from \"./mat4-compose-into.js\";\n\n/** Compose TRS (translation * rotation * scale) into a single Mat4. */\nexport function mat4Compose(tx: number, ty: number, tz: number, qx: number, qy: number, qz: number, qw: number, sx: number, sy: number, sz: number): Mat4 {\n const out = new Float32Array(16) as Mat4;\n mat4ComposeInto(out, 0, tx, ty, tz, qx, qy, qz, qw, sx, sy, sz);\n return out;\n}\n","/** ObservableQuat — a 4-component quaternion with setters that notify on change.\n * Used for TransformNode.rotationQuaternion so the hierarchy system\n * can detect rotation changes via a version counter.\n * Same pattern as ObservableVec3. V8 inlines trivial getters/setters. */\n\nimport type { Quat } from \"./types.js\";\n\n/**\n * A 4-component quaternion whose `x`/`y`/`z`/`w` setters fire an `onDirty` callback\n * when a component actually changes, letting the hierarchy system detect rotation updates.\n */\nexport class ObservableQuat implements Quat {\n private _x: number;\n private _y: number;\n private _z: number;\n private _w: number;\n private readonly _onDirty: () => void;\n\n constructor(x: number, y: number, z: number, w: number, onDirty: () => void) {\n this._x = x;\n this._y = y;\n this._z = z;\n this._w = w;\n this._onDirty = onDirty;\n }\n\n get x(): number {\n return this._x;\n }\n set x(v: number) {\n if (this._x !== v) {\n this._x = v;\n this._onDirty();\n }\n }\n\n get y(): number {\n return this._y;\n }\n set y(v: number) {\n if (this._y !== v) {\n this._y = v;\n this._onDirty();\n }\n }\n\n get z(): number {\n return this._z;\n }\n set z(v: number) {\n if (this._z !== v) {\n this._z = v;\n this._onDirty();\n }\n }\n\n get w(): number {\n return this._w;\n }\n set w(v: number) {\n if (this._w !== v) {\n this._w = v;\n this._onDirty();\n }\n }\n\n /** Bulk set — one dirty notification instead of four. */\n set(x: number, y: number, z: number, w: number): void {\n this._x = x;\n this._y = y;\n this._z = z;\n this._w = w;\n this._onDirty();\n }\n\n /** Copy values from another quaternion. */\n copyFrom(q: Quat): void {\n this.set(q.x, q.y, q.z, q.w);\n }\n\n /** Copy into a Float32Array at offset. */\n toArray(out: Float32Array, offset = 0): void {\n out[offset] = this._x;\n out[offset + 1] = this._y;\n out[offset + 2] = this._z;\n out[offset + 3] = this._w;\n }\n}\n","/** SceneNode — common base for all scene entities with TRS, parent, and children.\n *\n * Provides position, rotationQuaternion (source of truth), rotation (Euler XYZ proxy),\n * scaling, parent, worldMatrix, worldMatrixVersion, and children. */\n\nimport type { Mat4 } from \"../math/types.js\";\nimport type { IWorldMatrixProvider } from \"./parentable.js\";\nimport { mat4Compose } from \"../math/mat4-compose.js\";\nimport { mat4Identity } from \"../math/mat4-identity.js\";\nimport { ObservableVec3 } from \"../math/observable-vec3.js\";\nimport { ObservableQuat } from \"../math/observable-quat.js\";\nimport { createWorldMatrixState, attachWorldMatrixState } from \"./world-matrix-state.js\";\n\n// ─── EulerProxy ──────────────────────────────────────────────────────\n\n/** Bidirectional Euler XYZ view over a quaternion.\n * Reads decompose the current quaternion on the fly; writes convert Euler→quat atomically. */\nexport interface EulerProxy {\n x: number;\n y: number;\n z: number;\n set(x: number, y: number, z: number): void;\n}\n\n// ─── SceneNode ───────────────────────────────────────────────────────\n\n/** Common base for all scene entities: TRS transform, parent/children hierarchy, and a cached world matrix. */\nexport interface SceneNode {\n name: string;\n children: SceneNode[];\n position: ObservableVec3;\n /** Quaternion rotation — source of truth for the local matrix. */\n rotationQuaternion: ObservableQuat;\n /** Euler XYZ bidirectional proxy — reads decompose current quat; writes update quat atomically. */\n rotation: EulerProxy;\n scaling: ObservableVec3;\n parent: IWorldMatrixProvider | null;\n readonly worldMatrix: Mat4;\n readonly worldMatrixVersion: number;\n /** @internal Raw local matrix for glTF matrix nodes. */\n _localMatrix?: Mat4;\n /** Self-visibility. Undefined/true = visible; `false` skips render + camera AABB.\n * Cascade is materialized at write-time by `setSubtreeVisible`. */\n visible?: boolean;\n}\n\n// ─── Math helpers ─────────────────────────────────────────────────────\n\n/** Euler XYZ → quaternion (intrinsic XYZ order). */\nexport function eulerToQuat(rx: number, ry: number, rz: number): [number, number, number, number] {\n const cx = Math.cos(rx * 0.5),\n sx_ = Math.sin(rx * 0.5);\n const cy = Math.cos(ry * 0.5),\n sy_ = Math.sin(ry * 0.5);\n const cz = Math.cos(rz * 0.5),\n sz_ = Math.sin(rz * 0.5);\n return [sx_ * cy * cz + cx * sy_ * sz_, cx * sy_ * cz - sx_ * cy * sz_, cx * cy * sz_ + sx_ * sy_ * cz, cx * cy * cz - sx_ * sy_ * sz_];\n}\n\n/** Quaternion → Euler XYZ (inverse of eulerToQuat). */\nexport function quatToEulerXYZ(qx: number, qy: number, qz: number, qw: number): [number, number, number] {\n const sinY = 2 * (qx * qz + qw * qy);\n const ry = Math.asin(Math.max(-1, Math.min(1, sinY)));\n const rx = Math.atan2(-(2 * (qy * qz - qw * qx)), 1 - 2 * (qx * qx + qy * qy));\n const rz = Math.atan2(-(2 * (qx * qy - qw * qz)), 1 - 2 * (qy * qy + qz * qz));\n return [rx, ry, rz];\n}\n\n/** Create a live bidirectional EulerProxy backed by the given ObservableQuat. */\nexport function createEulerProxy(rq: ObservableQuat): EulerProxy {\n const e = () => quatToEulerXYZ(rq.x, rq.y, rq.z, rq.w);\n const s = (x: number, y: number, z: number) => {\n const [a, b, c, d] = eulerToQuat(x, y, z);\n rq.set(a, b, c, d);\n };\n return {\n get x() {\n return e()[0];\n },\n set x(v: number) {\n const r = e();\n s(v, r[1], r[2]);\n },\n get y() {\n return e()[1];\n },\n set y(v: number) {\n const r = e();\n s(r[0], v, r[2]);\n },\n get z() {\n return e()[2];\n },\n set z(v: number) {\n const r = e();\n s(r[0], r[1], v);\n },\n set: s,\n };\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────\n\n/** Create a SceneNode with given TRS (position and scaling in cartesian, rotation as quaternion). */\nexport function createSceneNode(name: string, px = 0, py = 0, pz = 0, qx = 0, qy = 0, qz = 0, qw = 1, sx = 1, sy = 1, sz = 1): SceneNode {\n return createSceneNodeCore(name, null, px, py, pz, qx, qy, qz, qw, sx, sy, sz);\n}\n\nexport function createSceneNodeFromMatrix(name: string, matrix: Mat4): SceneNode {\n return createSceneNodeCore(name, matrix);\n}\n\nfunction createSceneNodeCore(name: string, matrix: Mat4 | null, px = 0, py = 0, pz = 0, qx = 0, qy = 0, qz = 0, qw = 1, sx = 1, sy = 1, sz = 1): SceneNode {\n const wm = createWorldMatrixState(() => {\n if (matrix) {\n return matrix;\n }\n const p = node.position,\n rq = node.rotationQuaternion,\n s = node.scaling;\n const isIdentity = p.x === 0 && p.y === 0 && p.z === 0 && rq.x === 0 && rq.y === 0 && rq.z === 0 && rq.w === 1 && s.x === 1 && s.y === 1 && s.z === 1;\n return isIdentity ? mat4Identity() : mat4Compose(p.x, p.y, p.z, rq.x, rq.y, rq.z, rq.w, s.x, s.y, s.z);\n });\n const onWmDirty = () => {\n if (!matrix) {\n wm.markLocalDirty();\n }\n };\n\n const rq = new ObservableQuat(qx, qy, qz, qw, onWmDirty);\n\n const node: SceneNode = {\n name,\n children: [],\n position: new ObservableVec3(px, py, pz, onWmDirty),\n rotationQuaternion: rq,\n rotation: createEulerProxy(rq),\n scaling: new ObservableVec3(sx, sy, sz, onWmDirty),\n get parent() {\n return wm.parent;\n },\n set parent(v) {\n wm.parent = v;\n },\n get worldMatrix() {\n return wm.getWorldMatrix();\n },\n get worldMatrixVersion() {\n return wm.getWorldMatrixVersion();\n },\n };\n if (matrix) {\n node._localMatrix = matrix;\n }\n attachWorldMatrixState(node, wm);\n return node;\n}\n","/** High-level Mesh — position/rotation/scaling + material + GPU geometry.\n * Plain data (no scene reference). The scene collects meshes via addToScene(). */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport { mat4Compose } from \"../math/mat4-compose.js\";\nimport { mat4Identity } from \"../math/mat4-identity.js\";\nimport type { Material } from \"../material/material.js\";\nimport type { SkeletonData, MorphTargetData } from \"../animation/types.js\";\nimport { ObservableVec3 } from \"../math/observable-vec3.js\";\nimport { ObservableQuat } from \"../math/observable-quat.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport { createWorldMatrixState, attachWorldMatrixState } from \"../scene/world-matrix-state.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { eulerToQuat, createEulerProxy } from \"../scene/scene-node.js\";\n\n// ─── Mesh GPU Geometry ───────────────────────────────────────────────\n\n/** Per-attribute interleave override. When present, the attribute's GPU buffer\n * is a shared interleaved slice: the pipeline uses `_stride` as the vertex\n * buffer arrayStride and the draw binds the buffer at byte offset `_offset`.\n * Absent attributes use the canonical tight layout (own buffer, default stride,\n * offset 0) — byte-identical to non-interleaved meshes. */\nexport interface MeshVbAttr {\n /** @internal Vertex buffer arrayStride for this attribute's pipeline layout entry. */\n readonly _stride: number;\n /** @internal Byte offset passed to setVertexBuffer (bind offset into the shared buffer). */\n readonly _offset: number;\n}\n\n/** Optional per-attribute interleave layout. Only set for meshes that source one\n * or more attributes from a strided (interleaved) glTF bufferView. */\nexport interface MeshVbLayout {\n /** @internal */\n readonly _p?: MeshVbAttr;\n /** @internal */\n readonly _n?: MeshVbAttr;\n /** @internal */\n readonly _t?: MeshVbAttr;\n /** @internal */\n readonly _u?: MeshVbAttr;\n /** @internal */\n readonly _u2?: MeshVbAttr;\n /** @internal */\n readonly _c?: MeshVbAttr;\n}\n\n/** Opaque GPU geometry handle (user never touches these). */\nexport interface MeshGPU {\n readonly positionBuffer: GPUBuffer;\n readonly normalBuffer: GPUBuffer;\n readonly tangentBuffer?: GPUBuffer | null;\n readonly uvBuffer: GPUBuffer;\n readonly uv2Buffer?: GPUBuffer | null;\n readonly colorBuffer?: GPUBuffer | null;\n readonly hasUv?: boolean;\n readonly hasUv2?: boolean;\n readonly hasTangent?: boolean;\n readonly hasColor?: boolean;\n readonly indexBuffer: GPUBuffer;\n readonly indexCount: number;\n readonly indexFormat: GPUIndexFormat;\n /** @internal Per-attribute interleave layout. Undefined → all attributes tight (default). */\n readonly _vbLayout?: MeshVbLayout;\n /** @internal Precomputed pipeline cache-key suffix for this mesh's interleave layout.\n * Built once by the interleave module so the hot render path never assembles\n * it. Undefined → tight mesh (empty suffix, byte-identical pipeline key). */\n readonly _vbKey?: string;\n}\n\n// ─── Mesh ────────────────────────────────────────────────────────────\n\n/** A renderable mesh — plain data with transform, material, and GPU geometry.\n * Works with both standard and PBR pipelines; routing is based on material type.\n * Extends SceneNode for the full TRS + parent + children hierarchy. */\nexport interface Mesh extends SceneNode {\n /** Unique ID from source file (e.g. .babylon). Used for light include/exclude filtering. */\n id?: string;\n material: Material;\n receiveShadows: boolean;\n /** World-space bounding box (set by loaders for camera framing). */\n boundMin?: [number, number, number];\n boundMax?: [number, number, number];\n /** Skeleton GPU data (skeletal animation). Type-only — no module dependency. */\n skeleton?: SkeletonData | null;\n /** Morph target GPU data. Type-only — no module dependency. */\n morphTargets?: MorphTargetData | null;\n /** User-controlled render order. Lower = drawn first within phase.\n * Only affects ordering within the opaque or transparent phase. */\n renderOrder?: number;\n /** Thin instance data (CPU-side). GPU buffer managed by render system. */\n thinInstances?: ThinInstanceData | null;\n // name, children, position, rotation, rotationQuaternion, scaling,\n // parent, worldMatrix, worldMatrixVersion — all inherited from SceneNode\n\n /** @internal */\n _materialDirty: boolean;\n /** @internal */\n _gpu: MeshGPU;\n /** @internal */\n _cpuPositions?: Float32Array;\n /** @internal */\n _cpuNormals?: Float32Array;\n /** @internal */\n _cpuUvs?: Float32Array;\n /** @internal */\n _cpuUv2s?: Float32Array | null;\n /** @internal */\n _cpuTangents?: Float32Array | null;\n /** @internal */\n _cpuColors?: Float32Array | null;\n /** @internal */\n _cpuIndices?: Uint32Array;\n /** @internal */\n _cpuGpuIndices?: Uint16Array | Uint32Array;\n /** @internal */\n _cpuIndexFormat?: GPUIndexFormat;\n}\n\n/** Wire ObservableVec3/ObservableQuat TRS and children onto a partially-built mesh object.\n * Used by all mesh creation paths (factories, loaders). */\nexport function initMeshTransform(mesh: Mesh, px = 0, py = 0, pz = 0, rx = 0, ry = 0, rz = 0, sx = 1, sy = 1, sz = 1): void {\n const wm = createWorldMatrixState(() => {\n const p = mesh.position,\n rq = mesh.rotationQuaternion,\n s = mesh.scaling;\n const isIdentity = p.x === 0 && p.y === 0 && p.z === 0 && rq.x === 0 && rq.y === 0 && rq.z === 0 && rq.w === 1 && s.x === 1 && s.y === 1 && s.z === 1;\n return isIdentity ? mat4Identity() : mat4Compose(p.x, p.y, p.z, rq.x, rq.y, rq.z, rq.w, s.x, s.y, s.z);\n });\n const onWmDirty = () => wm.markLocalDirty();\n\n const [iqx, iqy, iqz, iqw] = eulerToQuat(rx, ry, rz);\n const rq = new ObservableQuat(iqx, iqy, iqz, iqw, onWmDirty);\n mesh.rotationQuaternion = rq;\n mesh.rotation = createEulerProxy(rq);\n mesh.position = new ObservableVec3(px, py, pz, onWmDirty);\n mesh.scaling = new ObservableVec3(sx, sy, sz, onWmDirty);\n\n if (!(mesh as unknown as Record<string, unknown>).children) {\n (mesh as unknown as Record<string, unknown>).children = [];\n }\n\n Object.defineProperty(mesh, \"parent\", {\n get() {\n return wm.parent;\n },\n set(v) {\n wm.parent = v;\n },\n configurable: true,\n enumerable: true,\n });\n Object.defineProperty(mesh, \"worldMatrix\", {\n get() {\n return wm.getWorldMatrix();\n },\n configurable: true,\n enumerable: false,\n });\n Object.defineProperty(mesh, \"worldMatrixVersion\", {\n get() {\n return wm.getWorldMatrixVersion();\n },\n configurable: true,\n enumerable: false,\n });\n attachWorldMatrixState(mesh, wm);\n}\n\n// ─── GPU Geometry Upload ─────────────────────────────────────────────\n\n/** Upload typed arrays to GPU buffers and return a MeshGPU handle. */\nexport function uploadMeshToGPU(\n engine: EngineContext,\n positions: Float32Array,\n normals: Float32Array,\n indices: Uint32Array,\n uvs?: Float32Array,\n uvs2?: Float32Array,\n tangents?: Float32Array,\n colors?: Float32Array\n): MeshGPU {\n const device = engine._device;\n const positionBuffer = createMappedBuffer(engine, positions, GPUBufferUsage.VERTEX);\n const normalBuffer = createMappedBuffer(engine, normals, GPUBufferUsage.VERTEX);\n const indexBuffer = createMappedBuffer(engine, indices, GPUBufferUsage.INDEX);\n\n // UVs: use provided or create zero-filled buffer\n let uvBuffer: GPUBuffer;\n if (uvs && uvs.length > 0) {\n uvBuffer = createMappedBuffer(engine, uvs, GPUBufferUsage.VERTEX);\n } else {\n uvBuffer = device.createBuffer({\n size: (positions.length / 3) * 8,\n usage: GPUBufferUsage.VERTEX,\n mappedAtCreation: true,\n });\n uvBuffer.unmap();\n }\n\n // UV2: only create if provided\n let uv2Buffer: GPUBuffer | null = null;\n if (uvs2 && uvs2.length > 0) {\n uv2Buffer = createMappedBuffer(engine, uvs2, GPUBufferUsage.VERTEX);\n }\n\n const tangentBuffer = tangents && tangents.length > 0 ? createMappedBuffer(engine, tangents, GPUBufferUsage.VERTEX) : null;\n const colorBuffer = colors && colors.length > 0 ? createMappedBuffer(engine, colors, GPUBufferUsage.VERTEX) : null;\n\n return {\n positionBuffer,\n normalBuffer,\n uvBuffer,\n uv2Buffer,\n tangentBuffer,\n colorBuffer,\n hasUv: !!uvs && uvs.length > 0,\n hasUv2: !!uvs2 && uvs2.length > 0,\n hasTangent: !!tangents && tangents.length > 0,\n hasColor: !!colors && colors.length > 0,\n indexBuffer,\n indexCount: indices.length,\n indexFormat: \"uint32\",\n };\n}\n","/** Axis-aligned bounding box helpers. */\n\nimport type { Aabb } from \"./aabb.js\";\nimport type { Mat4 } from \"./types.js\";\n\n/** Compute an AABB by folding XYZ min/max over a positions buffer.\n *\n * When `world` is provided each position is transformed by it before being\n * folded (column-major Mat4: m[col*4+row]). Otherwise the AABB is computed\n * in the positions' own space.\n *\n * Returns `[[+Inf,+Inf,+Inf],[-Inf,-Inf,-Inf]]` for empty input — callers\n * that care can check `isFinite(min[0])`. */\nexport function computeAabb(positions: Float32Array, world?: Mat4): Aabb {\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n if (world) {\n const m0 = world[0]!,\n m1 = world[1]!,\n m2 = world[2]!,\n m4 = world[4]!,\n m5 = world[5]!,\n m6 = world[6]!,\n m8 = world[8]!,\n m9 = world[9]!,\n m10 = world[10]!,\n m12 = world[12]!,\n m13 = world[13]!,\n m14 = world[14]!;\n for (let i = 0; i < positions.length; i += 3) {\n const lx = positions[i]!;\n const ly = positions[i + 1]!;\n const lz = positions[i + 2]!;\n const x = m0 * lx + m4 * ly + m8 * lz + m12;\n const y = m1 * lx + m5 * ly + m9 * lz + m13;\n const z = m2 * lx + m6 * ly + m10 * lz + m14;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n } else {\n for (let i = 0; i < positions.length; i += 3) {\n const x = positions[i]!;\n const y = positions[i + 1]!;\n const z = positions[i + 2]!;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n }\n\n return [\n [minX, minY, minZ],\n [maxX, maxY, maxZ],\n ];\n}\n","/** Procedural UV sphere — matches Babylon MeshBuilder.CreateSphere defaults.\n * Generates vertex positions, normals, and indices for a unit sphere.\n * Left-handed winding (CCW front face) to match Babylon. */\n\nexport interface SphereMeshData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n vertexCount: number;\n indexCount: number;\n}\n\n/** Options for {@link createSphereData}. Subset of Babylon's CreateSphere. */\nexport interface SphereOptions {\n segments?: number;\n diameter?: number;\n diameterX?: number;\n diameterY?: number;\n diameterZ?: number;\n}\n\n/** Generate UV sphere geometry matching Babylon's CreateSphere exactly.\n * Babylon uses: totalZ = 2 + segments rows, totalY = 2 * totalZ columns.\n * Default: 32 segments → 35×69 = 2415 vertices. */\nexport function createSphereData(options: SphereOptions = {}): SphereMeshData {\n const segments = Math.max(3, options.segments ?? 32);\n const baseDiameter = options.diameter ?? 1;\n const rx = (options.diameterX ?? baseDiameter) / 2;\n const ry = (options.diameterY ?? baseDiameter) / 2;\n const rz = (options.diameterZ ?? baseDiameter) / 2;\n\n // Babylon's sphere tessellation formula\n const totalZRotationSteps = 2 + segments;\n const totalYRotationSteps = 2 * totalZRotationSteps;\n\n const totalVertices = (totalZRotationSteps + 1) * (totalYRotationSteps + 1);\n const totalIndices = totalZRotationSteps * totalYRotationSteps * 6;\n\n const positions = new Float32Array(totalVertices * 3);\n const normals = new Float32Array(totalVertices * 3);\n const uvs = new Float32Array(totalVertices * 2);\n const indices = new Uint32Array(totalIndices);\n\n let vIdx = 0;\n for (let zStep = 0; zStep <= totalZRotationSteps; zStep++) {\n const normalizedZ = zStep / totalZRotationSteps;\n const angleZ = normalizedZ * Math.PI;\n\n for (let yStep = 0; yStep <= totalYRotationSteps; yStep++) {\n const normalizedY = yStep / totalYRotationSteps;\n const angleY = normalizedY * Math.PI * 2;\n\n const nx = Math.sin(angleZ) * Math.cos(angleY);\n const ny = Math.cos(angleZ);\n const nz = -Math.sin(angleZ) * Math.sin(angleY);\n\n positions[vIdx * 3] = rx * nx;\n positions[vIdx * 3 + 1] = ry * ny;\n positions[vIdx * 3 + 2] = rz * nz;\n\n normals[vIdx * 3] = nx;\n normals[vIdx * 3 + 1] = ny;\n normals[vIdx * 3 + 2] = nz;\n\n uvs[vIdx * 2] = normalizedY;\n uvs[vIdx * 2 + 1] = normalizedZ;\n\n vIdx++;\n }\n }\n\n // Indices — triangulate quads\n let iIdx = 0;\n for (let zStep = 0; zStep < totalZRotationSteps; zStep++) {\n for (let yStep = 0; yStep < totalYRotationSteps; yStep++) {\n const a = zStep * (totalYRotationSteps + 1) + yStep;\n const b = a + totalYRotationSteps + 1;\n\n indices[iIdx++] = a;\n indices[iIdx++] = a + 1;\n indices[iIdx++] = b;\n\n indices[iIdx++] = b;\n indices[iIdx++] = a + 1;\n indices[iIdx++] = b + 1;\n }\n }\n\n return {\n positions,\n normals,\n uvs,\n indices,\n vertexCount: totalVertices,\n indexCount: totalIndices,\n };\n}\n","/**\n * CreateBox — procedural box mesh matching Babylon.js MeshBuilder.CreateBox()\n *\n * Generates a unit box (size=1, extends from -0.5 to 0.5) with:\n * - 24 vertices (4 per face × 6 faces)\n * - 36 indices (2 triangles per face × 6 faces)\n * - Per-face normals (axis-aligned)\n *\n * Face order matches Babylon exactly: +Z, -Z, +X, -X, +Y, -Y\n */\n\nexport interface BoxData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n vertexCount: number;\n indexCount: number;\n}\n\n// prettier-ignore\nconst BOX_POSITIONS = new Float32Array([\n // +Z face\n 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5,\n // -Z face\n 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5,\n // +X face\n 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5,\n // -X face\n -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5,\n // +Y face\n -0.5, 0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5,\n // -Y face\n 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5,\n]);\n\n// prettier-ignore\nconst BOX_NORMALS = new Float32Array([\n // +Z\n 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,\n // -Z\n 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1,\n // +X\n 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,\n // -X\n -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,\n // +Y\n 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,\n // -Y\n 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0,\n]);\n\n// prettier-ignore\nconst BOX_UVS = new Float32Array([\n // Each face: (1,1), (0,1), (0,0), (1,0) — matching BJS box UV layout\n 1, 1, 0, 1, 0, 0, 1, 0, // +Z\n 1, 1, 0, 1, 0, 0, 1, 0, // -Z\n 1, 1, 0, 1, 0, 0, 1, 0, // +X\n 1, 1, 0, 1, 0, 0, 1, 0, // -X\n 1, 1, 0, 1, 0, 0, 1, 0, // +Y\n 1, 1, 0, 1, 0, 0, 1, 0, // -Y\n]);\n\n// prettier-ignore\nconst BOX_INDICES = new Uint32Array([\n 0, 1, 2, 0, 2, 3,\n 4, 5, 6, 4, 6, 7,\n 8, 9, 10, 8, 10, 11,\n 12, 13, 14, 12, 14, 15,\n 16, 17, 18, 16, 18, 19,\n 20, 21, 22, 20, 22, 23,\n]);\n\n/** Create box CPU data. `size` scales all positions (default 1). */\nexport function createBoxData(size = 1): BoxData {\n if (size === 1) {\n return {\n positions: BOX_POSITIONS,\n normals: BOX_NORMALS,\n uvs: BOX_UVS,\n indices: BOX_INDICES,\n vertexCount: 24,\n indexCount: 36,\n };\n }\n const positions = new Float32Array(BOX_POSITIONS.length);\n for (let i = 0; i < positions.length; i++) {\n positions[i] = BOX_POSITIONS[i]! * size;\n }\n return {\n positions,\n normals: BOX_NORMALS,\n uvs: BOX_UVS,\n indices: BOX_INDICES,\n vertexCount: 24,\n indexCount: 36,\n };\n}\n","/**\n * Torus mesh generator — matches Babylon.js Mesh.CreateTorus exactly.\n *\n * Babylon's parameterization:\n * R = diameter / 2 (major radius)\n * r = thickness / 2 (tube radius)\n * outerAngle = i * 2π / tess - π/2 (around ring, offset by -π/2)\n * innerAngle = j * 2π / tess + π (around tube, offset by π)\n *\n * Local position = (cos(inner)*r, sin(inner)*r, 0)\n * Then: Translate(R, 0, 0) * RotateY(outerAngle)\n *\n * Equivalent direct formulas:\n * x = (cos(inner)*r + R) * cos(outer)\n * y = sin(inner) * r\n * z = -(cos(inner)*r + R) * sin(outer)\n */\n\nexport interface TorusData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createTorusData`. Subset of Babylon's CreateTorus. */\nexport interface TorusOptions {\n diameter?: number;\n thickness?: number;\n tessellation?: number;\n}\n\nexport function createTorusData(opts: TorusOptions = {}): TorusData {\n const diameter = opts.diameter ?? 1;\n const thickness = opts.thickness ?? 0.5;\n const tessellation = opts.tessellation ?? 16;\n\n const R = diameter / 2;\n const r = thickness / 2;\n const stride = tessellation + 1;\n const vertexCount = stride * stride;\n // Babylon generates indices for ALL vertex pairs including wrapping seams\n const indexCount = stride * stride * 6;\n\n const positions = new Float32Array(vertexCount * 3);\n const normals = new Float32Array(vertexCount * 3);\n const uvs = new Float32Array(vertexCount * 2);\n const indices = new Uint32Array(indexCount);\n\n const TWO_PI = Math.PI * 2;\n\n let vi = 0;\n let ui = 0;\n let ii = 0;\n\n for (let i = 0; i <= tessellation; i++) {\n const outerAngle = (i * TWO_PI) / tessellation - Math.PI / 2;\n const cosOuter = Math.cos(outerAngle);\n const sinOuter = Math.sin(outerAngle);\n\n for (let j = 0; j <= tessellation; j++) {\n const innerAngle = (j * TWO_PI) / tessellation + Math.PI;\n const dx = Math.cos(innerAngle);\n const dy = Math.sin(innerAngle);\n\n // Position: Translation(R, 0, 0) then RotationY(outerAngle)\n const px = dx * r; // local position x\n const x = (px + R) * cosOuter;\n const y = dy * r;\n const z = -(px + R) * sinOuter;\n\n positions[vi] = x;\n positions[vi + 1] = y;\n positions[vi + 2] = z;\n\n // Normal: RotationY(outerAngle) applied to (dx, dy, 0)\n normals[vi] = dx * cosOuter;\n normals[vi + 1] = dy;\n normals[vi + 2] = -dx * sinOuter;\n\n vi += 3;\n\n // UV\n uvs[ui] = i / tessellation;\n uvs[ui + 1] = 1 - j / tessellation;\n ui += 2;\n\n // Indices (with wrapping via modulo)\n const nextI = (i + 1) % stride;\n const nextJ = (j + 1) % stride;\n\n indices[ii++] = i * stride + j;\n indices[ii++] = i * stride + nextJ;\n indices[ii++] = nextI * stride + j;\n indices[ii++] = i * stride + nextJ;\n indices[ii++] = nextI * stride + nextJ;\n indices[ii++] = nextI * stride + j;\n }\n }\n\n return { positions, normals, uvs, indices };\n}\n","/**\n * Ground from heightmap — matches Babylon.js MeshBuilder.CreateGroundFromHeightMap.\n *\n * Creates a subdivided plane, loads a heightmap image, displaces Y values\n * based on the heightmap luminance, and recomputes normals.\n *\n * Grid: (subdivisions + 1) × (subdivisions + 1) vertices\n * Position range: [-width/2, width/2] in X, [-height/2, height/2] in Z\n * UV: (0,1) at top-left, (1,0) at bottom-right (matching Babylon convention)\n */\n\nexport interface GroundData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createFlatGroundData` and {@link createGroundFromHeightMap}. */\nexport interface GroundOptions {\n width?: number;\n height?: number;\n subdivisions?: number;\n minHeight?: number;\n maxHeight?: number;\n /** UV scale factor [uScale, vScale]. Multiplies generated UVs for texture tiling. Default [1, 1]. */\n uvScale?: [number, number];\n}\n\n/**\n * Create a flat ground plane. Call applyHeightmap() after to displace.\n */\nexport function createFlatGroundData(opts: GroundOptions = {}): GroundData {\n const width = opts.width ?? 1;\n const height = opts.height ?? 1;\n const subdivisions = opts.subdivisions ?? 1;\n const cols = subdivisions + 1;\n const rows = cols;\n const vertexCount = cols * rows;\n const indexCount = subdivisions * subdivisions * 6;\n\n const positions = new Float32Array(vertexCount * 3);\n const normals = new Float32Array(vertexCount * 3);\n const uvs = new Float32Array(vertexCount * 2);\n const indices = new Uint32Array(indexCount);\n\n // Generate vertices\n let vi = 0;\n let ui = 0;\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const x = -width / 2 + (col / subdivisions) * width;\n const z = -height / 2 + (1 - row / subdivisions) * height;\n\n positions[vi] = x;\n positions[vi + 1] = 0; // Y = 0 initially\n positions[vi + 2] = z;\n\n normals[vi] = 0;\n normals[vi + 1] = 1;\n normals[vi + 2] = 0;\n\n vi += 3;\n\n // Babylon UV: col/subdivisions, 1 - row/subdivisions\n uvs[ui] = col / subdivisions;\n uvs[ui + 1] = 1 - row / subdivisions;\n ui += 2;\n }\n }\n\n // Apply UV scale for texture tiling\n const uScale = opts.uvScale?.[0] ?? 1;\n const vScale = opts.uvScale?.[1] ?? 1;\n if (uScale !== 1 || vScale !== 1) {\n for (let i = 0; i < uvs.length; i += 2) {\n uvs[i] = uvs[i]! * uScale;\n uvs[i + 1] = uvs[i + 1]! * vScale;\n }\n }\n\n // Generate indices — Babylon uses specific winding\n let ii = 0;\n for (let row = 0; row < subdivisions; row++) {\n for (let col = 0; col < subdivisions; col++) {\n const topLeft = row * cols + col;\n const topRight = topLeft + 1;\n const bottomLeft = (row + 1) * cols + col;\n const bottomRight = bottomLeft + 1;\n\n indices[ii++] = bottomRight;\n indices[ii++] = topRight;\n indices[ii++] = topLeft;\n\n indices[ii++] = bottomLeft;\n indices[ii++] = bottomRight;\n indices[ii++] = topLeft;\n }\n }\n\n return { positions, normals, uvs, indices };\n}\n\n/**\n * Apply heightmap displacement from image pixel data.\n * The heightmap image must already be loaded and drawn to a canvas\n * so we can read pixel data.\n */\nfunction applyHeightmap(ground: GroundData, heightmapData: Uint8ClampedArray, hmWidth: number, hmHeight: number, subdivisions: number, minHeight: number, maxHeight: number): void {\n const cols = subdivisions + 1;\n const rows = cols;\n const range = maxHeight - minHeight;\n\n // Displace Y based on heightmap luminance\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const idx = row * cols + col;\n // Sample heightmap at corresponding UV\n const u = col / subdivisions;\n const v = row / subdivisions; // row 0 = top of image\n // Babylon: floor(u * (bufferWidth - 1)), floor(v * (bufferHeight - 1))\n const px = (u * (hmWidth - 1)) | 0;\n const py = (v * (hmHeight - 1)) | 0;\n const pixIdx = (py * hmWidth + px) * 4;\n const r = heightmapData[pixIdx]! / 255;\n const g = heightmapData[pixIdx + 1]! / 255;\n const b = heightmapData[pixIdx + 2]! / 255;\n // Babylon uses weighted luminance: r * 0.3 + g * 0.59 + b * 0.11\n const gradient = r * 0.3 + g * 0.59 + b * 0.11;\n ground.positions[idx * 3 + 1] = minHeight + gradient * range;\n }\n }\n\n // Recompute normals from cross products\n // Reset normals to zero\n ground.normals.fill(0);\n\n for (let i = 0; i < ground.indices.length; i += 3) {\n const i0 = ground.indices[i]!;\n const i1 = ground.indices[i + 1]!;\n const i2 = ground.indices[i + 2]!;\n\n const pos = ground.positions;\n const p0x = pos[i0 * 3]!;\n const p0y = pos[i0 * 3 + 1]!;\n const p0z = pos[i0 * 3 + 2]!;\n const p1x = pos[i1 * 3]!;\n const p1y = pos[i1 * 3 + 1]!;\n const p1z = pos[i1 * 3 + 2]!;\n const p2x = pos[i2 * 3]!;\n const p2y = pos[i2 * 3 + 1]!;\n const p2z = pos[i2 * 3 + 2]!;\n\n // Edge vectors\n const e1x = p1x - p0x;\n const e1y = p1y - p0y;\n const e1z = p1z - p0z;\n const e2x = p2x - p0x;\n const e2y = p2y - p0y;\n const e2z = p2z - p0z;\n\n // Cross product (face normal) — negated to match Lite's CCW winding convention\n let fnx = -(e1y * e2z - e1z * e2y);\n let fny = -(e1z * e2x - e1x * e2z);\n let fnz = -(e1x * e2y - e1y * e2x);\n\n // Normalize face normal before accumulation (equal-weight per face,\n // matching Babylon's ComputeNormals which normalizes each face normal\n // before adding to vertices).\n const fnMag = Math.sqrt(fnx * fnx + fny * fny + fnz * fnz) || 1;\n fnx /= fnMag;\n fny /= fnMag;\n fnz /= fnMag;\n\n // Accumulate unit face normals\n const nrm = ground.normals;\n nrm[i0 * 3] = nrm[i0 * 3]! + fnx;\n nrm[i0 * 3 + 1] = nrm[i0 * 3 + 1]! + fny;\n nrm[i0 * 3 + 2] = nrm[i0 * 3 + 2]! + fnz;\n nrm[i1 * 3] = nrm[i1 * 3]! + fnx;\n nrm[i1 * 3 + 1] = nrm[i1 * 3 + 1]! + fny;\n nrm[i1 * 3 + 2] = nrm[i1 * 3 + 2]! + fnz;\n nrm[i2 * 3] = nrm[i2 * 3]! + fnx;\n nrm[i2 * 3 + 1] = nrm[i2 * 3 + 1]! + fny;\n nrm[i2 * 3 + 2] = nrm[i2 * 3 + 2]! + fnz;\n }\n\n // Normalize\n const vCount = ground.positions.length / 3;\n for (let i = 0; i < vCount; i++) {\n const nx = ground.normals[i * 3]!;\n const ny = ground.normals[i * 3 + 1]!;\n const nz = ground.normals[i * 3 + 2]!;\n const len = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;\n ground.normals[i * 3] = nx / len;\n ground.normals[i * 3 + 1] = ny / len;\n ground.normals[i * 3 + 2] = nz / len;\n }\n}\n\n/**\n * Load heightmap image and create ground mesh data.\n */\nexport async function createGroundFromHeightMap(heightmapUrl: string, opts: GroundOptions = {}): Promise<GroundData> {\n const subdivisions = opts.subdivisions ?? 1;\n const minHeight = opts.minHeight ?? 0;\n const maxHeight = opts.maxHeight ?? 1;\n\n const ground = createFlatGroundData(opts);\n\n // Load image and extract pixel data\n const img = new Image();\n img.crossOrigin = \"anonymous\";\n await new Promise<void>((resolve, reject) => {\n img.onload = () => resolve();\n img.onerror = (e) => reject(e instanceof Error ? e : new Error(String(e)));\n img.src = heightmapUrl;\n });\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = img.width;\n canvas.height = img.height;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.drawImage(img, 0, 0);\n const imageData = ctx.getImageData(0, 0, img.width, img.height);\n\n applyHeightmap(ground, imageData.data, img.width, img.height, subdivisions, minHeight, maxHeight);\n\n return ground;\n}\n","/**\n * CreateCylinder — matches Babylon.js MeshBuilder.CreateCylinder default options.\n *\n * Supports cylinders, cones (diameterTop=0), truncated cones, and prisms\n * (low tessellation). Options are a subset of Babylon's MeshBuilder that\n * covers the typical procedural use-case. Advanced options — `arc`,\n * `enclose`, `hasRings`, `faceColors`, `faceUV`, `cap != CAP_ALL` — are\n * intentionally omitted to keep the API small; the default behavior (full\n * 360°, single ring, CAP_ALL) matches Babylon exactly.\n *\n * Index order and normal computation are ported verbatim from\n * `@babylonjs/core/Meshes/Builders/cylinderBuilder.js` to guarantee parity.\n */\n\nexport interface CylinderData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createCylinderData`. Subset of Babylon's CreateCylinder. */\nexport interface CylinderOptions {\n height?: number;\n diameter?: number;\n diameterTop?: number;\n diameterBottom?: number;\n tessellation?: number;\n subdivisions?: number;\n}\n\nexport function createCylinderData(options: CylinderOptions = {}): CylinderData {\n const height = options.height ?? 2;\n let diameterTop = options.diameterTop === 0 ? 0 : (options.diameterTop ?? options.diameter ?? 1);\n let diameterBottom = options.diameterBottom === 0 ? 0 : (options.diameterBottom ?? options.diameter ?? 1);\n // Prevent broken normals on degenerate rings.\n if (diameterTop === 0) {\n diameterTop = 0.00001;\n }\n if (diameterBottom === 0) {\n diameterBottom = 0.00001;\n }\n const tessellation = Math.max(3, (options.tessellation ?? 24) | 0);\n const subdivisions = Math.max(1, (options.subdivisions ?? 1) | 0);\n const arc = 1; // full circle only (see header comment)\n\n const positions: number[] = [];\n const normals: number[] = [];\n const uvs: number[] = [];\n const indices: number[] = [];\n\n const angleStep = (Math.PI * 2 * arc) / tessellation;\n const tan = (diameterBottom - diameterTop) / 2 / height;\n\n // Side ring vertices\n for (let i = 0; i <= subdivisions; i++) {\n const h = i / subdivisions;\n const radius = (h * (diameterTop - diameterBottom) + diameterBottom) / 2;\n\n for (let j = 0; j <= tessellation; j++) {\n const angle = j * angleStep;\n const rvx = Math.cos(-angle) * radius;\n const rvy = -height / 2 + h * height;\n const rvz = Math.sin(-angle) * radius;\n\n let nx: number;\n let ny: number;\n let nz: number;\n if (options.diameterTop === 0 && i === subdivisions) {\n // Cone tip: reuse previous ring's normals (Babylon parity).\n const base = normals.length - (tessellation + 1) * 3;\n nx = normals[base]!;\n ny = normals[base + 1]!;\n nz = normals[base + 2]!;\n } else {\n nx = rvx;\n nz = rvz;\n ny = Math.sqrt(nx * nx + nz * nz) * tan;\n const invLen = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);\n nx *= invLen;\n ny *= invLen;\n nz *= invLen;\n }\n\n positions.push(rvx, rvy, rvz);\n normals.push(nx, ny, nz);\n // Default faceUV for side is (0,0,1,1): u=j/tessellation, v=h\n uvs.push(j / tessellation, h);\n }\n }\n\n // Side indices (e = tessellation since arc === 1 && !enclose)\n const e = tessellation;\n for (let s = 0; s < subdivisions; s++) {\n for (let j = 0; j < tessellation; j++) {\n const i0 = s * (e + 1) + j;\n const i1 = (s + 1) * (e + 1) + j;\n const i2 = s * (e + 1) + (j + 1);\n const i3 = (s + 1) * (e + 1) + (j + 1);\n indices.push(i0, i1, i2);\n indices.push(i3, i2, i1);\n }\n }\n\n // Caps (CAP_ALL)\n const createCap = (isTop: boolean): void => {\n const radius = isTop ? diameterTop / 2 : diameterBottom / 2;\n if (radius === 0) {\n return;\n }\n\n const vbase = positions.length / 3;\n const offset = isTop ? height / 2 : -height / 2;\n\n // Center vertex\n positions.push(0, offset, 0);\n normals.push(0, isTop ? 1 : -1, 0);\n uvs.push(0.5, 0.5);\n\n for (let i = 0; i <= tessellation; i++) {\n const angle = (Math.PI * 2 * i * arc) / tessellation;\n const cos = Math.cos(-angle);\n const sin = Math.sin(-angle);\n positions.push(cos * radius, offset, sin * radius);\n normals.push(0, isTop ? 1 : -1, 0);\n uvs.push(cos * 0.5 + 0.5, sin * 0.5 + 0.5);\n }\n\n for (let i = 0; i < tessellation; i++) {\n if (!isTop) {\n indices.push(vbase, vbase + (i + 1), vbase + (i + 2));\n } else {\n indices.push(vbase, vbase + (i + 2), vbase + (i + 1));\n }\n }\n };\n createCap(false);\n createCap(true);\n\n return {\n positions: new Float32Array(positions),\n normals: new Float32Array(normals),\n uvs: new Float32Array(uvs),\n indices: new Uint32Array(indices),\n };\n}\n","/**\n * CreatePlane — matches Babylon.js MeshBuilder.CreatePlane defaults.\n *\n * Unit quad in the XY plane with a -Z facing normal (Babylon convention).\n * 4 vertices, 2 triangles, UVs span [0,1].\n */\n\nexport interface PlaneData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createPlaneData`. Subset of Babylon's CreatePlane. */\nexport interface PlaneOptions {\n size?: number;\n width?: number;\n height?: number;\n}\n\nexport function createPlaneData(options: PlaneOptions = {}): PlaneData {\n const size = options.size ?? 1;\n const width = options.width ?? size;\n const height = options.height ?? size;\n const hw = width / 2;\n const hh = height / 2;\n\n // prettier-ignore\n const positions = new Float32Array([\n -hw, -hh, 0,\n hw, -hh, 0,\n hw, hh, 0,\n -hw, hh, 0,\n ]);\n // prettier-ignore\n const normals = new Float32Array([\n 0, 0, -1,\n 0, 0, -1,\n 0, 0, -1,\n 0, 0, -1,\n ]);\n // prettier-ignore\n const uvs = new Float32Array([\n 0, 0,\n 1, 0,\n 1, 1,\n 0, 1,\n ]);\n const indices = new Uint32Array([0, 1, 2, 0, 2, 3]);\n\n return { positions, normals, uvs, indices };\n}\n","/**\n * CreateDisc — matches Babylon.js MeshBuilder.CreateDisc defaults.\n *\n * A flat regular polygon / disc in the XY plane, centered at the origin,\n * facing -Z. With `arc < 1` the disc becomes a pie slice. Normals are\n * computed from the triangle winding (all +Z because winding is CW from -Z).\n *\n * Babylon's formula:\n * step = arc === 1 ? 2π/tess : 2π·arc/(tess - 1)\n * vertex 0 = (0, 0, 0) ← center\n * vertex t = (cos(a)·r, sin(a)·r, 0) for t = 0..tess-1\n * if arc === 1 → duplicate vertex 1 to close the circle\n * triangles fan from the center: (0, i, i+1)\n */\n\nexport interface DiscData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createDiscData`. Subset of Babylon's CreateDisc. */\nexport interface DiscOptions {\n radius?: number;\n tessellation?: number;\n /** Fraction of circumference (`0 < arc ≤ 1`). Default 1 (full disc). */\n arc?: number;\n}\n\nexport function createDiscData(options: DiscOptions = {}): DiscData {\n const radius = options.radius ?? 0.5;\n const tessellation = options.tessellation ?? 64;\n const arc = options.arc && (options.arc <= 0 || options.arc > 1) ? 1 : (options.arc ?? 1);\n\n const positions: number[] = [];\n const uvs: number[] = [];\n const indices: number[] = [];\n\n // Center\n positions.push(0, 0, 0);\n uvs.push(0.5, 0.5);\n\n const theta = Math.PI * 2 * arc;\n const step = arc === 1 ? theta / tessellation : theta / (tessellation - 1);\n\n let a = 0;\n for (let t = 0; t < tessellation; t++) {\n const x = Math.cos(a);\n const y = Math.sin(a);\n positions.push(radius * x, radius * y, 0);\n uvs.push((x + 1) / 2, (1 - y) / 2);\n a += step;\n }\n if (arc === 1) {\n positions.push(positions[3]!, positions[4]!, positions[5]!);\n uvs.push(uvs[2]!, uvs[3]!);\n }\n\n const vertexNb = positions.length / 3;\n for (let i = 1; i < vertexNb - 1; i++) {\n indices.push(i + 1, 0, i);\n }\n\n // Normals: Babylon's ComputeNormals on this triangle ordering yields -Z\n // for every vertex (see cross-product derivation in tests).\n const normals = new Float32Array(vertexNb * 3);\n for (let i = 0; i < vertexNb; i++) {\n normals[i * 3 + 2] = -1;\n }\n\n return {\n positions: new Float32Array(positions),\n normals,\n uvs: new Float32Array(uvs),\n indices: new Uint32Array(indices),\n };\n}\n","/** Babylon MeshBuilder polyhedron tables - 15 preset types, indices match\n * the type parameter in `createPolyhedronData({type})`.\n * Copied from `@babylonjs/core/Meshes/Builders/polyhedronBuilder.js`. */\n\nexport interface PolyhedronSpec {\n vertex: number[][];\n face: number[][];\n}\n\nexport const POLYHEDRA: PolyhedronSpec[] = [\n {\n vertex: [\n [0, 0, 1.732051],\n [1.632993, 0, -0.5773503],\n [-0.8164966, 1.414214, -0.5773503],\n [-0.8164966, -1.414214, -0.5773503],\n ],\n face: [\n [0, 1, 2],\n [0, 2, 3],\n [0, 3, 1],\n [1, 3, 2],\n ],\n },\n {\n vertex: [\n [0, 0, 1.414214],\n [1.414214, 0, 0],\n [0, 1.414214, 0],\n [-1.414214, 0, 0],\n [0, -1.414214, 0],\n [0, 0, -1.414214],\n ],\n face: [\n [0, 1, 2],\n [0, 2, 3],\n [0, 3, 4],\n [0, 4, 1],\n [1, 4, 5],\n [1, 5, 2],\n [2, 5, 3],\n [3, 5, 4],\n ],\n },\n {\n vertex: [\n [0, 0, 1.070466],\n [0.7136442, 0, 0.7978784],\n [-0.3568221, 0.618034, 0.7978784],\n [-0.3568221, -0.618034, 0.7978784],\n [0.7978784, 0.618034, 0.3568221],\n [0.7978784, -0.618034, 0.3568221],\n [-0.9341724, 0.381966, 0.3568221],\n [0.1362939, 1, 0.3568221],\n [0.1362939, -1, 0.3568221],\n [-0.9341724, -0.381966, 0.3568221],\n [0.9341724, 0.381966, -0.3568221],\n [0.9341724, -0.381966, -0.3568221],\n [-0.7978784, 0.618034, -0.3568221],\n [-0.1362939, 1, -0.3568221],\n [-0.1362939, -1, -0.3568221],\n [-0.7978784, -0.618034, -0.3568221],\n [0.3568221, 0.618034, -0.7978784],\n [0.3568221, -0.618034, -0.7978784],\n [-0.7136442, 0, -0.7978784],\n [0, 0, -1.070466],\n ],\n face: [\n [0, 1, 4, 7, 2],\n [0, 2, 6, 9, 3],\n [0, 3, 8, 5, 1],\n [1, 5, 11, 10, 4],\n [2, 7, 13, 12, 6],\n [3, 9, 15, 14, 8],\n [4, 10, 16, 13, 7],\n [5, 8, 14, 17, 11],\n [6, 12, 18, 15, 9],\n [10, 11, 17, 19, 16],\n [12, 13, 16, 19, 18],\n [14, 15, 18, 19, 17],\n ],\n },\n {\n vertex: [\n [0, 0, 1.175571],\n [1.051462, 0, 0.5257311],\n [0.3249197, 1, 0.5257311],\n [-0.8506508, 0.618034, 0.5257311],\n [-0.8506508, -0.618034, 0.5257311],\n [0.3249197, -1, 0.5257311],\n [0.8506508, 0.618034, -0.5257311],\n [0.8506508, -0.618034, -0.5257311],\n [-0.3249197, 1, -0.5257311],\n [-1.051462, 0, -0.5257311],\n [-0.3249197, -1, -0.5257311],\n [0, 0, -1.175571],\n ],\n face: [\n [0, 1, 2],\n [0, 2, 3],\n [0, 3, 4],\n [0, 4, 5],\n [0, 5, 1],\n [1, 5, 7],\n [1, 7, 6],\n [1, 6, 2],\n [2, 6, 8],\n [2, 8, 3],\n [3, 8, 9],\n [3, 9, 4],\n [4, 9, 10],\n [4, 10, 5],\n [5, 10, 7],\n [6, 7, 11],\n [6, 11, 8],\n [7, 10, 11],\n [8, 11, 9],\n [9, 11, 10],\n ],\n },\n {\n vertex: [\n [0, 0, 1.070722],\n [0.7148135, 0, 0.7971752],\n [-0.104682, 0.7071068, 0.7971752],\n [-0.6841528, 0.2071068, 0.7971752],\n [-0.104682, -0.7071068, 0.7971752],\n [0.6101315, 0.7071068, 0.5236279],\n [1.04156, 0.2071068, 0.1367736],\n [0.6101315, -0.7071068, 0.5236279],\n [-0.3574067, 1, 0.1367736],\n [-0.7888348, -0.5, 0.5236279],\n [-0.9368776, 0.5, 0.1367736],\n [-0.3574067, -1, 0.1367736],\n [0.3574067, 1, -0.1367736],\n [0.9368776, -0.5, -0.1367736],\n [0.7888348, 0.5, -0.5236279],\n [0.3574067, -1, -0.1367736],\n [-0.6101315, 0.7071068, -0.5236279],\n [-1.04156, -0.2071068, -0.1367736],\n [-0.6101315, -0.7071068, -0.5236279],\n [0.104682, 0.7071068, -0.7971752],\n [0.6841528, -0.2071068, -0.7971752],\n [0.104682, -0.7071068, -0.7971752],\n [-0.7148135, 0, -0.7971752],\n [0, 0, -1.070722],\n ],\n face: [\n [0, 2, 3],\n [1, 6, 5],\n [4, 9, 11],\n [7, 15, 13],\n [8, 16, 10],\n [12, 14, 19],\n [17, 22, 18],\n [20, 21, 23],\n [0, 1, 5, 2],\n [0, 3, 9, 4],\n [0, 4, 7, 1],\n [1, 7, 13, 6],\n [2, 5, 12, 8],\n [2, 8, 10, 3],\n [3, 10, 17, 9],\n [4, 11, 15, 7],\n [5, 6, 14, 12],\n [6, 13, 20, 14],\n [8, 12, 19, 16],\n [9, 17, 18, 11],\n [10, 16, 22, 17],\n [11, 18, 21, 15],\n [13, 15, 21, 20],\n [14, 20, 23, 19],\n [16, 19, 23, 22],\n [18, 22, 23, 21],\n ],\n },\n {\n vertex: [\n [0, 0, 1.322876],\n [1.309307, 0, 0.1889822],\n [-0.9819805, 0.8660254, 0.1889822],\n [0.1636634, -1.299038, 0.1889822],\n [0.3273268, 0.8660254, -0.9449112],\n [-0.8183171, -0.4330127, -0.9449112],\n ],\n face: [\n [0, 3, 1],\n [2, 4, 5],\n [0, 1, 4, 2],\n [0, 2, 5, 3],\n [1, 3, 5, 4],\n ],\n },\n {\n vertex: [\n [0, 0, 1.159953],\n [1.013464, 0, 0.5642542],\n [-0.3501431, 0.9510565, 0.5642542],\n [-0.7715208, -0.6571639, 0.5642542],\n [0.6633206, 0.9510565, -0.03144481],\n [0.8682979, -0.6571639, -0.3996071],\n [-1.121664, 0.2938926, -0.03144481],\n [-0.2348831, -1.063314, -0.3996071],\n [0.5181548, 0.2938926, -0.9953061],\n [-0.5850262, -0.112257, -0.9953061],\n ],\n face: [\n [0, 1, 4, 2],\n [0, 2, 6, 3],\n [1, 5, 8, 4],\n [3, 6, 9, 7],\n [5, 7, 9, 8],\n [0, 3, 7, 5, 1],\n [2, 4, 8, 9, 6],\n ],\n },\n {\n vertex: [\n [0, 0, 1.118034],\n [0.8944272, 0, 0.6708204],\n [-0.2236068, 0.8660254, 0.6708204],\n [-0.7826238, -0.4330127, 0.6708204],\n [0.6708204, 0.8660254, 0.2236068],\n [1.006231, -0.4330127, -0.2236068],\n [-1.006231, 0.4330127, 0.2236068],\n [-0.6708204, -0.8660254, -0.2236068],\n [0.7826238, 0.4330127, -0.6708204],\n [0.2236068, -0.8660254, -0.6708204],\n [-0.8944272, 0, -0.6708204],\n [0, 0, -1.118034],\n ],\n face: [\n [0, 1, 4, 2],\n [0, 2, 6, 3],\n [1, 5, 8, 4],\n [3, 6, 10, 7],\n [5, 9, 11, 8],\n [7, 10, 11, 9],\n [0, 3, 7, 9, 5, 1],\n [2, 4, 8, 11, 10, 6],\n ],\n },\n {\n vertex: [\n [-0.729665, 0.670121, 0.319155],\n [-0.655235, -0.29213, -0.754096],\n [-0.093922, -0.607123, 0.537818],\n [0.702196, 0.595691, 0.485187],\n [0.776626, -0.36656, -0.588064],\n ],\n face: [\n [1, 4, 2],\n [0, 1, 2],\n [3, 0, 2],\n [4, 3, 2],\n [4, 1, 0, 3],\n ],\n },\n {\n vertex: [\n [-0.868849, -0.100041, 0.61257],\n [-0.329458, 0.976099, 0.28078],\n [-0.26629, -0.013796, -0.477654],\n [-0.13392, -1.034115, 0.229829],\n [0.738834, 0.707117, -0.307018],\n [0.859683, -0.535264, -0.338508],\n ],\n face: [\n [3, 0, 2],\n [5, 3, 2],\n [4, 5, 2],\n [1, 4, 2],\n [0, 1, 2],\n [0, 3, 5, 4, 1],\n ],\n },\n {\n vertex: [\n [-0.610389, 0.243975, 0.531213],\n [-0.187812, -0.48795, -0.664016],\n [-0.187812, 0.9759, -0.664016],\n [0.187812, -0.9759, 0.664016],\n [0.798201, 0.243975, 0.132803],\n ],\n face: [\n [1, 3, 0],\n [3, 4, 0],\n [3, 1, 4],\n [0, 2, 1],\n [0, 4, 2],\n [2, 4, 1],\n ],\n },\n {\n vertex: [\n [-1.028778, 0.392027, -0.048786],\n [-0.640503, -0.646161, 0.621837],\n [-0.125162, -0.395663, -0.540059],\n [0.004683, 0.888447, -0.651988],\n [0.125161, 0.395663, 0.540059],\n [0.632925, -0.791376, 0.433102],\n [1.031672, 0.157063, -0.354165],\n ],\n face: [\n [3, 2, 0],\n [2, 1, 0],\n [2, 5, 1],\n [0, 4, 3],\n [0, 1, 4],\n [4, 1, 5],\n [2, 3, 6],\n [3, 4, 6],\n [5, 2, 6],\n [4, 5, 6],\n ],\n },\n {\n vertex: [\n [-0.669867, 0.334933, -0.529576],\n [-0.669867, 0.334933, 0.529577],\n [-0.4043, 1.212901, 0],\n [-0.334933, -0.669867, -0.529576],\n [-0.334933, -0.669867, 0.529577],\n [0.334933, 0.669867, -0.529576],\n [0.334933, 0.669867, 0.529577],\n [0.4043, -1.212901, 0],\n [0.669867, -0.334933, -0.529576],\n [0.669867, -0.334933, 0.529577],\n ],\n face: [\n [8, 9, 7],\n [6, 5, 2],\n [3, 8, 7],\n [5, 0, 2],\n [4, 3, 7],\n [0, 1, 2],\n [9, 4, 7],\n [1, 6, 2],\n [9, 8, 5, 6],\n [8, 3, 0, 5],\n [3, 4, 1, 0],\n [4, 9, 6, 1],\n ],\n },\n {\n vertex: [\n [-0.931836, 0.219976, -0.264632],\n [-0.636706, 0.318353, 0.692816],\n [-0.613483, -0.735083, -0.264632],\n [-0.326545, 0.979634, 0],\n [-0.318353, -0.636706, 0.692816],\n [-0.159176, 0.477529, -0.856368],\n [0.159176, -0.477529, -0.856368],\n [0.318353, 0.636706, 0.692816],\n [0.326545, -0.979634, 0],\n [0.613482, 0.735082, -0.264632],\n [0.636706, -0.318353, 0.692816],\n [0.931835, -0.219977, -0.264632],\n ],\n face: [\n [11, 10, 8],\n [7, 9, 3],\n [6, 11, 8],\n [9, 5, 3],\n [2, 6, 8],\n [5, 0, 3],\n [4, 2, 8],\n [0, 1, 3],\n [10, 4, 8],\n [1, 7, 3],\n [10, 11, 9, 7],\n [11, 6, 5, 9],\n [6, 2, 0, 5],\n [2, 4, 1, 0],\n [4, 10, 7, 1],\n ],\n },\n {\n vertex: [\n [-0.93465, 0.300459, -0.271185],\n [-0.838689, -0.260219, -0.516017],\n [-0.711319, 0.717591, 0.128359],\n [-0.710334, -0.156922, 0.080946],\n [-0.599799, 0.556003, -0.725148],\n [-0.503838, -0.004675, -0.969981],\n [-0.487004, 0.26021, 0.48049],\n [-0.460089, -0.750282, -0.512622],\n [-0.376468, 0.973135, -0.325605],\n [-0.331735, -0.646985, 0.084342],\n [-0.254001, 0.831847, 0.530001],\n [-0.125239, -0.494738, -0.966586],\n [0.029622, 0.027949, 0.730817],\n [0.056536, -0.982543, -0.262295],\n [0.08085, 1.087391, 0.076037],\n [0.125583, -0.532729, 0.485984],\n [0.262625, 0.599586, 0.780328],\n [0.391387, -0.726999, -0.716259],\n [0.513854, -0.868287, 0.139347],\n [0.597475, 0.85513, 0.326364],\n [0.641224, 0.109523, 0.783723],\n [0.737185, -0.451155, 0.538891],\n [0.848705, -0.612742, -0.314616],\n [0.976075, 0.365067, 0.32976],\n [1.072036, -0.19561, 0.084927],\n ],\n face: [\n [15, 18, 21],\n [12, 20, 16],\n [6, 10, 2],\n [3, 0, 1],\n [9, 7, 13],\n [2, 8, 4, 0],\n [0, 4, 5, 1],\n [1, 5, 11, 7],\n [7, 11, 17, 13],\n [13, 17, 22, 18],\n [18, 22, 24, 21],\n [21, 24, 23, 20],\n [20, 23, 19, 16],\n [16, 19, 14, 10],\n [10, 14, 8, 2],\n [15, 9, 13, 18],\n [12, 15, 21, 20],\n [6, 12, 16, 10],\n [3, 6, 2, 0],\n [9, 3, 1, 7],\n [9, 15, 12, 6, 3],\n [22, 17, 11, 5, 4, 8, 14, 19, 23, 24],\n ],\n },\n];\n","/**\n * ComputeNormals — equivalent to Babylon.js VertexData.ComputeNormals for the\n * default left-handed case. Accumulates face normals per-vertex, normalizes.\n *\n * Operates on plain number arrays so callers can collect variable-length\n * geometry and typed-array convert at the end.\n */\nexport function computeNormals(positions: number[], indices: number[]): number[] {\n const n = positions.length;\n const pos = new Float64Array(n);\n for (let i = 0; i < n; i++) {\n pos[i] = positions[i]!;\n }\n const idx = new Uint32Array(indices.length);\n for (let i = 0; i < indices.length; i++) {\n idx[i] = indices[i]!;\n }\n const normals = new Float64Array(n);\n const nbFaces = (indices.length / 3) | 0;\n for (let f = 0; f < nbFaces; f++) {\n const v1x = idx[f * 3]! * 3;\n const v2x = idx[f * 3 + 1]! * 3;\n const v3x = idx[f * 3 + 2]! * 3;\n\n const p1p2x = pos[v1x]! - pos[v2x]!;\n const p1p2y = pos[v1x + 1]! - pos[v2x + 1]!;\n const p1p2z = pos[v1x + 2]! - pos[v2x + 2]!;\n const p3p2x = pos[v3x]! - pos[v2x]!;\n const p3p2y = pos[v3x + 1]! - pos[v2x + 1]!;\n const p3p2z = pos[v3x + 2]! - pos[v2x + 2]!;\n\n let nx = p1p2y * p3p2z - p1p2z * p3p2y;\n let ny = p1p2z * p3p2x - p1p2x * p3p2z;\n let nz = p1p2x * p3p2y - p1p2y * p3p2x;\n let len = Math.sqrt(nx * nx + ny * ny + nz * nz);\n if (len === 0) {\n len = 1;\n }\n nx /= len;\n ny /= len;\n nz /= len;\n\n normals[v1x] = normals[v1x]! + nx;\n normals[v1x + 1] = normals[v1x + 1]! + ny;\n normals[v1x + 2] = normals[v1x + 2]! + nz;\n normals[v2x] = normals[v2x]! + nx;\n normals[v2x + 1] = normals[v2x + 1]! + ny;\n normals[v2x + 2] = normals[v2x + 2]! + nz;\n normals[v3x] = normals[v3x]! + nx;\n normals[v3x + 1] = normals[v3x + 1]! + ny;\n normals[v3x + 2] = normals[v3x + 2]! + nz;\n }\n const nVerts = (n / 3) | 0;\n const out = new Array<number>(n);\n for (let i = 0; i < nVerts; i++) {\n const x = normals[i * 3]!;\n const y = normals[i * 3 + 1]!;\n const z = normals[i * 3 + 2]!;\n let len = Math.sqrt(x * x + y * y + z * z);\n if (len === 0) {\n len = 1;\n }\n out[i * 3] = x / len;\n out[i * 3 + 1] = y / len;\n out[i * 3 + 2] = z / len;\n }\n return out;\n}\n","/**\n * CreatePolyhedron — matches Babylon.js MeshBuilder.CreatePolyhedron defaults.\n *\n * The 15 preset polyhedra are stored in `polyhedron-data.ts` (tables copied\n * verbatim from BJS). Two rendering modes:\n * flat=true (default) — each face is duplicated per-vertex with a uniform\n * UV layout; faces appear as distinct polygons.\n * flat=false — shared vertex positions, smoothed normals, empty UVs.\n *\n * Options omitted vs. BJS: `custom`, `faceUV`, `faceColors`, `sideOrientation`,\n * `frontUVs`, `backUVs`. Defaults match exactly.\n */\n\nimport { POLYHEDRA } from \"./polyhedron-data.js\";\nimport { computeNormals } from \"./compute-normals.js\";\n\nexport interface PolyhedronData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createPolyhedronData`. Subset of Babylon's CreatePolyhedron. */\nexport interface PolyhedronOptions {\n /** Preset index 0-14. 0=Tetrahedron, 1=Octahedron, 2=Dodecahedron,\n * 3=Icosahedron, 4=Rhombicuboctahedron, 5=TriangularPrism, 6=PentagonalPrism,\n * 7=HexagonalPrism, 8=SquarePyramid(J1), 9=PentagonalPyramid(J2),\n * 10=TriangularDipyramid(J12), 11=PentagonalDipyramid(J13),\n * 12=ElongatedSquareDipyramid(J15), 13=ElongatedPentagonalDipyramid(J16),\n * 14=ElongatedPentagonalCupola(J20). Default 0. */\n type?: number;\n size?: number;\n sizeX?: number;\n sizeY?: number;\n sizeZ?: number;\n flat?: boolean;\n}\n\nexport function createPolyhedronData(options: PolyhedronOptions = {}): PolyhedronData {\n const type = options.type !== undefined && (options.type < 0 || options.type >= POLYHEDRA.length) ? 0 : (options.type ?? 0);\n const size = options.size;\n const sizeX = options.sizeX ?? size ?? 1;\n const sizeY = options.sizeY ?? size ?? 1;\n const sizeZ = options.sizeZ ?? size ?? 1;\n const flat = options.flat ?? true;\n const data = POLYHEDRA[type]!;\n const nbfaces = data.face.length;\n\n const positions: number[] = [];\n const uvs: number[] = [];\n const indices: number[] = [];\n\n if (!flat) {\n for (let i = 0; i < data.vertex.length; i++) {\n const v = data.vertex[i]!;\n positions.push(v[0]! * sizeX, v[1]! * sizeY, v[2]! * sizeZ);\n uvs.push(0, 0);\n }\n for (let f = 0; f < nbfaces; f++) {\n const face = data.face[f]!;\n for (let i = 0; i < face.length - 2; i++) {\n indices.push(face[0]!, face[i + 2]!, face[i + 1]!);\n }\n }\n } else {\n let index = 0;\n let faceIdx = 0;\n const indexes: number[] = [];\n for (let f = 0; f < nbfaces; f++) {\n const face = data.face[f]!;\n const fl = face.length;\n const ang = (2 * Math.PI) / fl;\n let x = 0.5 * Math.tan(ang / 2);\n let y = 0.5;\n for (let i = 0; i < fl; i++) {\n const v = data.vertex[face[i]!]!;\n positions.push(v[0]! * sizeX, v[1]! * sizeY, v[2]! * sizeZ);\n indexes.push(index);\n index++;\n // Default faceUV (0,0,1,1)\n uvs.push(0.5 + x, y - 0.5 + 0.5);\n const tmp = x * Math.cos(ang) - y * Math.sin(ang);\n y = x * Math.sin(ang) + y * Math.cos(ang);\n x = tmp;\n }\n for (let i = 0; i < fl - 2; i++) {\n indices.push(indexes[0 + faceIdx]!, indexes[i + 2 + faceIdx]!, indexes[i + 1 + faceIdx]!);\n }\n faceIdx += fl;\n }\n }\n\n const normals = computeNormals(positions, indices);\n\n return {\n positions: new Float32Array(positions),\n normals: new Float32Array(normals),\n uvs: new Float32Array(uvs),\n indices: new Uint32Array(indices),\n };\n}\n","/**\n * CreateRibbon — matches Babylon.js MeshBuilder.CreateRibbon defaults.\n *\n * A ribbon joins a set of parallel paths (arrays of Vec3) into a strip of\n * triangles. Used directly and also as the primitive underlying `createTube`\n * and `createExtrudeShape`.\n *\n * Options omitted vs. BJS: `sideOrientation`, `frontUVs/backUVs`, `invertUV`,\n * `uvs`, `colors`, `instance`. Index ordering, UV normalization by cumulative\n * distance, and `closePath`/`closeArray` normal averaging are ported verbatim\n * from `@babylonjs/core/Meshes/Builders/ribbonBuilder.js`.\n */\n\nimport type { Vec3 } from \"../math/types.js\";\nimport { computeNormals } from \"./compute-normals.js\";\n\nexport interface RibbonData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n indices: Uint32Array;\n}\n\n/** Options for `createRibbonData`: a set of parallel paths joined into a strip. */\nexport interface RibbonOptions {\n pathArray: Vec3[][];\n closeArray?: boolean;\n closePath?: boolean;\n offset?: number;\n}\n\nfunction len(v: Vec3): number {\n return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n}\nfunction sub(a: Vec3, b: Vec3): Vec3 {\n return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };\n}\n\nexport function createRibbonData(options: RibbonOptions): RibbonData {\n let pathArray = options.pathArray;\n const closeArray = options.closeArray || false;\n const closePath = options.closePath || false;\n const defaultOffset = Math.floor(pathArray[0]!.length / 2);\n let offset = options.offset ?? defaultOffset;\n offset = offset > defaultOffset ? defaultOffset : Math.floor(offset);\n\n // Single path → split into two via offset.\n if (pathArray.length < 2) {\n const ar1: Vec3[] = [];\n const ar2: Vec3[] = [];\n const src = pathArray[0]!;\n for (let i = 0; i < src.length - offset; i++) {\n ar1.push(src[i]!);\n ar2.push(src[i + offset]!);\n }\n pathArray = [ar1, ar2];\n }\n\n const positions: number[] = [];\n const indices: number[] = [];\n const uvs: number[] = [];\n const us: number[][] = [];\n const vs: number[][] = [];\n const uTotalDistance: number[] = [];\n const vTotalDistance: number[] = [];\n const lg: number[] = [];\n const idx: number[] = [];\n\n const closePathCorr = closePath ? 1 : 0;\n const closeArrayCorr = closeArray ? 1 : 0;\n\n let minlg = pathArray[0]!.length;\n let idc = 0;\n for (let p = 0; p < pathArray.length + closeArrayCorr; p++) {\n uTotalDistance[p] = 0;\n us[p] = [0];\n const path = (p === pathArray.length ? pathArray[0] : pathArray[p])!;\n const l = path.length;\n minlg = minlg < l ? minlg : l;\n let j = 0;\n while (j < l) {\n const pt = path[j]!;\n positions.push(pt.x, pt.y, pt.z);\n if (j > 0) {\n const vectlg = len(sub(path[j]!, path[j - 1]!));\n const dist = vectlg + uTotalDistance[p]!;\n us[p]!.push(dist);\n uTotalDistance[p] = dist;\n }\n j++;\n }\n if (closePath) {\n j--;\n positions.push(path[0]!.x, path[0]!.y, path[0]!.z);\n const vectlg = len(sub(path[j]!, path[0]!));\n const dist = vectlg + uTotalDistance[p]!;\n us[p]!.push(dist);\n uTotalDistance[p] = dist;\n }\n lg[p] = l + closePathCorr;\n idx[p] = idc;\n idc += l + closePathCorr;\n }\n\n for (let i = 0; i < minlg + closePathCorr; i++) {\n vTotalDistance[i] = 0;\n vs[i] = [0];\n for (let p = 0; p < pathArray.length - 1 + closeArrayCorr; p++) {\n const path1 = pathArray[p]!;\n const path2 = (p === pathArray.length - 1 ? pathArray[0] : pathArray[p + 1])!;\n let v1: Vec3;\n let v2: Vec3;\n if (i === minlg) {\n v1 = path1[0]!;\n v2 = path2[0]!;\n } else {\n v1 = path1[i]!;\n v2 = path2[i]!;\n }\n const vectlg = len(sub(v2, v1));\n const dist = vectlg + vTotalDistance[i]!;\n vs[i]!.push(dist);\n vTotalDistance[i] = dist;\n }\n }\n\n for (let p = 0; p < pathArray.length + closeArrayCorr; p++) {\n for (let i = 0; i < minlg + closePathCorr; i++) {\n const u = uTotalDistance[p]! !== 0 ? us[p]![i]! / uTotalDistance[p]! : 0;\n const v = vTotalDistance[i]! !== 0 ? vs[i]![p]! / vTotalDistance[i]! : 0;\n uvs.push(u, v);\n }\n }\n\n // Indices (Babylon's ribbon triangulation).\n let p = 0;\n let pi = 0;\n let l1 = lg[p]! - 1;\n let l2 = lg[p + 1]! - 1;\n let min = l1 < l2 ? l1 : l2;\n let shft = idx[1]! - idx[0]!;\n const path1nb = lg.length - 1;\n while (pi <= min && p < path1nb) {\n indices.push(pi, pi + shft, pi + 1);\n indices.push(pi + shft + 1, pi + 1, pi + shft);\n pi += 1;\n if (pi === min) {\n p++;\n shft = idx[p + 1]! - idx[p]!;\n l1 = lg[p]! - 1;\n l2 = lg[p + 1]! - 1;\n pi = idx[p]!;\n min = l1 < l2 ? l1 + pi : l2 + pi;\n }\n }\n\n const normals = computeNormals(positions, indices);\n\n if (closePath) {\n // Average the seam normals between the first and last vertex of each path.\n for (let p = 0; p < pathArray.length; p++) {\n const indexFirst = idx[p]! * 3;\n const indexLast = p + 1 < pathArray.length ? (idx[p + 1]! - 1) * 3 : normals.length - 3;\n normals[indexFirst] = (normals[indexFirst]! + normals[indexLast]!) * 0.5;\n normals[indexFirst + 1] = (normals[indexFirst + 1]! + normals[indexLast + 1]!) * 0.5;\n normals[indexFirst + 2] = (normals[indexFirst + 2]! + normals[indexLast + 2]!) * 0.5;\n const nl =\n Math.sqrt(\n normals[indexFirst]! * normals[indexFirst]! + normals[indexFirst + 1]! * normals[indexFirst + 1]! + normals[indexFirst + 2]! * normals[indexFirst + 2]!\n ) || 1;\n normals[indexFirst] = normals[indexFirst]! / nl;\n normals[indexFirst + 1] = normals[indexFirst + 1]! / nl;\n normals[indexFirst + 2] = normals[indexFirst + 2]! / nl;\n normals[indexLast] = normals[indexFirst]!;\n normals[indexLast + 1] = normals[indexFirst + 1]!;\n normals[indexLast + 2] = normals[indexFirst + 2]!;\n }\n }\n if (closeArray) {\n let indexFirst = idx[0]! * 3;\n let indexLast = idx[pathArray.length]! * 3;\n for (let i = 0; i < minlg + closePathCorr; i++) {\n normals[indexFirst] = (normals[indexFirst]! + normals[indexLast]!) * 0.5;\n normals[indexFirst + 1] = (normals[indexFirst + 1]! + normals[indexLast + 1]!) * 0.5;\n normals[indexFirst + 2] = (normals[indexFirst + 2]! + normals[indexLast + 2]!) * 0.5;\n const nl =\n Math.sqrt(\n normals[indexFirst]! * normals[indexFirst]! + normals[indexFirst + 1]! * normals[indexFirst + 1]! + normals[indexFirst + 2]! * normals[indexFirst + 2]!\n ) || 1;\n normals[indexFirst] = normals[indexFirst]! / nl;\n normals[indexFirst + 1] = normals[indexFirst + 1]! / nl;\n normals[indexFirst + 2] = normals[indexFirst + 2]! / nl;\n normals[indexLast] = normals[indexFirst]!;\n normals[indexLast + 1] = normals[indexFirst + 1]!;\n normals[indexLast + 2] = normals[indexFirst + 2]!;\n indexFirst += 3;\n indexLast += 3;\n }\n }\n\n return {\n positions: new Float32Array(positions),\n normals: new Float32Array(normals),\n uvs: new Float32Array(uvs),\n indices: new Uint32Array(indices),\n };\n}\n","import type { Vec3 } from \"./types.js\";\n\nexport function crossVec3(a: Vec3, b: Vec3): Vec3 {\n return {\n x: a.y * b.z - a.z * b.y,\n y: a.z * b.x - a.x * b.z,\n z: a.x * b.y - a.y * b.x,\n };\n}\n","import type { Vec3 } from \"./types.js\";\n\nexport function lengthVec3(v: Vec3): number {\n return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);\n}\n","import type { Vec3 } from \"./types.js\";\nimport { lengthVec3 } from \"./length-vec3.js\";\n\nexport function normalizeVec3(v: Vec3): Vec3 {\n const len = lengthVec3(v);\n if (len < 1e-10) {\n return { x: 0, y: 0, z: 0 };\n }\n const inv = 1 / len;\n return { x: v.x * inv, y: v.y * inv, z: v.z * inv };\n}\n","import type { Vec3 } from \"./types.js\";\n\nexport function subVec3(a: Vec3, b: Vec3): Vec3 {\n return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };\n}\n","/**\n * Minimal Path3D — ports just the tangent / normal / binormal / distance\n * computation from `@babylonjs/core/Maths/math.path.ts::Path3D`. Used by\n * `createTube` and `createExtrudeShape`. Always normalized (non-raw).\n *\n * Algorithm: http://www.cs.cmu.edu/afs/andrew/scs/cs/15-462/web/old/asst2camera.html\n */\n\nimport type { Vec3 } from \"../math/types.js\";\nimport { crossVec3 } from \"../math/cross-vec3.js\";\nimport { lengthVec3 } from \"../math/length-vec3.js\";\nimport { normalizeVec3 } from \"../math/normalize-vec3-object.js\";\nimport { subVec3 } from \"../math/sub-vec3.js\";\nimport { vec3 } from \"../math/vec3-ctor.js\";\n\nconst EPSILON = 0.001;\n\nfunction withinEpsilon(a: number, b: number, eps: number): boolean {\n return Math.abs(a - b) <= eps;\n}\n\nfunction getFirstNonNullVector(curve: Vec3[], index: number): Vec3 {\n let i = 1;\n let v = subVec3(curve[index + i]!, curve[index]!);\n while (lengthVec3(v) === 0 && index + i + 1 < curve.length) {\n i++;\n v = subVec3(curve[index + i]!, curve[index]!);\n }\n return v;\n}\n\nfunction getLastNonNullVector(curve: Vec3[], index: number): Vec3 {\n let i = 1;\n let v = subVec3(curve[index]!, curve[index - i]!);\n while (lengthVec3(v) === 0 && index > i + 1) {\n i++;\n v = subVec3(curve[index]!, curve[index - i]!);\n }\n return v;\n}\n\nfunction normalVector(vt: Vec3, va: Vec3 | null): Vec3 {\n let n: Vec3;\n let tgl = lengthVec3(vt);\n if (tgl === 0) {\n tgl = 1;\n }\n if (va === null) {\n let point: Vec3;\n if (!withinEpsilon(Math.abs(vt.y) / tgl, 1, EPSILON)) {\n point = vec3(0, -1, 0);\n } else if (!withinEpsilon(Math.abs(vt.x) / tgl, 1, EPSILON)) {\n point = vec3(1, 0, 0);\n } else if (!withinEpsilon(Math.abs(vt.z) / tgl, 1, EPSILON)) {\n point = vec3(0, 0, 1);\n } else {\n point = vec3(0, 0, 0);\n }\n n = crossVec3(vt, point);\n } else {\n const c = crossVec3(vt, va);\n n = crossVec3(c, vt);\n }\n return normalizeVec3(n);\n}\n\nexport interface Path3D {\n tangents: Vec3[];\n normals: Vec3[];\n binormals: Vec3[];\n distances: number[];\n}\n\nexport function computePath3D(curve: Vec3[], firstNormal: Vec3 | null = null): Path3D {\n const l = curve.length;\n const tangents: Vec3[] = new Array(l);\n const normals: Vec3[] = new Array(l);\n const binormals: Vec3[] = new Array(l);\n const distances: number[] = new Array(l);\n\n if (l < 2) {\n return { tangents, normals, binormals, distances };\n }\n\n tangents[0] = normalizeVec3(getFirstNonNullVector(curve, 0));\n tangents[l - 1] = normalizeVec3(subVec3(curve[l - 1]!, curve[l - 2]!));\n\n const pp0 = normalizeVec3(normalVector(tangents[0]!, firstNormal));\n normals[0] = pp0;\n binormals[0] = normalizeVec3(crossVec3(tangents[0]!, normals[0]!));\n distances[0] = 0;\n\n for (let i = 1; i < l; i++) {\n const prev = getLastNonNullVector(curve, i);\n if (i < l - 1) {\n const cur = getFirstNonNullVector(curve, i);\n const sum = { x: prev.x + cur.x, y: prev.y + cur.y, z: prev.z + cur.z };\n tangents[i] = normalizeVec3(sum);\n }\n distances[i] = distances[i - 1]! + lengthVec3(subVec3(curve[i]!, curve[i - 1]!));\n\n const curTang = tangents[i]!;\n const prevBinor = binormals[i - 1]!;\n let n = crossVec3(prevBinor, curTang);\n if (lengthVec3(n) === 0) {\n const prevN = normals[i - 1]!;\n n = { x: prevN.x, y: prevN.y, z: prevN.z };\n } else {\n n = normalizeVec3(n);\n }\n normals[i] = n;\n binormals[i] = normalizeVec3(crossVec3(curTang, n));\n }\n\n return { tangents, normals, binormals, distances };\n}\n","/**\n * CreateTube — matches Babylon.js MeshBuilder.CreateTube defaults.\n *\n * Generates a tube (cylinder following an arbitrary path) by building a\n * closed ribbon whose paths are circles placed at each curve point, oriented\n * by the Frenet frame computed by `computePath3D`.\n *\n * Options omitted vs. BJS: `updatable`, `sideOrientation`, `frontUVs/backUVs`,\n * `invertUV`, `instance`. Defaults match: radius 1, tessellation 64,\n * cap NO_CAP, arc 1.\n */\n\nimport type { Vec3 } from \"../math/types.js\";\nimport { computePath3D } from \"./path3d.js\";\nimport { createRibbonData, type RibbonData } from \"./create-ribbon.js\";\n\n/** Cap mode: no caps on either end of the tube/extrusion. */\nexport const CAP_NONE = 0;\n/** Cap mode: close only the start of the tube/extrusion. */\nexport const CAP_START = 1;\n/** Cap mode: close only the end of the tube/extrusion. */\nexport const CAP_END = 2;\n/** Cap mode: close both ends of the tube/extrusion. */\nexport const CAP_ALL = 3;\n\n/** Options for `createTubeData`: a circular cross-section swept along a path. */\nexport interface TubeOptions {\n path: Vec3[];\n radius?: number;\n tessellation?: number;\n /** Per-point radius override; receives the point index and its distance along the path. */\n radiusFunction?: (i: number, distance: number) => number;\n cap?: number;\n arc?: number;\n}\n\nfunction rodrigues(v: Vec3, k: Vec3, angle: number): Vec3 {\n // v is a unit/scaled vector, k is a unit axis.\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const dot = k.x * v.x + k.y * v.y + k.z * v.z;\n const crossX = k.y * v.z - k.z * v.y;\n const crossY = k.z * v.x - k.x * v.z;\n const crossZ = k.x * v.y - k.y * v.x;\n return {\n x: v.x * c + crossX * s + k.x * dot * (1 - c),\n y: v.y * c + crossY * s + k.y * dot * (1 - c),\n z: v.z * c + crossZ * s + k.z * dot * (1 - c),\n };\n}\n\nexport function createTubeData(options: TubeOptions): RibbonData {\n const path = options.path;\n const radius = options.radius ?? 1;\n const tessellation = (options.tessellation ?? 64) | 0;\n const radiusFunction = options.radiusFunction ?? null;\n let cap = options.cap ?? CAP_NONE;\n cap = cap < 0 || cap > 3 ? CAP_NONE : cap;\n const arc = options.arc && (options.arc <= 0 || options.arc > 1) ? 1 : (options.arc ?? 1);\n\n const path3D = computePath3D(path);\n const { tangents, normals, distances } = path3D;\n\n const pi2 = Math.PI * 2;\n const step = (pi2 / tessellation) * arc;\n const circlePaths: Vec3[][] = [];\n let index = cap === CAP_NONE || cap === CAP_END ? 0 : 2;\n\n for (let i = 0; i < path.length; i++) {\n const rad = radiusFunction ? radiusFunction(i, distances[i]!) : radius;\n const circle: Vec3[] = [];\n const normal = normals[i]!;\n const tangent = tangents[i]!;\n for (let t = 0; t < tessellation; t++) {\n const rotated = rodrigues(normal, tangent, step * t);\n circle.push({\n x: rotated.x * rad + path[i]!.x,\n y: rotated.y * rad + path[i]!.y,\n z: rotated.z * rad + path[i]!.z,\n });\n }\n circlePaths[index] = circle;\n index++;\n }\n\n const capPath = (nbPoints: number, pathIndex: number): Vec3[] => {\n const pts: Vec3[] = [];\n for (let i = 0; i < nbPoints; i++) {\n pts.push(path[pathIndex]!);\n }\n return pts;\n };\n if (cap === CAP_START || cap === CAP_ALL) {\n circlePaths[0] = capPath(tessellation, 0);\n circlePaths[1] = circlePaths[2]!.slice(0);\n }\n if (cap === CAP_END || cap === CAP_ALL) {\n circlePaths[index] = circlePaths[index - 1]!.slice(0);\n circlePaths[index + 1] = capPath(tessellation, path.length - 1);\n }\n\n return createRibbonData({\n pathArray: circlePaths,\n closePath: true,\n closeArray: false,\n });\n}\n","/**\n * CreateExtrudeShape — matches Babylon.js MeshBuilder.ExtrudeShape defaults.\n *\n * Sweeps a 2D `shape` (an array of Vec3 designed in the xOy plane; z becomes\n * the \"along-tangent\" dimension) along a 3D `path`, scaling and rotating at\n * each path point. Under the hood it builds a ribbon whose rows are the\n * transformed shape at each path position.\n *\n * Options omitted vs. BJS: `updatable`, `sideOrientation`, `frontUVs/backUVs`,\n * `invertUV`, `instance`, `closeShape`, `closePath`, `firstNormal`,\n * `adjustFrame`, `capFunction`. Defaults match: scale 1, rotation 0,\n * cap NO_CAP.\n */\n\nimport type { Vec3 } from \"../math/types.js\";\nimport { computePath3D } from \"./path3d.js\";\nimport { createRibbonData, type RibbonData } from \"./create-ribbon.js\";\nimport { CAP_NONE, CAP_START, CAP_END, CAP_ALL } from \"./create-tube.js\";\nexport { CAP_NONE, CAP_START, CAP_END, CAP_ALL } from \"./create-tube.js\";\n\n/** Options for `createExtrudeShapeData`: a 2D `shape` swept along a 3D `path`. */\nexport interface ExtrudeShapeOptions {\n shape: Vec3[];\n path: Vec3[];\n scale?: number;\n rotation?: number;\n cap?: number;\n}\n\nfunction rodrigues(v: Vec3, k: Vec3, angle: number): Vec3 {\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const dot = k.x * v.x + k.y * v.y + k.z * v.z;\n const crossX = k.y * v.z - k.z * v.y;\n const crossY = k.z * v.x - k.x * v.z;\n const crossZ = k.x * v.y - k.y * v.x;\n return {\n x: v.x * c + crossX * s + k.x * dot * (1 - c),\n y: v.y * c + crossY * s + k.y * dot * (1 - c),\n z: v.z * c + crossZ * s + k.z * dot * (1 - c),\n };\n}\n\nexport function createExtrudeShapeData(options: ExtrudeShapeOptions): RibbonData {\n const shape = options.shape;\n const curve = options.path;\n const scale = options.scale ?? 1;\n const rotation = options.rotation ?? 0;\n let cap = options.cap ?? CAP_NONE;\n cap = cap < 0 || cap > 3 ? CAP_NONE : cap;\n\n const path3D = computePath3D(curve);\n const { tangents, normals, binormals } = path3D;\n\n const shapePaths: Vec3[][] = [];\n let index = cap === CAP_NONE || cap === CAP_END ? 0 : 2;\n let angle = 0;\n for (let i = 0; i < curve.length; i++) {\n const shapePath: Vec3[] = [];\n const t = tangents[i]!;\n const n = normals[i]!;\n const b = binormals[i]!;\n for (let p = 0; p < shape.length; p++) {\n const sp = shape[p]!;\n // planed = t*sp.z + n*sp.x + b*sp.y\n const planed = {\n x: t.x * sp.z + n.x * sp.x + b.x * sp.y,\n y: t.y * sp.z + n.y * sp.x + b.y * sp.y,\n z: t.z * sp.z + n.z * sp.x + b.z * sp.y,\n };\n const rotated = rodrigues(planed, t, angle);\n shapePath.push({\n x: rotated.x * scale + curve[i]!.x,\n y: rotated.y * scale + curve[i]!.y,\n z: rotated.z * scale + curve[i]!.z,\n });\n }\n shapePaths[index] = shapePath;\n angle += rotation;\n index++;\n }\n\n const barycenterCap = (shapePath: Vec3[]): Vec3[] => {\n const bc = { x: 0, y: 0, z: 0 };\n for (const pt of shapePath) {\n bc.x += pt.x;\n bc.y += pt.y;\n bc.z += pt.z;\n }\n const inv = 1 / shapePath.length;\n bc.x *= inv;\n bc.y *= inv;\n bc.z *= inv;\n const out: Vec3[] = [];\n for (let i = 0; i < shapePath.length; i++) {\n out.push(bc);\n }\n return out;\n };\n\n if (cap === CAP_START || cap === CAP_ALL) {\n shapePaths[0] = barycenterCap(shapePaths[2]!);\n shapePaths[1] = shapePaths[2]!;\n }\n if (cap === CAP_END || cap === CAP_ALL) {\n shapePaths[index] = shapePaths[index - 1]!;\n shapePaths[index + 1] = barycenterCap(shapePaths[index - 1]!);\n }\n\n return createRibbonData({\n pathArray: shapePaths,\n closeArray: false,\n closePath: false,\n });\n}\n","/** High-level mesh factory functions.\n * Each creates geometry, uploads to GPU, and returns a Mesh.\n * The caller adds to the scene via addToScene(scene, mesh).\n *\n * Pillar 4b: plain data, no scene reference.\n * Pillar 4c: materials own shaders — mesh just holds material props. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh } from \"./mesh.js\";\nimport { initMeshTransform, uploadMeshToGPU } from \"./mesh.js\";\nimport { computeAabb } from \"../math/compute-aabb.js\";\nimport { createSphereData } from \"./create-sphere.js\";\nimport type { SphereOptions } from \"./create-sphere.js\";\nimport { createBoxData } from \"./create-box.js\";\nimport { createTorusData } from \"./create-torus.js\";\nimport type { TorusOptions } from \"./create-torus.js\";\nimport { createFlatGroundData, createGroundFromHeightMap as createGroundCPU } from \"./create-ground.js\";\nimport type { GroundOptions } from \"./create-ground.js\";\nimport { createCylinderData } from \"./create-cylinder.js\";\nimport type { CylinderOptions } from \"./create-cylinder.js\";\nimport { createPlaneData } from \"./create-plane.js\";\nimport type { PlaneOptions } from \"./create-plane.js\";\nimport { createDiscData } from \"./create-disc.js\";\nimport type { DiscOptions } from \"./create-disc.js\";\nimport { createPolyhedronData } from \"./create-polyhedron.js\";\nimport type { PolyhedronOptions } from \"./create-polyhedron.js\";\nimport { createRibbonData } from \"./create-ribbon.js\";\nimport type { RibbonOptions } from \"./create-ribbon.js\";\nimport { createTubeData } from \"./create-tube.js\";\nimport type { TubeOptions } from \"./create-tube.js\";\nimport { createExtrudeShapeData } from \"./create-extrude.js\";\nimport type { ExtrudeShapeOptions } from \"./create-extrude.js\";\n\n/** Create a Mesh from raw geometry data + GPU device.\n * No material is assigned — the caller must set mesh.material before adding to scene. */\nexport function createMeshFromData(\n engine: EngineContext,\n name: string,\n positions: Float32Array,\n normals: Float32Array,\n indices: Uint32Array,\n uvs?: Float32Array,\n uvs2?: Float32Array,\n tangents?: Float32Array,\n colors?: Float32Array\n): Mesh {\n const [min, max] = computeAabb(positions);\n const mesh = {\n name,\n material: null as unknown,\n receiveShadows: false,\n boundMin: isFinite(min[0]) ? min : undefined,\n boundMax: isFinite(max[0]) ? max : undefined,\n _materialDirty: false,\n _gpu: uploadMeshToGPU(engine, positions, normals, indices, uvs, uvs2, tangents, colors),\n } as unknown as Mesh;\n initMeshTransform(mesh);\n\n // Retain CPU geometry for detailed picking (ray-triangle intersection)\n mesh._cpuPositions = positions;\n mesh._cpuNormals = normals;\n mesh._cpuUvs = uvs;\n mesh._cpuIndices = indices;\n engine._dlr?.m(mesh, uvs2 ?? null, tangents ?? null, colors ?? null, indices, \"uint32\");\n\n return mesh;\n}\n\n/** Update a mesh's GPU vertex positions in place (e.g. CPU vertex animation).\n * `positions` must hold tightly-packed XYZ floats matching the mesh's vertex count.\n * `vertexOffset` is the first vertex to overwrite (defaults to 0).\n * The mesh must have been created via createMeshFromData / a mesh factory.\n * Zero-allocation GPU upload only — CPU-side picking geometry is not refreshed. */\nexport function updateMeshPositions(engine: EngineContext, mesh: Mesh, positions: Float32Array, vertexOffset = 0): void {\n const gpu = mesh._gpu;\n engine._device.queue.writeBuffer(gpu.positionBuffer, vertexOffset * 3 * 4, positions.buffer as ArrayBuffer, positions.byteOffset, positions.byteLength);\n}\n\n/** Create a sphere mesh. Caller must assign material. */\nexport function createSphere(engine: EngineContext, options?: SphereOptions): Mesh {\n const data = createSphereData(options);\n return createMeshFromData(engine as EngineContext, \"sphere\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a box mesh. Caller must assign material. */\nexport function createBox(engine: EngineContext, size = 1): Mesh {\n const data = createBoxData(size);\n return createMeshFromData(engine as EngineContext, \"box\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a torus mesh. Caller must assign material. */\nexport function createTorus(engine: EngineContext, options?: TorusOptions): Mesh {\n const data = createTorusData(options);\n return createMeshFromData(engine as EngineContext, \"torus\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a ground mesh from a heightmap URL. Caller must assign material. */\nexport async function createGroundFromHeightMap(engine: EngineContext, url: string, options: GroundOptions): Promise<Mesh> {\n const data = await createGroundCPU(url, options);\n return createMeshFromData(engine as EngineContext, \"ground\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a flat ground mesh. Caller must assign material. */\nexport function createGround(engine: EngineContext, options?: GroundOptions): Mesh {\n const data = createFlatGroundData(options);\n return createMeshFromData(engine as EngineContext, \"ground\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a cylinder (or cone / truncated cone / prism) mesh. Caller must assign material. */\nexport function createCylinder(engine: EngineContext, options?: CylinderOptions): Mesh {\n const data = createCylinderData(options);\n return createMeshFromData(engine as EngineContext, \"cylinder\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a plane (unit quad facing -Z). Caller must assign material. */\nexport function createPlane(engine: EngineContext, options?: PlaneOptions): Mesh {\n const data = createPlaneData(options);\n return createMeshFromData(engine as EngineContext, \"plane\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a disc (or ring / pie slice via `arc`). Caller must assign material. */\nexport function createDisc(engine: EngineContext, options?: DiscOptions): Mesh {\n const data = createDiscData(options);\n return createMeshFromData(engine as EngineContext, \"disc\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a polyhedron (15 presets). Caller must assign material. */\nexport function createPolyhedron(engine: EngineContext, options?: PolyhedronOptions): Mesh {\n const data = createPolyhedronData(options);\n return createMeshFromData(engine as EngineContext, \"polyhedron\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a ribbon from an array of parallel Vec3 paths. Caller must assign material. */\nexport function createRibbon(engine: EngineContext, options: RibbonOptions): Mesh {\n const data = createRibbonData(options);\n return createMeshFromData(engine as EngineContext, \"ribbon\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create a tube (circular cross-section swept along a path). Caller must assign material. */\nexport function createTube(engine: EngineContext, options: TubeOptions): Mesh {\n const data = createTubeData(options);\n return createMeshFromData(engine as EngineContext, \"tube\", data.positions, data.normals, data.indices, data.uvs);\n}\n\n/** Create an extruded shape (2D shape swept along a path). Caller must assign material. */\nexport function createExtrudeShape(engine: EngineContext, options: ExtrudeShapeOptions): Mesh {\n const data = createExtrudeShapeData(options);\n return createMeshFromData(engine as EngineContext, \"extrude\", data.positions, data.normals, data.indices, data.uvs);\n}\n","import type { Mat4 } from \"./types.js\";\n\n/** Compute inverse of a Mat4. Returns null if singular. */\nexport function mat4Invert(m: Mat4): Mat4 | null {\n const a00 = m[0]!,\n a01 = m[1]!,\n a02 = m[2]!,\n a03 = m[3]!;\n const a10 = m[4]!,\n a11 = m[5]!,\n a12 = m[6]!,\n a13 = m[7]!;\n const a20 = m[8]!,\n a21 = m[9]!,\n a22 = m[10]!,\n a23 = m[11]!;\n const a30 = m[12]!,\n a31 = m[13]!,\n a32 = m[14]!,\n a33 = m[15]!;\n\n const b00 = a00 * a11 - a01 * a10;\n const b01 = a00 * a12 - a02 * a10;\n const b02 = a00 * a13 - a03 * a10;\n const b03 = a01 * a12 - a02 * a11;\n const b04 = a01 * a13 - a03 * a11;\n const b05 = a02 * a13 - a03 * a12;\n const b06 = a20 * a31 - a21 * a30;\n const b07 = a20 * a32 - a22 * a30;\n const b08 = a20 * a33 - a23 * a30;\n const b09 = a21 * a32 - a22 * a31;\n const b10 = a21 * a33 - a23 * a31;\n const b11 = a22 * a33 - a23 * a32;\n\n let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n if (Math.abs(det) < 1e-10) {\n return null;\n }\n det = 1 / det;\n\n const out = new Float32Array(16) as Mat4;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return out;\n}\n","import type { Vec3Tuple } from \"./types.js\";\n\n/**\n * Normalizes the vector `(x, y, z)` to unit length.\n * @param x - X component.\n * @param y - Y component.\n * @param z - Z component.\n * @param epsilon - Length threshold below which the vector is treated as degenerate.\n * @returns The unit-length vector, or `[0, 1, 0]` if the input length is at or below `epsilon`.\n */\nexport function normalizeVec3(x: number, y: number, z: number, epsilon = 1e-10): Vec3Tuple {\n const len = Math.hypot(x, y, z);\n if (len <= epsilon) {\n return [0, 1, 0];\n }\n return [x / len, y / len, z / len];\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh } from \"./mesh.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Material } from \"../material/material.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { normalizeVec3 } from \"../math/normalize-vec3.js\";\nimport { createMeshFromData } from \"./mesh-factories.js\";\n\ndeclare const csgSolidBrand: unique symbol;\n\n/** An immutable BSP-based CSG solid (set of polygons) for boolean mesh operations. */\nexport interface CsgSolid {\n readonly [csgSolidBrand]: true;\n /** @internal */\n readonly _polygons: readonly CsgPolygon[];\n}\n\n/** @internal */\ninterface CsgVertex {\n readonly x: number;\n readonly y: number;\n readonly z: number;\n readonly nx: number;\n readonly ny: number;\n readonly nz: number;\n readonly u: number;\n readonly v: number;\n}\n\n/** @internal */\nclass CsgPlane {\n constructor(\n public nx: number,\n public ny: number,\n public nz: number,\n public w: number\n ) {}\n\n clone(): CsgPlane {\n return new CsgPlane(this.nx, this.ny, this.nz, this.w);\n }\n\n flip(): void {\n this.nx = -this.nx;\n this.ny = -this.ny;\n this.nz = -this.nz;\n this.w = -this.w;\n }\n}\n\n/** @internal */\nclass CsgPolygon {\n public plane: CsgPlane;\n\n constructor(\n public vertices: CsgVertex[],\n public readonly materialSlot = 0\n ) {\n this.plane = planeFromVertices(vertices[0]!, vertices[1]!, vertices[2]!);\n }\n\n clone(): CsgPolygon {\n return new CsgPolygon(this.vertices.map(cloneVertex), this.materialSlot);\n }\n\n flip(): void {\n this.vertices.reverse();\n this.vertices = this.vertices.map((v) => ({ ...v, nx: -v.nx, ny: -v.ny, nz: -v.nz }));\n this.plane.flip();\n }\n}\n\nclass CsgNode {\n private plane: CsgPlane | null = null;\n private polygons: CsgPolygon[] = [];\n private front: CsgNode | null = null;\n private back: CsgNode | null = null;\n\n constructor(polygons: CsgPolygon[] = []) {\n if (polygons.length > 0) {\n this.build(polygons);\n }\n }\n\n clone(): CsgNode {\n const node = new CsgNode();\n node.plane = this.plane?.clone() ?? null;\n node.polygons = this.polygons.map((p) => p.clone());\n node.front = this.front?.clone() ?? null;\n node.back = this.back?.clone() ?? null;\n return node;\n }\n\n invert(): void {\n for (const polygon of this.polygons) {\n polygon.flip();\n }\n this.plane?.flip();\n this.front?.invert();\n this.back?.invert();\n const temp = this.front;\n this.front = this.back;\n this.back = temp;\n }\n\n clipPolygons(polygons: CsgPolygon[]): CsgPolygon[] {\n if (!this.plane) {\n return polygons.map((p) => p.clone());\n }\n let front: CsgPolygon[] = [];\n let back: CsgPolygon[] = [];\n for (const polygon of polygons) {\n splitPolygon(this.plane, polygon, front, back, front, back);\n }\n if (this.front) {\n front = this.front.clipPolygons(front);\n }\n if (this.back) {\n back = this.back.clipPolygons(back);\n } else {\n back = [];\n }\n return front.concat(back);\n }\n\n clipTo(other: CsgNode): void {\n this.polygons = other.clipPolygons(this.polygons);\n this.front?.clipTo(other);\n this.back?.clipTo(other);\n }\n\n allPolygons(): CsgPolygon[] {\n let polygons = this.polygons.map((p) => p.clone());\n if (this.front) {\n polygons = polygons.concat(this.front.allPolygons());\n }\n if (this.back) {\n polygons = polygons.concat(this.back.allPolygons());\n }\n return polygons;\n }\n\n build(polygons: CsgPolygon[]): void {\n if (polygons.length === 0) {\n return;\n }\n if (!this.plane) {\n this.plane = polygons[0]!.plane.clone();\n }\n const front: CsgPolygon[] = [];\n const back: CsgPolygon[] = [];\n for (const polygon of polygons) {\n splitPolygon(this.plane, polygon, this.polygons, this.polygons, front, back);\n }\n if (front.length > 0) {\n if (!this.front) {\n this.front = new CsgNode();\n }\n this.front.build(front);\n }\n if (back.length > 0) {\n if (!this.back) {\n this.back = new CsgNode();\n }\n this.back.build(back);\n }\n }\n}\n\nconst EPSILON = 1e-5;\nconst COPLANAR = 0;\nconst FRONT = 1;\nconst BACK = 2;\nconst SPANNING = 3;\n\nfunction cloneVertex(v: CsgVertex): CsgVertex {\n return { x: v.x, y: v.y, z: v.z, nx: v.nx, ny: v.ny, nz: v.nz, u: v.u, v: v.v };\n}\n\nfunction planeFromVertices(a: CsgVertex, b: CsgVertex, c: CsgVertex): CsgPlane {\n const bax = b.x - a.x;\n const bay = b.y - a.y;\n const baz = b.z - a.z;\n const cax = c.x - a.x;\n const cay = c.y - a.y;\n const caz = c.z - a.z;\n const [nx, ny, nz] = normalizeVec3(cay * baz - caz * bay, caz * bax - cax * baz, cax * bay - cay * bax, 1e-20);\n return new CsgPlane(nx, ny, nz, nx * a.x + ny * a.y + nz * a.z);\n}\n\nfunction triangleArea2(a: CsgVertex, b: CsgVertex, c: CsgVertex): number {\n const bax = b.x - a.x;\n const bay = b.y - a.y;\n const baz = b.z - a.z;\n const cax = c.x - a.x;\n const cay = c.y - a.y;\n const caz = c.z - a.z;\n const cx = bay * caz - baz * cay;\n const cy = baz * cax - bax * caz;\n const cz = bax * cay - bay * cax;\n return cx * cx + cy * cy + cz * cz;\n}\n\nfunction interpolateVertex(a: CsgVertex, b: CsgVertex, t: number): CsgVertex {\n const nx = a.nx + (b.nx - a.nx) * t;\n const ny = a.ny + (b.ny - a.ny) * t;\n const nz = a.nz + (b.nz - a.nz) * t;\n const [nnx, nny, nnz] = normalizeVec3(nx, ny, nz, 1e-20);\n return {\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n z: a.z + (b.z - a.z) * t,\n nx: nnx,\n ny: nny,\n nz: nnz,\n u: a.u + (b.u - a.u) * t,\n v: a.v + (b.v - a.v) * t,\n };\n}\n\nfunction splitPolygon(plane: CsgPlane, polygon: CsgPolygon, coplanarFront: CsgPolygon[], coplanarBack: CsgPolygon[], front: CsgPolygon[], back: CsgPolygon[]): void {\n let polygonType = 0;\n const types: number[] = [];\n for (const vertex of polygon.vertices) {\n const t = plane.nx * vertex.x + plane.ny * vertex.y + plane.nz * vertex.z - plane.w;\n const type = t < -EPSILON ? BACK : t > EPSILON ? FRONT : COPLANAR;\n polygonType |= type;\n types.push(type);\n }\n\n if (polygonType === COPLANAR) {\n const facing = plane.nx * polygon.plane.nx + plane.ny * polygon.plane.ny + plane.nz * polygon.plane.nz;\n (facing > 0 ? coplanarFront : coplanarBack).push(polygon);\n return;\n }\n if (polygonType === FRONT) {\n front.push(polygon);\n return;\n }\n if (polygonType === BACK) {\n back.push(polygon);\n return;\n }\n\n const frontVertices: CsgVertex[] = [];\n const backVertices: CsgVertex[] = [];\n for (let i = 0; i < polygon.vertices.length; i++) {\n const j = (i + 1) % polygon.vertices.length;\n const vi = polygon.vertices[i]!;\n const vj = polygon.vertices[j]!;\n const ti = types[i]!;\n const tj = types[j]!;\n if (ti !== BACK) {\n frontVertices.push(cloneVertex(vi));\n }\n if (ti !== FRONT) {\n backVertices.push(cloneVertex(vi));\n }\n if ((ti | tj) === SPANNING) {\n const denom = plane.nx * (vj.x - vi.x) + plane.ny * (vj.y - vi.y) + plane.nz * (vj.z - vi.z);\n if (Math.abs(denom) > 1e-20) {\n const t = (plane.w - plane.nx * vi.x - plane.ny * vi.y - plane.nz * vi.z) / denom;\n const vertex = interpolateVertex(vi, vj, t);\n frontVertices.push(vertex);\n backVertices.push(cloneVertex(vertex));\n }\n }\n }\n if (frontVertices.length >= 3) {\n front.push(new CsgPolygon(frontVertices, polygon.materialSlot));\n }\n if (backVertices.length >= 3) {\n back.push(new CsgPolygon(backVertices, polygon.materialSlot));\n }\n}\n\nfunction solidFromPolygons(polygons: CsgPolygon[]): CsgSolid {\n return { _polygons: polygons } as unknown as CsgSolid;\n}\n\nfunction clonePolygons(solid: CsgSolid): CsgPolygon[] {\n return solid._polygons.map((p) => p.clone());\n}\n\nfunction transformPoint(m: Mat4, x: number, y: number, z: number): [number, number, number] {\n return [m[0]! * x + m[4]! * y + m[8]! * z + m[12]!, m[1]! * x + m[5]! * y + m[9]! * z + m[13]!, m[2]! * x + m[6]! * y + m[10]! * z + m[14]!];\n}\n\nfunction transformNormal(m: Mat4, inv: Mat4 | null, x: number, y: number, z: number): [number, number, number] {\n if (inv) {\n return normalizeVec3(inv[0]! * x + inv[1]! * y + inv[2]! * z, inv[4]! * x + inv[5]! * y + inv[6]! * z, inv[8]! * x + inv[9]! * y + inv[10]! * z, 1e-20);\n }\n return normalizeVec3(m[0]! * x + m[4]! * y + m[8]! * z, m[1]! * x + m[5]! * y + m[9]! * z, m[2]! * x + m[6]! * y + m[10]! * z, 1e-20);\n}\n\nfunction requireCpuGeometry(mesh: Mesh): Mesh {\n if (!mesh._cpuPositions) {\n throw new Error(`createCsgFromMesh(\"${mesh.name}\") requires CPU positions. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n if (!mesh._cpuIndices) {\n throw new Error(`createCsgFromMesh(\"${mesh.name}\") requires CPU indices. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n if (!mesh._cpuNormals) {\n throw new Error(`createCsgFromMesh(\"${mesh.name}\") requires CPU normals. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n return mesh;\n}\n\n/**\n * Builds a {@link CsgSolid} from a mesh's CPU geometry, baking its world transform.\n * @param mesh - Source mesh; must retain CPU positions, normals, and indices.\n * @param materialSlot - Material slot index tagged onto every generated polygon.\n * @returns A CSG solid usable with {@link csgUnion}, {@link csgSubtract}, and {@link csgIntersect}.\n */\nexport function createCsgFromMesh(mesh: Mesh, materialSlot = 0): CsgSolid {\n const internal = requireCpuGeometry(mesh);\n const positions = internal._cpuPositions!;\n const normals = internal._cpuNormals!;\n const indices = internal._cpuIndices!;\n const uvs = internal._cpuUvs;\n const world = mesh.worldMatrix;\n const invWorld = mat4Invert(world);\n const polygons: CsgPolygon[] = [];\n\n for (let i = 0; i < indices.length; i += 3) {\n const vertices: CsgVertex[] = [];\n for (let corner = 0; corner < 3; corner++) {\n const index = indices[i + corner]!;\n const p = index * 3;\n const uv = index * 2;\n const [x, y, z] = transformPoint(world, positions[p]!, positions[p + 1]!, positions[p + 2]!);\n const [nx, ny, nz] = transformNormal(world, invWorld, normals[p]!, normals[p + 1]!, normals[p + 2]!);\n vertices.push({ x, y, z, nx, ny, nz, u: uvs?.[uv] ?? 0, v: uvs?.[uv + 1] ?? 0 });\n }\n if (triangleArea2(vertices[0]!, vertices[1]!, vertices[2]!) <= EPSILON * EPSILON) {\n continue;\n }\n polygons.push(new CsgPolygon(vertices, materialSlot));\n }\n\n return solidFromPolygons(polygons);\n}\n\n/**\n * Returns the boolean union (`a` ∪ `b`) of two solids.\n * @returns A new solid; inputs are not modified.\n */\nexport function csgUnion(a: CsgSolid, b: CsgSolid): CsgSolid {\n const an = new CsgNode(clonePolygons(a));\n const bn = new CsgNode(clonePolygons(b));\n an.clipTo(bn);\n bn.clipTo(an);\n bn.invert();\n bn.clipTo(an);\n bn.invert();\n an.build(bn.allPolygons());\n return solidFromPolygons(an.allPolygons());\n}\n\n/**\n * Returns the boolean difference (`a` − `b`) of two solids.\n * @returns A new solid; inputs are not modified.\n */\nexport function csgSubtract(a: CsgSolid, b: CsgSolid): CsgSolid {\n const an = new CsgNode(clonePolygons(a));\n const bn = new CsgNode(clonePolygons(b));\n an.invert();\n an.clipTo(bn);\n bn.clipTo(an);\n bn.invert();\n bn.clipTo(an);\n bn.invert();\n an.build(bn.allPolygons());\n an.invert();\n return solidFromPolygons(an.allPolygons());\n}\n\n/**\n * Returns the boolean intersection (`a` ∩ `b`) of two solids.\n * @returns A new solid; inputs are not modified.\n */\nexport function csgIntersect(a: CsgSolid, b: CsgSolid): CsgSolid {\n const an = new CsgNode(clonePolygons(a));\n const bn = new CsgNode(clonePolygons(b));\n an.invert();\n bn.clipTo(an);\n bn.invert();\n an.clipTo(bn);\n bn.clipTo(an);\n an.build(bn.allPolygons());\n an.invert();\n return solidFromPolygons(an.allPolygons());\n}\n\nfunction createMeshFromPolygons(engine: EngineContext, polygons: readonly CsgPolygon[], name: string): Mesh {\n const positions: number[] = [];\n const normals: number[] = [];\n const uvs: number[] = [];\n const indices: number[] = [];\n\n for (const polygon of polygons) {\n const base = positions.length / 3;\n for (const vertex of polygon.vertices) {\n positions.push(vertex.x, vertex.y, vertex.z);\n normals.push(vertex.nx, vertex.ny, vertex.nz);\n uvs.push(vertex.u, vertex.v);\n }\n for (let i = 2; i < polygon.vertices.length; i++) {\n indices.push(base, base + i - 1, base + i);\n }\n }\n\n return createMeshFromData(engine as EngineContext, name, new Float32Array(positions), new Float32Array(normals), new Uint32Array(indices), new Float32Array(uvs));\n}\n\n/**\n * Triangulates a {@link CsgSolid} into a single renderable mesh.\n * @param name - Name for the created mesh.\n */\nexport function createMeshFromCsg(engine: EngineContext, solid: CsgSolid, name = \"csg\"): Mesh {\n return createMeshFromPolygons(engine, solid._polygons, name);\n}\n\nexport function createMeshesFromCsg(engine: EngineContext, solid: CsgSolid, materials: readonly Material[], name = \"csg\"): Mesh[] {\n const polygons = solid._polygons;\n const slots: number[] = [];\n for (const polygon of polygons) {\n if (!slots.includes(polygon.materialSlot)) {\n slots.push(polygon.materialSlot);\n }\n }\n slots.sort((a, b) => a - b);\n\n const meshes: Mesh[] = [];\n for (const slot of slots) {\n const material = materials[slot];\n if (!material) {\n throw new Error(`createMeshesFromCsg(\"${name}\") missing material for CSG material slot ${slot}.`);\n }\n const slotPolygons = polygons.filter((p) => p.materialSlot === slot);\n const mesh = createMeshFromPolygons(engine, slotPolygons, `${name}_sub${slot}`);\n mesh.material = material;\n meshes.push(mesh);\n }\n return meshes;\n}\n","import type { Manifold, ManifoldToplevel, Mesh as ManifoldMesh } from \"manifold-3d\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Material } from \"../material/material.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"./mesh.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { normalizeVec3 } from \"../math/normalize-vec3.js\";\nimport { createMeshFromData } from \"./mesh-factories.js\";\n\ndeclare const csg2SolidBrand: unique symbol;\n\nconst MATERIAL_ID_RESERVE_COUNT = 65536;\n\n/** A manifold-3d backed CSG solid for high-precision boolean mesh operations. */\nexport interface Csg2Solid {\n readonly [csg2SolidBrand]: true;\n /** @internal */\n _manifold: Manifold | null;\n /** @internal */\n readonly _numProp: number;\n}\n\ninterface Csg2Runtime {\n readonly Manifold: typeof Manifold;\n readonly Mesh: typeof ManifoldMesh;\n readonly firstMaterialId: number;\n}\n\ninterface GeometryBuffers {\n readonly positions: Float32Array;\n readonly normals: Float32Array;\n readonly indices: Uint32Array;\n readonly uvs: Float32Array | undefined;\n}\n\nlet csg2Runtime: Csg2Runtime | null = null;\nlet csg2RuntimePromise: Promise<Csg2Runtime> | null = null;\n\n/** Returns whether the manifold-3d runtime has finished loading and CSG2 is usable. */\nexport function isCsg2Ready(): boolean {\n return csg2Runtime !== null;\n}\n\n/** Loads the manifold-3d WASM runtime. Must be awaited once before any CSG2 operation. */\nexport async function initializeCsg2Async(): Promise<void> {\n await getRuntimeAsync();\n}\n\nasync function getRuntimeAsync(): Promise<Csg2Runtime> {\n if (csg2Runtime) {\n return csg2Runtime;\n }\n if (csg2RuntimePromise) {\n return csg2RuntimePromise;\n }\n\n csg2RuntimePromise = (async () => {\n const [module, wasm] = await Promise.all([import(\"manifold-3d\"), import(\"manifold-3d/manifold.wasm?url\")]);\n const manifoldModule: ManifoldToplevel = await module.default({\n locateFile: () => new URL(wasm.default, import.meta.url).href,\n });\n manifoldModule.setup();\n const runtime = {\n Manifold: manifoldModule.Manifold,\n Mesh: manifoldModule.Mesh,\n firstMaterialId: manifoldModule.Manifold.reserveIDs(MATERIAL_ID_RESERVE_COUNT),\n };\n csg2Runtime = runtime;\n return runtime;\n })();\n\n return csg2RuntimePromise;\n}\n\nfunction requireRuntime(): Csg2Runtime {\n if (!csg2Runtime) {\n throw new Error(\"CSG2 is not initialized. Call and await initializeCsg2Async() before using CSG2 operations.\");\n }\n return csg2Runtime;\n}\n\nfunction requireSolidManifold(solid: Csg2Solid, operation: string): Manifold {\n const manifold = solid._manifold;\n if (!manifold) {\n throw new Error(`${operation} cannot use a disposed CSG2 solid.`);\n }\n return manifold;\n}\n\nfunction solidFromManifold(manifold: Manifold, numProp: number): Csg2Solid {\n return { _manifold: manifold, _numProp: numProp } as unknown as Csg2Solid;\n}\n\nfunction transformPoint(m: Mat4, x: number, y: number, z: number): [number, number, number] {\n return [m[0]! * x + m[4]! * y + m[8]! * z + m[12]!, m[1]! * x + m[5]! * y + m[9]! * z + m[13]!, m[2]! * x + m[6]! * y + m[10]! * z + m[14]!];\n}\n\nfunction transformNormal(m: Mat4, inv: Mat4 | null, x: number, y: number, z: number): [number, number, number] {\n if (inv) {\n return normalizeVec3(inv[0]! * x + inv[1]! * y + inv[2]! * z, inv[4]! * x + inv[5]! * y + inv[6]! * z, inv[8]! * x + inv[9]! * y + inv[10]! * z, 1e-20);\n }\n return normalizeVec3(m[0]! * x + m[4]! * y + m[8]! * z, m[1]! * x + m[5]! * y + m[9]! * z, m[2]! * x + m[6]! * y + m[10]! * z, 1e-20);\n}\n\nfunction requireCpuGeometry(mesh: Mesh): GeometryBuffers {\n if (!mesh._cpuPositions) {\n throw new Error(`createCsg2FromMesh(\"${mesh.name}\") requires CPU positions. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n if (!mesh._cpuIndices) {\n throw new Error(`createCsg2FromMesh(\"${mesh.name}\") requires CPU indices. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n if (!mesh._cpuNormals) {\n throw new Error(`createCsg2FromMesh(\"${mesh.name}\") requires CPU normals. Use a Babylon Lite mesh factory or loader that retains CPU geometry.`);\n }\n return {\n positions: mesh._cpuPositions,\n normals: mesh._cpuNormals,\n indices: mesh._cpuIndices,\n uvs: mesh._cpuUvs,\n };\n}\n\n/**\n * Builds a {@link Csg2Solid} from a mesh's CPU geometry, baking its world transform.\n * @param mesh - Source mesh; must retain CPU positions, normals, and indices.\n * @param materialSlot - Material slot index (0 to 65535) tagged onto the solid's triangles.\n * @returns A CSG2 solid; call {@link disposeCsg2} when finished to free WASM memory.\n */\nexport function createCsg2FromMesh(mesh: Mesh, materialSlot = 0): Csg2Solid {\n const runtime = requireRuntime();\n if (materialSlot < 0 || materialSlot >= MATERIAL_ID_RESERVE_COUNT || !Number.isInteger(materialSlot)) {\n throw new Error(`createCsg2FromMesh(\"${mesh.name}\") materialSlot must be an integer from 0 to ${MATERIAL_ID_RESERVE_COUNT - 1}.`);\n }\n\n const geometry = requireCpuGeometry(mesh);\n const vertexCount = geometry.positions.length / 3;\n const numProp = 8;\n const vertProperties = new Float32Array(vertexCount * numProp);\n const world = mesh.worldMatrix;\n const invWorld = mat4Invert(world);\n\n for (let i = 0; i < vertexCount; i++) {\n const p = i * 3;\n const uv = i * 2;\n const out = i * numProp;\n const [x, y, z] = transformPoint(world, geometry.positions[p]!, geometry.positions[p + 1]!, geometry.positions[p + 2]!);\n const [nx, ny, nz] = transformNormal(world, invWorld, geometry.normals[p]!, geometry.normals[p + 1]!, geometry.normals[p + 2]!);\n vertProperties[out] = x;\n vertProperties[out + 1] = y;\n vertProperties[out + 2] = z;\n vertProperties[out + 3] = nx;\n vertProperties[out + 4] = ny;\n vertProperties[out + 5] = nz;\n vertProperties[out + 6] = geometry.uvs?.[uv] ?? 0;\n vertProperties[out + 7] = geometry.uvs?.[uv + 1] ?? 0;\n }\n\n const triVerts = new Uint32Array(geometry.indices.length);\n for (let i = 0; i < geometry.indices.length; i += 3) {\n triVerts[i] = geometry.indices[i + 2]!;\n triVerts[i + 1] = geometry.indices[i + 1]!;\n triVerts[i + 2] = geometry.indices[i]!;\n }\n\n const manifoldMesh = new runtime.Mesh({\n numProp,\n vertProperties,\n triVerts,\n runIndex: new Uint32Array([0]),\n runOriginalID: new Uint32Array([runtime.firstMaterialId + materialSlot]),\n });\n manifoldMesh.merge();\n\n try {\n return solidFromManifold(new runtime.Manifold(manifoldMesh), numProp);\n } catch (err) {\n throw new Error(`Error while creating CSG2 from mesh \"${mesh.name}\".`, { cause: err });\n }\n}\n\nfunction runBooleanOperation(operation: \"difference\" | \"intersection\" | \"union\", a: Csg2Solid, b: Csg2Solid): Csg2Solid {\n const runtime = requireRuntime();\n if (a._numProp !== b._numProp) {\n throw new Error(\"CSG2 operations require solids with the same vertex property layout.\");\n }\n return solidFromManifold(runtime.Manifold[operation](requireSolidManifold(a, `csg2 ${operation}`), requireSolidManifold(b, `csg2 ${operation}`)), a._numProp);\n}\n\n/** Returns the boolean difference (`a` − `b`) of two solids as a new solid. */\nexport function csg2Subtract(a: Csg2Solid, b: Csg2Solid): Csg2Solid {\n return runBooleanOperation(\"difference\", a, b);\n}\n\n/** Returns the boolean intersection (`a` ∩ `b`) of two solids as a new solid. */\nexport function csg2Intersect(a: Csg2Solid, b: Csg2Solid): Csg2Solid {\n return runBooleanOperation(\"intersection\", a, b);\n}\n\n/** Returns the boolean union (`a` ∪ `b`) of two solids as a new solid. */\nexport function csg2Add(a: Csg2Solid, b: Csg2Solid): Csg2Solid {\n return runBooleanOperation(\"union\", a, b);\n}\n\n/** Frees the WASM memory backing a solid. The solid must not be used afterwards. */\nexport function disposeCsg2(solid: Csg2Solid): void {\n if (solid._manifold) {\n solid._manifold.delete();\n solid._manifold = null;\n }\n}\n\nfunction materialSlotFromOriginalId(runtime: Csg2Runtime, originalId: number, name: string): number {\n const materialSlot = originalId - runtime.firstMaterialId;\n if (materialSlot < 0 || materialSlot >= MATERIAL_ID_RESERVE_COUNT) {\n throw new Error(`createMeshesFromCsg2(\"${name}\") received an unknown Manifold material original ID ${originalId}.`);\n }\n return materialSlot;\n}\n\nfunction appendTriangle(\n output: { positions: number[]; normals: number[]; uvs: number[]; indices: number[] },\n mesh: ManifoldMesh,\n triVerts: Uint32Array,\n numProp: number,\n triIndex: number\n): void {\n const base = output.positions.length / 3;\n for (let corner = 2; corner >= 0; corner--) {\n const vertexIndex = triVerts[triIndex + corner]!;\n const prop = vertexIndex * numProp;\n output.positions.push(mesh.vertProperties[prop]!, mesh.vertProperties[prop + 1]!, mesh.vertProperties[prop + 2]!);\n output.normals.push(mesh.vertProperties[prop + 3]!, mesh.vertProperties[prop + 4]!, mesh.vertProperties[prop + 5]!);\n output.uvs.push(mesh.vertProperties[prop + 6]!, mesh.vertProperties[prop + 7]!);\n output.indices.push(base + (2 - corner));\n }\n}\n\nfunction createMeshFromOutput(engine: EngineContext, name: string, output: { positions: number[]; normals: number[]; uvs: number[]; indices: number[] }): Mesh {\n if (output.positions.length === 0) {\n throw new Error(`Unable to build CSG2 mesh \"${name}\". Manifold has 0 vertices for this output.`);\n }\n return createMeshFromData(engine, name, new Float32Array(output.positions), new Float32Array(output.normals), new Uint32Array(output.indices), new Float32Array(output.uvs));\n}\n\n/**\n * Triangulates a {@link Csg2Solid} into a single renderable mesh.\n * @param name - Name for the created mesh.\n */\nexport function createMeshFromCsg2(engine: EngineContext, solid: Csg2Solid, name = \"csg2\"): Mesh {\n requireRuntime();\n const mesh = requireSolidManifold(solid, `createMeshFromCsg2(\"${name}\")`).getMesh();\n const output = { positions: [] as number[], normals: [] as number[], uvs: [] as number[], indices: [] as number[] };\n for (let i = 0; i < mesh.triVerts.length; i += 3) {\n appendTriangle(output, mesh, mesh.triVerts, solid._numProp, i);\n }\n return createMeshFromOutput(engine, name, output);\n}\n\n/**\n * Triangulates a {@link Csg2Solid} into one mesh per material slot.\n * @param materials - Materials indexed by the material slots assigned during construction.\n * @param name - Base name; each sub-mesh is suffixed with its slot index.\n * @returns One mesh per distinct material slot, each assigned its corresponding material.\n */\nexport function createMeshesFromCsg2(engine: EngineContext, solid: Csg2Solid, materials: readonly Material[], name = \"csg2\"): Mesh[] {\n const runtime = requireRuntime();\n const mesh = requireSolidManifold(solid, `createMeshesFromCsg2(\"${name}\")`).getMesh();\n const outputs: Array<{ materialSlot: number; positions: number[]; normals: number[]; uvs: number[]; indices: number[] }> = [];\n\n for (let run = 0; run < mesh.numRun; run++) {\n const originalId = mesh.runOriginalID[run]!;\n const materialSlot = materialSlotFromOriginalId(runtime, originalId, name);\n let output = outputs.find((entry) => entry.materialSlot === materialSlot);\n if (!output) {\n output = { materialSlot, positions: [], normals: [], uvs: [], indices: [] };\n outputs.push(output);\n }\n\n const start = mesh.runIndex[run] ?? 0;\n const end = mesh.runIndex[run + 1] ?? mesh.triVerts.length;\n for (let i = start; i < end; i += 3) {\n appendTriangle(output, mesh, mesh.triVerts, solid._numProp, i);\n }\n }\n\n outputs.sort((a, b) => a.materialSlot - b.materialSlot);\n return outputs.map((output) => {\n const material = materials[output.materialSlot];\n if (!material) {\n throw new Error(`createMeshesFromCsg2(\"${name}\") missing material for CSG2 material slot ${output.materialSlot}.`);\n }\n const result = createMeshFromOutput(engine, `${name}_sub${output.materialSlot}`, output);\n result.material = material;\n return result;\n });\n}\n","/** Create a 1×1 solid-color texture for flat-color PBR materials.\n * Avoids loading an image — just writes 4 bytes to a tiny GPU texture. */\n\nimport type { Texture2D } from \"./texture-2d.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\n\n/** Create a 1×1 solid-color `Texture2D` from straight RGBA components in [0, 1].\n * @param engine - Engine context.\n * @param r - Red channel (0–1).\n * @param g - Green channel (0–1).\n * @param b - Blue channel (0–1).\n * @param a - Alpha channel (0–1). Default 1.0.\n * @returns A bilinear-sampled `Texture2D` backed by a tiny GPU texture. */\nexport function createSolidTexture2D(engine: EngineContext, r: number, g: number, b: number, a: number = 1.0): Texture2D {\n const device = engine._device;\n const texture = device.createTexture({\n size: { width: 1, height: 1 },\n format: \"rgba8unorm\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n\n const data = new Uint8Array([Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), Math.round(a * 255)]);\n device.queue.writeTexture({ texture }, data, { bytesPerRow: 4, rowsPerImage: 1 }, { width: 1, height: 1 });\n\n const sampler = getBilinearSampler(engine);\n\n const tex: Texture2D = { texture, view: texture.createView(), sampler, width: 1, height: 1 };\n engine._dlr?.s(tex, r, g, b, a);\n return tex;\n}\n","/**\n * Create a 2D texture from raw pixel bytes (CPU-generated data).\n *\n * This is the generic analog to Babylon.js `RawTexture`: it uploads an\n * application-provided byte buffer into a GPU texture rather than decoding an\n * image from a URL. Use it for procedurally generated images, decoded asset\n * formats, or palette / lookup tables.\n *\n * The default sampler is nearest-neighbor with clamp-to-edge addressing and no\n * mipmaps — the common case for pixel-art / data textures. Override via options.\n */\n\nimport type { Texture2D } from \"./texture-2d.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { acquireTexture, getOrCreateSampler } from \"../resource/gpu-pool.js\";\n\n/** Sampler and format overrides for `createTexture2DFromPixels()`. */\nexport interface PixelsTexture2DOptions {\n /** Address mode U. Default 'clamp-to-edge'. */\n addressModeU?: GPUAddressMode;\n /** Address mode V. Default 'clamp-to-edge'. */\n addressModeV?: GPUAddressMode;\n /** Min filter. Default 'nearest'. */\n minFilter?: GPUFilterMode;\n /** Mag filter. Default 'nearest'. */\n magFilter?: GPUFilterMode;\n /** Use sRGB format (rgba8unorm-srgb) so the hardware converts to linear on\n * sample. Use for color data; leave false for lookup tables. Default false. */\n srgb?: boolean;\n}\n\n/**\n * Create a `Texture2D` from a tightly-packed RGBA8 byte buffer.\n *\n * @param engine - Engine context.\n * @param data - `width * height * 4` bytes, row-major, top-to-bottom, straight alpha.\n * @param width - Texture width in pixels (\\>= 1).\n * @param height - Texture height in pixels (\\>= 1).\n * @param options - Sampler / format overrides.\n */\nexport function createTexture2DFromPixels(engine: EngineContext, data: Uint8Array, width: number, height: number, options: PixelsTexture2DOptions = {}): Texture2D {\n if (width < 1 || height < 1) {\n throw new Error(`createTexture2DFromPixels: width/height must be >= 1 (got ${width}x${height})`);\n }\n const expected = width * height * 4;\n if (data.length < expected) {\n throw new Error(`createTexture2DFromPixels: data too short — need ${expected} bytes for ${width}x${height} RGBA, got ${data.length}`);\n }\n\n const device = engine._device;\n const format: GPUTextureFormat = options.srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n\n const texture = device.createTexture({\n size: { width, height },\n format,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n\n device.queue.writeTexture({ texture }, data as Uint8Array<ArrayBuffer>, { bytesPerRow: width * 4, rowsPerImage: height }, { width, height });\n\n const sampler = getOrCreateSampler(engine, {\n addressModeU: options.addressModeU ?? \"clamp-to-edge\",\n addressModeV: options.addressModeV ?? \"clamp-to-edge\",\n minFilter: options.minFilter ?? \"nearest\",\n magFilter: options.magFilter ?? \"nearest\",\n });\n\n const tex: Texture2D = { texture, view: texture.createView(), sampler, width, height };\n acquireTexture(tex);\n return tex;\n}\n","/**\n * 2D Texture loader — loads an image from URL into a GPU texture.\n *\n * Supports:\n * - rgba8unorm format (standard for diffuse/albedo textures)\n * - Automatic mipmap generation via copyExternalImageToTexture\n * - UV scaling via a texture matrix\n */\n\nimport { acquireTexture, getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\n\n/** A loaded 2D texture: the GPU texture, its default view and sampler, pixel\n * dimensions, and an optional per-texture UV transform. This is the public\n * texture handle returned by `loadTexture2D()`, `createSolidTexture2D()`, etc. */\nexport interface Texture2D {\n texture: GPUTexture;\n view: GPUTextureView;\n sampler: GPUSampler;\n width: number;\n height: number;\n /** Per-texture UV transform fields. All optional; defaults make identity.\n * Match BJS Texture.uScale/vScale/uOffset/vOffset/uAng semantics. These\n * fields are **build-time**: they are sampled when a material pipeline\n * is first compiled. Mutating them after the pipeline is built requires\n * a material rebuild (flag-based rebuild path). If a cached texture\n * wrapper needs a different transform than another use site, create a\n * fresh wrapper via `cloneTexture2D()`. */\n uScale?: number;\n vScale?: number;\n uOffset?: number;\n vOffset?: number;\n /** Rotation in radians around the (0,0) UV corner. */\n uAng?: number;\n /** True if the texel data is stored with origin at the top (y-down) and\n * must be flipped in V when sampled with standard (y-up) UVs. Applied at\n * UV-transform time in the material, so compressed-format textures (where\n * in-place row flipping is impractical) remain correct. */\n invertY?: boolean;\n /** @internal Depth textures require texture_depth_2d shader bindings. */\n _sampleType?: \"float\" | \"depth\";\n /** @internal Retained source for opt-in device-lost recovery. */\n _recoverySource?: Texture2DRecoverySource;\n}\n\nexport type Texture2DRecoverySource =\n | { kind: \"url\"; url: string; opts: Texture2DOptions }\n | { kind: \"solid\"; rgba: readonly [number, number, number, number] }\n | { kind: \"bitmap\"; bitmap: ImageBitmap | null; srgb: boolean; mipMaps: boolean; fallback?: Uint8Array; samplerDesc: GPUSamplerDescriptor };\n\n/** Create a fresh Texture2D wrapper that shares GPU resources with `base`\n * but carries its own UV transform. Use this when the same underlying image\n * is referenced with different transforms (e.g. glTF KHR_texture_transform\n * on different textureInfos pointing at the same source). The caller is\n * responsible for acquireTexture/release pairing if the wrapper outlives\n * the base. */\nexport function cloneTexture2D(\n base: Texture2D,\n transform: Partial<Pick<Texture2D, \"uScale\" | \"vScale\" | \"uOffset\" | \"vOffset\" | \"uAng\">> & { _texCoord?: 0 | 1; _hasTx?: true }\n): Texture2D {\n return { ...base, ...transform } as Texture2D;\n}\n\n/** Sampler, format, and decode options for `loadTexture2D()`. */\nexport interface Texture2DOptions {\n /** Generate mipmaps. Default true. */\n mipMaps?: boolean;\n /** Address mode U. Default 'repeat'. */\n addressModeU?: GPUAddressMode;\n /** Address mode V. Default 'repeat'. */\n addressModeV?: GPUAddressMode;\n /** Min filter. Default 'linear'. */\n minFilter?: GPUFilterMode;\n /** Mag filter. Default 'linear'. */\n magFilter?: GPUFilterMode;\n /** Flip Y axis during upload. Default true (matches Babylon.js convention). */\n invertY?: boolean;\n /** Use sRGB format (rgba8unorm-srgb). Enables hardware sRGB→linear on sample.\n * Use for color/albedo textures in PBR workflows. Default false. */\n srgb?: boolean;\n /** Premultiply alpha at decode time. Default false (straight RGBA, matches PNG-on-disk).\n * Set true for sprite atlases that will be rendered with a premultiplied blend pipeline\n * (`srcFactor: ONE`); doing so produces mathematically correct soft edges and stacked\n * translucency. */\n premultiplyAlpha?: boolean;\n}\n\n// Per-device URL cache: same (url + options) → shared Texture2D promise.\n// WeakMap ensures the cache is GC'd when the device is collected.\nlet _tex2dCache: WeakMap<GPUDevice, Map<string, Promise<Texture2D>>> | null = null;\n\n/** Clear the texture cache for a device, releasing cache-held refs. */\nexport function clearTexture2DCache(engine: EngineContext): void {\n const device = engine._device;\n _tex2dCache?.delete(device);\n}\n\n/** Load an image from `url` into a GPU `Texture2D`, generating mipmaps by default.\n * Results are cached per device by URL + options, so repeated calls with the\n * same arguments share one texture promise.\n * @param engine - Engine context.\n * @param url - Image URL to fetch and decode.\n * @param opts - Sampler, format, and decode overrides.\n * @returns A promise resolving to the uploaded `Texture2D`. */\nexport function loadTexture2D(engine: EngineContext, url: string, opts: Texture2DOptions = {}): Promise<Texture2D> {\n const device = engine._device;\n if (!_tex2dCache) {\n _tex2dCache = new WeakMap();\n }\n let dc = _tex2dCache.get(device);\n if (!dc) {\n dc = new Map();\n _tex2dCache.set(device, dc);\n }\n\n const key = `${url}\\0${opts.mipMaps ?? true}\\0${opts.addressModeU ?? \"repeat\"}\\0${opts.addressModeV ?? \"repeat\"}\\0${opts.minFilter ?? \"linear\"}\\0${opts.magFilter ?? \"linear\"}\\0${opts.invertY ?? true}\\0${opts.srgb ?? false}\\0${opts.premultiplyAlpha ?? false}`;\n const hit = dc.get(key);\n if (hit) {\n return hit;\n }\n\n const map = dc;\n const p = loadTexture2DImpl(engine, url, opts);\n map.set(key, p);\n p.catch(() => map.delete(key));\n return p;\n}\n\nasync function loadTexture2DImpl(engine: EngineContext, url: string, opts: Texture2DOptions): Promise<Texture2D> {\n const device = engine._device;\n const mipMaps = opts.mipMaps ?? true;\n const addressModeU = opts.addressModeU ?? \"repeat\";\n const addressModeV = opts.addressModeV ?? \"repeat\";\n const invertY = opts.invertY ?? true;\n const srgb = opts.srgb ?? false;\n const premultiplyAlpha = opts.premultiplyAlpha ?? false;\n const format: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n\n const response = await fetch(url);\n const blob = await response.blob();\n const imageBitmap = await createImageBitmap(blob, {\n premultiplyAlpha: premultiplyAlpha ? \"premultiply\" : \"none\",\n colorSpaceConversion: \"none\",\n });\n\n const width = imageBitmap.width;\n const height = imageBitmap.height;\n const mipLevelCount = mipMaps ? Math.floor(Math.log2(Math.max(width, height))) + 1 : 1;\n\n const texture = device.createTexture({\n size: { width, height },\n format,\n mipLevelCount,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n });\n\n device.queue.copyExternalImageToTexture({ source: imageBitmap, flipY: invertY }, { texture, premultipliedAlpha: premultiplyAlpha }, { width, height });\n imageBitmap.close();\n\n if (mipMaps && mipLevelCount > 1) {\n const { generateMipmaps } = await import(\"./generate-mipmaps.js\");\n generateMipmaps(engine, texture);\n }\n\n const minF = opts.minFilter ?? \"linear\";\n const magF = opts.magFilter ?? \"linear\";\n const mipF: GPUMipmapFilterMode = mipMaps ? \"linear\" : \"nearest\";\n const allLinear = minF === \"linear\" && magF === \"linear\" && mipF === \"linear\";\n const sampler = getOrCreateSampler(engine, {\n addressModeU,\n addressModeV,\n minFilter: minF,\n magFilter: magF,\n mipmapFilter: mipF,\n maxAnisotropy: allLinear ? 4 : 1,\n });\n\n const tex2d: Texture2D = { texture, view: texture.createView(), sampler, width, height };\n engine._dlr?.u(tex2d, url, opts);\n acquireTexture(tex2d);\n return tex2d;\n}\n","/**\n * GL internal format → WebGPU compressed texture format mapping.\n *\n * Maps KTX1 `glInternalFormat` values to the corresponding WebGPU\n * GPUTextureFormat, required device feature, and block dimensions.\n *\n * Only includes formats supported by WebGPU (PVRTC is excluded).\n *\n * Uses lazy-init to avoid module-level side effects (GUIDANCE.md §4).\n */\n\nexport interface CompressedFormatInfo {\n /** WebGPU texture format string (e.g. 'bc3-rgba-unorm'). */\n gpuFormat: GPUTextureFormat;\n /** Device feature required (e.g. 'texture-compression-bc'). */\n feature: string;\n /** Block width in texels. */\n blockW: number;\n /** Block height in texels. */\n blockH: number;\n /** Bytes per compressed block. */\n blockBytes: number;\n}\n\n// Lazy-initialized lookup table (no module-level side effects).\nlet _table: Map<number, CompressedFormatInfo> | null = null;\n\nfunction getTable(): Map<number, CompressedFormatInfo> {\n if (_table) {\n return _table;\n }\n const t = new Map<number, CompressedFormatInfo>();\n _table = t;\n\n function add(gl: number, gpuFormat: GPUTextureFormat, feature: string, blockW: number, blockH: number, blockBytes: number): void {\n t.set(gl, { gpuFormat, feature, blockW, blockH, blockBytes });\n }\n\n const BC = \"texture-compression-bc\";\n const ETC = \"texture-compression-etc2\";\n const ASTC = \"texture-compression-astc\";\n\n // ── BC / S3TC / DXT ─────────────────────────────────────────────\n add(0x83f0, \"bc1-rgba-unorm\", BC, 4, 4, 8); // COMPRESSED_RGB_S3TC_DXT1_EXT\n add(0x83f1, \"bc1-rgba-unorm\", BC, 4, 4, 8); // COMPRESSED_RGBA_S3TC_DXT1_EXT\n add(0x83f2, \"bc2-rgba-unorm\", BC, 4, 4, 16); // COMPRESSED_RGBA_S3TC_DXT3_EXT\n add(0x83f3, \"bc3-rgba-unorm\", BC, 4, 4, 16); // COMPRESSED_RGBA_S3TC_DXT5_EXT\n add(0x8dbb, \"bc4-r-unorm\", BC, 4, 4, 8); // COMPRESSED_RED_RGTC1\n add(0x8dbc, \"bc4-r-snorm\", BC, 4, 4, 8); // COMPRESSED_SIGNED_RED_RGTC1\n add(0x8dbd, \"bc5-rg-unorm\", BC, 4, 4, 16); // COMPRESSED_RG_RGTC2\n add(0x8dbe, \"bc5-rg-snorm\", BC, 4, 4, 16); // COMPRESSED_SIGNED_RG_RGTC2\n add(0x8e8f, \"bc6h-rgb-ufloat\", BC, 4, 4, 16); // COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT\n add(0x8e8e, \"bc6h-rgb-float\", BC, 4, 4, 16); // COMPRESSED_RGB_BPTC_SIGNED_FLOAT\n add(0x8e8c, \"bc7-rgba-unorm\", BC, 4, 4, 16); // COMPRESSED_RGBA_BPTC_UNORM\n add(0x8e8d, \"bc7-rgba-unorm-srgb\", BC, 4, 4, 16); // COMPRESSED_SRGB_ALPHA_BPTC_UNORM\n\n // ── ETC2 / EAC ──────────────────────────────────────────────────\n add(0x9270, \"eac-r11unorm\", ETC, 4, 4, 8); // COMPRESSED_R11_EAC\n add(0x9271, \"eac-r11snorm\", ETC, 4, 4, 8); // COMPRESSED_SIGNED_R11_EAC\n add(0x9272, \"eac-rg11unorm\", ETC, 4, 4, 16); // COMPRESSED_RG11_EAC\n add(0x9273, \"eac-rg11snorm\", ETC, 4, 4, 16); // COMPRESSED_SIGNED_RG11_EAC\n add(0x9274, \"etc2-rgb8unorm\", ETC, 4, 4, 8); // COMPRESSED_RGB8_ETC2\n add(0x9275, \"etc2-rgb8unorm-srgb\", ETC, 4, 4, 8); // COMPRESSED_SRGB8_ETC2\n add(0x9276, \"etc2-rgb8a1unorm\", ETC, 4, 4, 8); // COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2\n add(0x9277, \"etc2-rgb8a1unorm-srgb\", ETC, 4, 4, 8); // COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2\n add(0x9278, \"etc2-rgba8unorm\", ETC, 4, 4, 16); // COMPRESSED_RGBA8_ETC2_EAC\n add(0x9279, \"etc2-rgba8unorm-srgb\", ETC, 4, 4, 16); // COMPRESSED_SRGB8_ALPHA8_ETC2_EAC\n\n // ── ASTC (all block sizes are 16 bytes) ─────────────────────────\n const ASTC_BLOCKS: [number, number][] = [\n [4, 4],\n [5, 4],\n [5, 5],\n [6, 5],\n [6, 6],\n [8, 5],\n [8, 6],\n [8, 8],\n [10, 5],\n [10, 6],\n [10, 8],\n [10, 10],\n [12, 10],\n [12, 12],\n ];\n for (let i = 0; i < ASTC_BLOCKS.length; i++) {\n const [w, h] = ASTC_BLOCKS[i]!;\n const tag = `${w}x${h}`;\n add(0x93b0 + i, `astc-${tag}-unorm` as GPUTextureFormat, ASTC, w, h, 16);\n add(0x93d0 + i, `astc-${tag}-unorm-srgb` as GPUTextureFormat, ASTC, w, h, 16);\n }\n\n return t;\n}\n\n// ── Public lookup ───────────────────────────────────────────────────\n\n/** Look up compressed format info from a KTX1 glInternalFormat value. Returns undefined if unknown/unsupported. */\nexport function getCompressedFormat(glInternalFormat: number): CompressedFormatInfo | undefined {\n return getTable().get(glInternalFormat);\n}\n\n/** Map a KTX suffix string to the required WebGPU device feature. Returns undefined for unsupported (e.g. PVRTC). */\nexport function suffixToFeature(suffix: string): string | undefined {\n const s = suffix.toLowerCase();\n if (s.includes(\"astc\")) {\n return \"texture-compression-astc\";\n }\n if (s.includes(\"dxt\") || s.includes(\"s3tc\") || s.includes(\"bc\")) {\n return \"texture-compression-bc\";\n }\n if (s.includes(\"etc\")) {\n return \"texture-compression-etc2\";\n }\n return undefined;\n}\n","/**\n * KTX1 compressed texture loader.\n *\n * Loads a KTX1 file, parses the header, uploads compressed mip data to the GPU.\n * Falls back to loadTexture2D (uncompressed) if the device doesn't support the\n * format or the fetch fails.\n *\n * Fully tree-shakable: only bundled when explicitly imported.\n */\n\nimport { acquireTexture, getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { loadTexture2D } from \"./texture-2d.js\";\nimport type { Texture2D, Texture2DOptions } from \"./texture-2d.js\";\nimport { getCompressedFormat, suffixToFeature } from \"./compressed-formats.js\";\nimport type { CompressedFormatInfo } from \"./compressed-formats.js\";\n\n// ── KTX1 magic number ───────────────────────────────────────────────\n\nconst KTX_MAGIC = new Uint8Array([0xab, 0x4b, 0x54, 0x58, 0x20, 0x31, 0x31, 0xbb, 0x0d, 0x0a, 0x1a, 0x0a]);\n\n// ── Internal types ──────────────────────────────────────────────────\n\ninterface KtxMipLevel {\n data: Uint8Array;\n width: number;\n height: number;\n}\n\ninterface KtxParseResult {\n format: CompressedFormatInfo;\n width: number;\n height: number;\n mips: KtxMipLevel[];\n}\n\n// ── KTX1 parser ─────────────────────────────────────────────────────\n\nfunction parseKtx1(buffer: ArrayBuffer): KtxParseResult {\n const bytes = new Uint8Array(buffer);\n if (buffer.byteLength < 64) {\n throw new Error(\"KTX: file too small\");\n }\n\n // Validate magic\n for (let i = 0; i < 12; i++) {\n if (bytes[i] !== KTX_MAGIC[i]) {\n throw new Error(\"KTX: invalid magic\");\n }\n }\n\n const view = new DataView(buffer);\n\n // Endianness check\n if (view.getUint32(12, true) !== 0x04030201) {\n throw new Error(\"KTX: unsupported endianness\");\n }\n\n // Must be compressed (glType === 0 && glFormat === 0)\n if (view.getUint32(16, true) !== 0) {\n throw new Error(\"KTX: not a compressed texture (glType != 0)\");\n }\n if (view.getUint32(24, true) !== 0) {\n throw new Error(\"KTX: not a compressed texture (glFormat != 0)\");\n }\n\n const glInternalFormat = view.getUint32(28, true);\n const format = getCompressedFormat(glInternalFormat);\n if (!format) {\n throw new Error(`KTX: unknown glInternalFormat 0x${glInternalFormat.toString(16)}`);\n }\n\n const width = view.getUint32(36, true);\n const height = view.getUint32(40, true);\n const pixelDepth = view.getUint32(44, true);\n const numberOfArrayElements = view.getUint32(48, true);\n const numberOfFaces = view.getUint32(52, true);\n const numberOfMipmapLevels = Math.max(view.getUint32(56, true), 1);\n const bytesOfKeyValueData = view.getUint32(60, true);\n\n if (pixelDepth > 0) {\n throw new Error(\"KTX: 3D textures not supported\");\n }\n if (numberOfArrayElements > 0) {\n throw new Error(\"KTX: texture arrays not supported\");\n }\n if (numberOfFaces !== 1) {\n throw new Error(\"KTX: cubemaps not supported (use loadCubeTexture)\");\n }\n\n // Skip header + key/value metadata\n let offset = 64 + bytesOfKeyValueData;\n if (offset > buffer.byteLength) {\n throw new Error(\"KTX: key/value data overflows buffer\");\n }\n\n // Extract per-mip data (zero-copy views into the original ArrayBuffer)\n const mips: KtxMipLevel[] = [];\n let mipW = width;\n let mipH = height;\n\n for (let i = 0; i < numberOfMipmapLevels; i++) {\n if (offset + 4 > buffer.byteLength) {\n throw new Error(`KTX: truncated at mip ${i} size field`);\n }\n const imageSize = view.getUint32(offset, true);\n offset += 4;\n\n if (offset + imageSize > buffer.byteLength) {\n throw new Error(`KTX: mip ${i} data overflows buffer`);\n }\n\n mips.push({ data: new Uint8Array(buffer as ArrayBuffer, offset, imageSize), width: mipW, height: mipH });\n offset += imageSize;\n // Align to 4 bytes\n offset = (offset + 3) & ~3;\n\n mipW = Math.max(1, mipW >> 1);\n mipH = Math.max(1, mipH >> 1);\n }\n\n if (mips.length === 0) {\n throw new Error(\"KTX: no mip levels found\");\n }\n\n return { format, width, height, mips };\n}\n\n// ── GPU upload ──────────────────────────────────────────────────────\n\nfunction uploadCompressed(engine: EngineContext, parsed: KtxParseResult, opts: Texture2DOptions): Texture2D {\n const device = engine._device;\n const fmt = parsed.format;\n const texture = device.createTexture({\n size: { width: parsed.width, height: parsed.height },\n format: fmt.gpuFormat,\n mipLevelCount: parsed.mips.length,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n\n for (let i = 0; i < parsed.mips.length; i++) {\n const mip = parsed.mips[i]!;\n const blocksPerRow = Math.ceil(mip.width / fmt.blockW);\n const rowBytes = blocksPerRow * fmt.blockBytes;\n device.queue.writeTexture({ texture, mipLevel: i }, mip.data as Uint8Array<ArrayBuffer>, { bytesPerRow: rowBytes }, { width: mip.width, height: mip.height });\n }\n\n const minF = opts.minFilter ?? \"linear\";\n const magF = opts.magFilter ?? \"linear\";\n const mipF: GPUMipmapFilterMode = parsed.mips.length > 1 ? \"linear\" : \"nearest\";\n const allLinear = minF === \"linear\" && magF === \"linear\" && mipF === \"linear\";\n const sampler = getOrCreateSampler(engine, {\n addressModeU: opts.addressModeU ?? \"repeat\",\n addressModeV: opts.addressModeV ?? \"repeat\",\n minFilter: minF,\n magFilter: magF,\n mipmapFilter: mipF,\n maxAnisotropy: allLinear ? 4 : 1,\n });\n\n const tex2d: Texture2D = {\n texture,\n view: texture.createView(),\n sampler,\n width: parsed.width,\n height: parsed.height,\n };\n acquireTexture(tex2d);\n return tex2d;\n}\n\n// ── URL rewriting ───────────────────────────────────────────────────\n\nfunction rewriteUrl(baseUrl: string, suffix: string): string {\n // \"https://host/path/UVgrid.png\" + \"-dxt.ktx\" → \"https://host/path/UVgrid-dxt.ktx\"\n const qIdx = baseUrl.indexOf(\"?\");\n const base = qIdx >= 0 ? baseUrl.substring(0, qIdx) : baseUrl;\n const query = qIdx >= 0 ? baseUrl.substring(qIdx) : \"\";\n const dotIdx = base.lastIndexOf(\".\");\n if (dotIdx < 0) {\n return base + suffix + query;\n }\n return base.substring(0, dotIdx) + suffix + query;\n}\n\n// ── Public API ──────────────────────────────────────────────────────\n\n/**\n * Load a texture with KTX compressed format auto-selection and fallback.\n *\n * Tries each suffix in priority order, picks the first whose compressed format\n * the GPU supports, fetches and parses the KTX1 file, and uploads it as a\n * compressed GPU texture. Falls back to the base URL (loaded as a regular image)\n * if no suffix is supported or loading fails.\n *\n * @param engine - The engine context (device must have compressed texture features enabled).\n * @param baseUrl - The fallback image URL (e.g. \"textures/grid.png\").\n * @param suffixes - KTX suffixes to try in priority order (e.g. [\"-astc.ktx\", \"-dxt.ktx\", \"-etc2.ktx\"]).\n * @param opts - Texture options (sampler, address mode, etc.). `mipMaps` is ignored — KTX mips are used as-is.\n * @returns A Texture2D (same interface whether compressed or fallback).\n */\nexport async function loadKtxTexture2D(engine: EngineContext, baseUrl: string, suffixes: string[], opts: Texture2DOptions = {}): Promise<Texture2D> {\n const device = engine._device;\n\n // Collect all suffixes whose feature the device supports\n const supported: string[] = [];\n for (const suffix of suffixes) {\n const feature = suffixToFeature(suffix);\n if (feature && device.features.has(feature as GPUFeatureName)) {\n supported.push(suffix);\n }\n }\n\n // Try each supported suffix; fall through on any failure\n for (const suffix of supported) {\n try {\n const ktxUrl = rewriteUrl(baseUrl, suffix);\n const resp = await fetch(ktxUrl);\n if (!resp.ok) {\n throw new Error(`KTX fetch failed: ${resp.status}`);\n }\n const parsed = parseKtx1(await resp.arrayBuffer());\n return uploadCompressed(engine, parsed, opts);\n } catch (e) {\n console.warn(`KTX load failed for suffix \"${suffix}\":`, e);\n }\n }\n\n // Fallback: load as regular image\n return loadTexture2D(engine, baseUrl, opts);\n}\n","/**\n * Basis Universal texture loader.\n *\n * Loads a .basis file, transcodes it on the main thread via the Binomial LLC\n * Basis Universal transcoder (fetched lazily from the Babylon.js CDN), selects\n * the best GPU-supported compressed format, and uploads the transcoded mip\n * chain as a WebGPU texture.\n *\n * Format priority (by WebGPU device features):\n * BC7 → ASTC 4×4 → ETC2 → BC3 → RGBA32 (uncompressed fallback)\n *\n * Fully tree-shakable: only bundled when explicitly imported. The transcoder\n * JS+WASM are fetched at runtime on the first call, so the bundle cost is just\n * this wrapper (no transcoder bytes are shipped).\n */\n\nimport { acquireTexture, getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D, Texture2DOptions } from \"./texture-2d.js\";\n\n// ── Basis transcoder format IDs (match BinomialLLC basis_transcoder.js) ─────\n// Names from basis_transcoder.js `BASIS_FORMAT`.\nconst cTFETC1 = 0;\nconst cTFETC2 = 1;\nconst cTFBC1 = 2;\nconst cTFBC3 = 3;\nconst cTFBC7 = 6;\nconst cTFASTC_4x4 = 10;\nconst cTFRGBA32 = 13;\n\ninterface BasisModule {\n initializeBasis(): void;\n BasisFile: new (data: Uint8Array) => BasisFileHandle;\n}\n\ninterface BasisFileHandle {\n close(): void;\n delete(): void;\n getHasAlpha(): number;\n getNumImages(): number;\n getNumLevels(imageIndex: number): number;\n getImageWidth(imageIndex: number, level: number): number;\n getImageHeight(imageIndex: number, level: number): number;\n getImageTranscodedSizeInBytes(imageIndex: number, level: number, format: number): number;\n startTranscoding(): number;\n transcodeImage(dst: Uint8Array, imageIndex: number, level: number, format: number, unused: number, getAlphaForOpaqueFormats: number): number;\n}\n\n// ── Lazy transcoder loader ──────────────────────────────────────────────────\n\nconst CDN_BASE = \"https://cdn.babylonjs.com/basisTranscoder/1\";\n\nlet _modulePromise: Promise<BasisModule> | null = null;\n\nfunction loadBasisModule(): Promise<BasisModule> {\n if (_modulePromise) {\n return _modulePromise;\n }\n _modulePromise = new Promise<BasisModule>((resolve, reject) => {\n const w = globalThis as unknown as { BASIS?: (opts: { locateFile: (p: string) => string }) => Promise<BasisModule> };\n const init = (): void => {\n const BASIS = w.BASIS;\n if (!BASIS) {\n reject(new Error(\"Basis: transcoder global BASIS not found after script load\"));\n return;\n }\n BASIS({ locateFile: (p: string) => `${CDN_BASE}/${p}` })\n .then((mod) => {\n mod.initializeBasis();\n resolve(mod);\n })\n .catch(reject);\n };\n if (w.BASIS) {\n init();\n return;\n }\n const script = document.createElement(\"script\");\n script.src = `${CDN_BASE}/basis_transcoder.js`;\n script.async = true;\n script.onload = init;\n script.onerror = (): void => reject(new Error(`Basis: failed to load ${script.src}`));\n document.head.appendChild(script);\n });\n _modulePromise.catch(() => {\n _modulePromise = null;\n });\n return _modulePromise;\n}\n\n// ── GPU format selection ────────────────────────────────────────────────────\n\ninterface BasisTargetFormat {\n /** basis_transcoder format id (BASIS_FORMAT.*). */\n basisFormat: number;\n /** Corresponding WebGPU format (unorm variant). */\n gpuFormat: GPUTextureFormat;\n /** sRGB counterpart (undefined if none). */\n gpuFormatSrgb?: GPUTextureFormat;\n /** Device feature required (undefined = always available, e.g. rgba8). */\n feature?: GPUFeatureName;\n /** Block width in texels (1 for uncompressed). */\n blockW: number;\n /** Block height in texels. */\n blockH: number;\n /** Bytes per compressed block (or per-texel for uncompressed rgba8 = 4). */\n blockBytes: number;\n /** True if this format encodes alpha. */\n hasAlpha: boolean;\n}\n\n// Priority-ordered target formats. Alpha-capable formats are preferred when the\n// source has alpha; opaque-only formats are skipped in that case (BC1).\nconst BASIS_TARGETS: BasisTargetFormat[] = [\n {\n basisFormat: cTFBC7,\n gpuFormat: \"bc7-rgba-unorm\",\n gpuFormatSrgb: \"bc7-rgba-unorm-srgb\",\n feature: \"texture-compression-bc\",\n blockW: 4,\n blockH: 4,\n blockBytes: 16,\n hasAlpha: true,\n },\n {\n basisFormat: cTFASTC_4x4,\n gpuFormat: \"astc-4x4-unorm\",\n gpuFormatSrgb: \"astc-4x4-unorm-srgb\",\n feature: \"texture-compression-astc\",\n blockW: 4,\n blockH: 4,\n blockBytes: 16,\n hasAlpha: true,\n },\n {\n basisFormat: cTFETC2,\n gpuFormat: \"etc2-rgba8unorm\",\n gpuFormatSrgb: \"etc2-rgba8unorm-srgb\",\n feature: \"texture-compression-etc2\",\n blockW: 4,\n blockH: 4,\n blockBytes: 16,\n hasAlpha: true,\n },\n {\n basisFormat: cTFBC3,\n gpuFormat: \"bc3-rgba-unorm\",\n gpuFormatSrgb: \"bc3-rgba-unorm-srgb\",\n feature: \"texture-compression-bc\",\n blockW: 4,\n blockH: 4,\n blockBytes: 16,\n hasAlpha: true,\n },\n {\n basisFormat: cTFBC1,\n gpuFormat: \"bc1-rgba-unorm\",\n gpuFormatSrgb: \"bc1-rgba-unorm-srgb\",\n feature: \"texture-compression-bc\",\n blockW: 4,\n blockH: 4,\n blockBytes: 8,\n hasAlpha: false,\n },\n // Uncompressed fallback — always supported, no device feature needed.\n { basisFormat: cTFRGBA32, gpuFormat: \"rgba8unorm\", gpuFormatSrgb: \"rgba8unorm-srgb\", blockW: 1, blockH: 1, blockBytes: 4, hasAlpha: true },\n // ETC1 fallback kept last (rare on WebGPU; mapped via ETC2 feature on GPUs that expose it).\n {\n basisFormat: cTFETC1,\n gpuFormat: \"etc2-rgb8unorm\",\n gpuFormatSrgb: \"etc2-rgb8unorm-srgb\",\n feature: \"texture-compression-etc2\",\n blockW: 4,\n blockH: 4,\n blockBytes: 8,\n hasAlpha: false,\n },\n];\n\nfunction pickTarget(device: GPUDevice, sourceHasAlpha: boolean): BasisTargetFormat {\n for (const t of BASIS_TARGETS) {\n if (!t.hasAlpha && sourceHasAlpha) {\n continue;\n }\n if (t.feature && !device.features.has(t.feature)) {\n continue;\n }\n return t;\n }\n // rgba8unorm entry has no feature gate, so we always reach it.\n return BASIS_TARGETS[BASIS_TARGETS.length - 2]!;\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Load a Basis Universal (.basis) texture, transcode it to the best GPU-supported\n * compressed format, and upload to a WebGPU texture.\n *\n * @param engine - The engine context.\n * @param url - URL of the .basis file.\n * @param opts - Sampler/address/filter options. `mipMaps` is ignored — basis\n * mips are used as-is. `invertY` is ignored — basis data is\n * already oriented for sampling.\n * @returns A Texture2D.\n */\nexport async function loadBasisTexture2D(engine: EngineContext, url: string, opts: Texture2DOptions = {}): Promise<Texture2D> {\n const device = engine._device;\n\n const [mod, buffer] = await Promise.all([loadBasisModule(), fetch(url).then((r) => r.arrayBuffer())]);\n\n const bytes = new Uint8Array(buffer);\n const file = new mod.BasisFile(bytes);\n try {\n if (file.getNumImages() === 0) {\n throw new Error(\"Basis: no images in file\");\n }\n if (file.startTranscoding() === 0) {\n throw new Error(\"Basis: startTranscoding failed\");\n }\n\n const hasAlpha = file.getHasAlpha() !== 0;\n const target = pickTarget(device, hasAlpha);\n const width = file.getImageWidth(0, 0);\n const height = file.getImageHeight(0, 0);\n const levels = file.getNumLevels(0);\n\n const srgb = opts.srgb ?? false;\n const gpuFormat: GPUTextureFormat = srgb && target.gpuFormatSrgb ? target.gpuFormatSrgb : target.gpuFormat;\n\n // Transcode all mip levels.\n const mips: { data: Uint8Array; width: number; height: number }[] = [];\n for (let level = 0; level < levels; level++) {\n const mipW = file.getImageWidth(0, level);\n const mipH = file.getImageHeight(0, level);\n const size = file.getImageTranscodedSizeInBytes(0, level, target.basisFormat);\n if (size === 0) {\n throw new Error(`Basis: transcoded size is 0 for mip ${level}`);\n }\n const dst = new Uint8Array(size);\n const ok = file.transcodeImage(dst, 0, level, target.basisFormat, 0, hasAlpha ? 1 : 0);\n if (ok === 0) {\n throw new Error(`Basis: transcodeImage failed for mip ${level}`);\n }\n mips.push({ data: dst, width: mipW, height: mipH });\n }\n\n // Create and populate the GPU texture.\n const texture = device.createTexture({\n size: { width, height },\n format: gpuFormat,\n mipLevelCount: mips.length,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n\n for (let level = 0; level < mips.length; level++) {\n const mip = mips[level]!;\n const blocksPerRow = Math.ceil(mip.width / target.blockW);\n const rowBytes = target.blockW === 1 ? mip.width * target.blockBytes : blocksPerRow * target.blockBytes;\n device.queue.writeTexture({ texture, mipLevel: level }, mip.data as Uint8Array<ArrayBuffer>, { bytesPerRow: rowBytes }, { width: mip.width, height: mip.height });\n }\n\n const minF = opts.minFilter ?? \"linear\";\n const magF = opts.magFilter ?? \"linear\";\n const mipF: GPUMipmapFilterMode = mips.length > 1 ? \"linear\" : \"nearest\";\n const allLinear = minF === \"linear\" && magF === \"linear\" && mipF === \"linear\";\n const sampler = getOrCreateSampler(engine, {\n addressModeU: opts.addressModeU ?? \"repeat\",\n addressModeV: opts.addressModeV ?? \"repeat\",\n minFilter: minF,\n magFilter: magF,\n mipmapFilter: mipF,\n maxAnisotropy: allLinear ? 4 : 1,\n });\n\n const tex2d: Texture2D = { texture, view: texture.createView(), sampler, width, height, invertY: true };\n acquireTexture(tex2d);\n return tex2d;\n } finally {\n file.close();\n file.delete();\n }\n}\n","import type { ShaderFragment } from \"../../shader/fragment-types.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { StandardMaterialProps } from \"./standard-material.js\";\n\n// ─── Feature Flags ──────────────────────────────────────────────────\n\nexport const HAS_DIFFUSE_TEXTURE = 1 << 0;\nexport const HAS_EMISSIVE_TEXTURE = 1 << 1;\nexport const HAS_BUMP_TEXTURE = 1 << 2;\nexport const HAS_SPECULAR_TEXTURE = 1 << 3;\nexport const HAS_AMBIENT_TEXTURE = 1 << 4;\nexport const HAS_LIGHTMAP_TEXTURE = 1 << 5;\nexport const HAS_OPACITY_TEXTURE = 1 << 6;\nexport const LIGHTMAP_USES_UV2 = 1 << 7;\nexport const AMBIENT_USES_UV2 = 1 << 8;\nexport const DOUBLE_SIDED = 1 << 9;\nexport const DIFFUSE_USES_UV2 = 1 << 10;\nexport const SPECULAR_USES_UV2 = 1 << 11;\nexport const OPACITY_FROM_RGB = 1 << 12;\nexport const HAS_REFLECTION_TEXTURE = 1 << 13;\nexport const DISABLE_LIGHTING = 1 << 14;\nexport const MATERIAL_ALPHA_BLEND = 1 << 16;\nexport const HAS_CUBE_REFLECTION = 1 << 17;\nexport const NO_COLOR_OUTPUT = 1 << 18;\nexport const HAS_DEPTH_EMISSIVE_TEXTURE = 1 << 19;\nexport const ESM_SHADOW_OUTPUT = 1 << 20;\n\n// ─── Standard Material Extension Registry ───────────────────────────\n\n/** Bind-ordering phase for StdExt textures (alphabetical by id within phase, matching composer). */\nexport type StdExtPhase = \"mesh\";\n\n/** Unified extension for Standard material. Each fragment module exports one.\n * Fragments register via `_registerStdExt(ext)` at dynamic-import sites. */\nexport interface StdExt {\n /** @internal */\n readonly _id: string;\n /** @internal */\n readonly _phase: StdExtPhase;\n /** @internal Feature bit this ext gates on. */\n readonly _feature: number;\n /** @internal */\n _frag(features: number, shadowLights?: ShadowLightSlotLite[]): ShaderFragment;\n /** @internal Push group-1 bind entries starting at binding `b`; return new b. */\n _bind?(mat: StandardMaterialProps, entries: GPUBindGroupEntry[], b: number): number;\n /** @internal Enumerate textures for acquire/release. */\n _textures?(mat: StandardMaterialProps, out: Texture2D[]): void;\n}\n\nexport interface ShadowLightSlotLite {\n lightIndex: number;\n shadowType: \"esm\" | \"pcf\";\n}\n\n// Lazy-init: avoids a module-level `new Map()` that defeats tree-shaking for\n// consumers importing flags/registry symbols without using extensions.\n// See GUIDANCE.md §4 (\"Zero module-level side effects\").\nlet _stdExts: Map<string, StdExt> | null = null;\nlet _stdExtsSorted: readonly StdExt[] | null = null;\n\nexport function _registerStdExt(ext: StdExt): void {\n (_stdExts ??= new Map()).set(ext._id, ext);\n _stdExtsSorted = null;\n}\n\nexport function _getStdExts(): ReadonlyMap<string, StdExt> {\n return (_stdExts ??= new Map());\n}\n\nexport function _getStdExtsSorted(): readonly StdExt[] {\n if (!_stdExtsSorted) {\n const map = _stdExts;\n _stdExtsSorted = map ? Array.from(map.values()).sort((a, b) => a._id.localeCompare(b._id)) : [];\n }\n return _stdExtsSorted;\n}\n\n/** Derived: mesh needs UV attribute (any texture present). */\nexport const NEEDS_UV = HAS_DIFFUSE_TEXTURE | HAS_EMISSIVE_TEXTURE | HAS_BUMP_TEXTURE | HAS_SPECULAR_TEXTURE | HAS_AMBIENT_TEXTURE | HAS_LIGHTMAP_TEXTURE | HAS_OPACITY_TEXTURE;\n\n/** Derived: mesh needs UV2 attribute. */\nexport const NEEDS_UV2 = LIGHTMAP_USES_UV2 | AMBIENT_USES_UV2 | DIFFUSE_USES_UV2 | SPECULAR_USES_UV2;\n","import type { EngineContext } from \"../../engine/engine.js\";\nimport type { MeshGroupBuilder } from \"../../render/renderable.js\";\nimport { _registerStdExt } from \"./standard-flags.js\";\nimport type { StandardMaterialProps } from \"./standard-material.js\";\n\n/** Lazy-imports the standard renderable builder and builds the pipeline. */\n// Material-property → fragment-module dispatch table. Each entry is a plain\n// extension: if any mesh's material has the named property, dynamic-import\n// the fragment module and register the named StdExt export. Keeping this as\n// a data table rather than an if-ladder keeps core size flat as extensions\n// grow.\nconst _STD_MAT_EXTS: ReadonlyArray<readonly [keyof StandardMaterialProps, () => Promise<any>, string]> = [\n [\"bumpTexture\", () => import(\"./fragments/normal-map-fragment.js\"), \"bumpStdExt\"],\n [\"emissiveTexture\", () => import(\"./fragments/std-emissive-fragment.js\"), \"stdEmissiveExt\"],\n [\"specularTexture\", () => import(\"./fragments/std-specular-fragment.js\"), \"stdSpecularExt\"],\n [\"ambientTexture\", () => import(\"./fragments/std-ambient-fragment.js\"), \"stdAmbientExt\"],\n [\"lightmapTexture\", () => import(\"./fragments/std-lightmap-fragment.js\"), \"stdLightmapExt\"],\n [\"opacityTexture\", () => import(\"./fragments/std-opacity-fragment.js\"), \"stdOpacityExt\"],\n [\"reflectionTexture\", () => import(\"./fragments/std-reflection-fragment.js\"), \"stdReflectionExt\"],\n [\"reflectionCubeTexture\", () => import(\"./fragments/std-cube-reflection-fragment.js\"), \"stdCubeReflectionExt\"],\n];\n\nexport const standardGroupBuilder: MeshGroupBuilder = async (scene, meshes) => {\n const hasTI = meshes.some((m) => !!m.thinInstances);\n const hasShadow = meshes.some((m) => m.receiveShadows) && scene.lights.some((l: { shadowGenerator?: unknown }) => !!l.shadowGenerator);\n\n let tiSync: ((engine: EngineContext, ti: any, pass: GPURenderPassEncoder | GPURenderBundleEncoder, slot: number, hasColor: boolean) => number) | undefined;\n let tiFragment: any;\n let shadowFragment: any;\n\n const imports: Promise<any>[] = [];\n if (hasTI) {\n imports.push(\n import(\"../../mesh/thin-instance-gpu.js\").then((m) => {\n tiSync = m.syncThinInstanceBuffers;\n }),\n import(\"../../shader/fragments/thin-instance-fragment.js\").then((m) => {\n tiFragment = m.createThinInstanceFragment;\n })\n );\n }\n if (hasShadow) {\n imports.push(\n import(\"./fragments/std-shadow-fragment.js\").then((m) => {\n shadowFragment = m.createStdShadowFragment;\n })\n );\n }\n for (const [prop, load, key] of _STD_MAT_EXTS) {\n if (meshes.some((m) => !!(m.material as any)[prop])) {\n imports.push(load().then((mod) => _registerStdExt(mod[key])));\n }\n }\n if (imports.length > 0) {\n await Promise.all(imports);\n }\n\n const renderableMod = await import(\"./standard-renderable.js\");\n const result = renderableMod.buildStandardMeshRenderables(scene, meshes, {\n tiSync,\n tiFragment,\n shadowFragment,\n });\n // Wire the per-mesh rebuild closure used by material swap + per-pass override.\n standardGroupBuilder._rebuildSingle = result.rebuildSingle;\n return result;\n};\n\nstandardGroupBuilder._materialFamily = \"standard\";\n","import type { StandardMaterialProps } from \"./standard-material.js\";\nimport { standardGroupBuilder } from \"./standard-group-builder.js\";\n\n/** Create StandardMaterial with Babylon defaults. */\nexport function createStandardMaterial(): StandardMaterialProps {\n return {\n diffuseColor: [1, 1, 1],\n alpha: 1,\n specularColor: [1, 1, 1],\n specularPower: 64,\n emissiveColor: [0, 0, 0],\n ambientColor: [0, 0, 0],\n diffuseTexture: null,\n diffuseCoordIndex: 0,\n emissiveTexture: null,\n bumpTexture: null,\n bumpLevel: 1,\n specularTexture: null,\n specularCoordIndex: 0,\n ambientTexture: null,\n ambientTexLevel: 1,\n ambientCoordIndex: 0,\n lightmapTexture: null,\n lightmapLevel: 1,\n lightmapCoordIndex: 1,\n opacityTexture: null,\n opacityLevel: 1,\n opacityFromRGB: false,\n alphaCutOff: 0,\n reflectionTexture: null,\n reflectionCubeTexture: null,\n reflectionLevel: 1,\n reflectionCoordMode: 1,\n uvScale: [1, 1],\n backFaceCulling: true,\n disableLighting: false,\n _buildGroup: standardGroupBuilder,\n _uboVersion: 0,\n } as StandardMaterialProps;\n}\n","import type { Material, MaterialRenderFeatures, MaterialView } from \"./material.js\";\n\n/** Create a material view that references source state and overrides render features exactly. */\nexport function createMaterialView(source: Material, renderFeatures: MaterialRenderFeatures): MaterialView {\n const src = getMaterialSource(source);\n const view = Object.create(src, {\n source: { value: src, enumerable: true },\n _renderFeatures: {\n value: {\n features: renderFeatures.features,\n features2: renderFeatures.features2,\n },\n writable: true,\n enumerable: true,\n configurable: true,\n },\n }) as MaterialView;\n return view;\n}\n\nexport function isMaterialView(material: Material): material is MaterialView {\n const maybeView = material as Partial<MaterialView>;\n return !!maybeView.source && !!maybeView._renderFeatures;\n}\n\nexport function getMaterialSource(material: Material): Material {\n return isMaterialView(material) ? material.source : material;\n}\n","/** Standard material view helper with no color output.\n *\n * Kept outside standard-material.ts so ordinary Standard scenes do not retain\n * the helper.\n */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { NO_COLOR_OUTPUT } from \"./standard-flags.js\";\nimport type { StandardMaterialProps } from \"./standard-material.js\";\n\n/** Create a no-color view over a Standard source material.\n * The view references the source; material state is never copied. */\nexport function createStandardNoColorMaterialView(source: StandardMaterialProps): MaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n return createMaterialView(source, { features: features.features | NO_COLOR_OUTPUT });\n}\n","export const PBR_HAS_NORMAL_MAP = 1 << 0;\nexport const PBR_HAS_EMISSIVE = 1 << 1;\nexport const PBR_HAS_ENV = 1 << 2;\nexport const PBR_HAS_ALPHA_TEST = 1 << 3;\nexport const PBR_HAS_TONEMAP = 1 << 4;\nexport const PBR_HAS_ALPHA_BLEND = 1 << 6;\nexport const PBR_HAS_SPEC_GLOSS = 1 << 7;\nexport const PBR_HAS_DOUBLE_SIDED = 1 << 8;\nexport const PBR_HAS_COTANGENT_NORMAL = 1 << 9;\nexport const PBR_HAS_METALLIC_REFLECTANCE_MAP = 1 << 10;\nexport const PBR_HAS_REFLECTANCE_MAP = 1 << 11;\nexport const PBR_HAS_USE_ALPHA_ONLY_MR = 1 << 12;\nexport const PBR_HAS_OCCLUSION = 1 << 15;\nexport const PBR_HAS_SPECULAR_AA = 1 << 17;\nexport const PBR_HAS_CLEARCOAT = 1 << 20;\nexport const PBR_HAS_EMISSIVE_COLOR = 1 << 21;\nexport const PBR_HAS_SHEEN = 1 << 22;\nexport const PBR_HAS_SHEEN_TEXTURE = 1 << 23;\nexport const PBR_HAS_GAMMA_ALBEDO = 1 << 25;\nexport const PBR_HAS_ANISOTROPY = 1 << 26;\nexport const PBR_HAS_SUBSURFACE = 1 << 27;\nexport const PBR_HAS_THICKNESS_MAP = 1 << 28;\nexport const PBR_HAS_SKYBOX = 1 << 29;\nexport const PBR_HAS_SHEEN_ALBEDO_SCALING = 1 << 30;\n\n// ─── features2 (extended feature bits) ──────────────────────────────\n// Used when `features` runs out of bits. Threaded separately through\n// composePbr / getOrCreatePbrPipeline / createPbrMeshBindGroup.\nexport const PBR2_CC_INT_MAP = 1 << 0;\nexport const PBR2_CC_ROUGH_MAP = 1 << 1;\nexport const PBR2_CC_NORMAL_MAP = 1 << 2;\nexport const PBR2_CC_F0_REMAP_OFF = 1 << 3;\n/** Material has KHR_materials_transmission (refraction through surface). */\nexport const PBR2_HAS_REFRACTION = 1 << 4;\n/** Material has KHR_materials_volume (thickness-based Beer-Lambert absorption). */\nexport const PBR2_HAS_VOLUME = 1 << 5;\n/** Material has a transmission texture (R channel). */\nexport const PBR2_HAS_REFRACTION_MAP = 1 << 6;\n/** Thickness texture samples the G channel (KHR_materials_volume). */\nexport const PBR2_HAS_THICKNESS_GLTF_CHANNEL = 1 << 7;\n/** Material is unlit — bypass all lighting (KHR_materials_unlit). */\nexport const PBR2_HAS_UNLIT = 1 << 8;\n/** Any bound texture on this material carries a non-identity UV transform\n * (`uScale/vScale/uOffset/vOffset/uAng` on its Texture2D). Enables per-\n * texture UV-transform UBO fields + `txfUV` wrapping in the shader. */\nexport const PBR2_HAS_UV_TRANSFORM = 1 << 9;\n/** Material has non-default metallicF0Factor or metallicReflectanceColor\n * without reflectance textures (factor-only KHR_materials_specular). */\nexport const PBR2_HAS_REFLECTANCE_FACTORS = 1 << 10;\n/** Material samples occlusion from TEXCOORD_1 when the mesh provides UV2. */\nexport const PBR2_HAS_UV2 = 1 << 11;\n/** Material multiplies textured albedo by a non-default glTF baseColorFactor. */\nexport const PBR2_HAS_BASE_COLOR_FACTOR = 1 << 12;\n/** Material has a sheen texture with a KHR_texture_transform. Sheen owns its\n * own `sheenUVm`/`sheenUVt` UBO fields and applies txfUV locally. */\nexport const PBR2_HAS_SHEEN_UV_TX = 1 << 13;\n/** Material participates in the opaque-scene refraction prepass and must be authored in linear space. */\nexport const PBR2_LINEAR_IMAGE_PROCESSING = 1 << 14;\n/** Material view runs the fragment shader but declares no color output. */\nexport const PBR2_NO_COLOR_OUTPUT = 1 << 15;\n/** Material view runs discard/clip logic and writes exponential shadow-map color. */\nexport const PBR2_ESM_SHADOW_OUTPUT = 1 << 16;\n/** Material has native PBR iridescence enabled. */\nexport const PBR2_HAS_IRIDESCENCE = 1 << 17;\n/** Iridescence intensity texture (R channel). */\nexport const PBR2_HAS_IRIDESCENCE_MAP = 1 << 18;\n/** Iridescence thickness texture (G channel). */\nexport const PBR2_HAS_IRIDESCENCE_THICKNESS_MAP = 1 << 19;\n/** Material has KHR_materials_dispersion (per-channel chromatic refraction).\n * Implies PBR2_HAS_VOLUME (the extension requires KHR_materials_volume). */\nexport const PBR2_HAS_DISPERSION = 1 << 20;\n","/** PBR feature flag constants + extension registry.\n * Tiny shared module imported by both pbr-pipeline and PBR fragments. */\n\nimport type { ShaderFragment } from \"../../shader/fragment-types.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\n\nexport * from \"./pbr-flag-bits.js\";\n\n// ─── Unified PBR Extension Registry ─────────────────────────────────\n/** @internal Bind-group phase, matching composer slot layout:\n * - \"vertex\": vertex-stage bindings (morph, skeleton) — between material UBO and base textures\n * - \"base-tex\": material-phase bindings (between base textures and lightsUBO)\n * - \"ibl\": scene-env bindings (after lightsUBO, before fragment-phase exts)\n * - \"fragment\": fragment-phase bindings (after IBL, alphabetical by id) */\nexport type PbrExtPhase = \"vertex\" | \"base-tex\" | \"ibl\" | \"fragment\";\n\n/** @internal Fragment creation context threaded through `PbrExt.frag`. */\nexport interface _PbrFragCtx {\n /** @internal */\n readonly _features: number;\n /** @internal */\n readonly _features2: number;\n /** @internal Mesh feature bits, separate from material feature bits. */\n readonly _meshFeatures: number;\n /** @internal */\n readonly _hasIbl: boolean;\n /** @internal */\n readonly _hasAnyNormal: boolean;\n /** @internal */\n readonly _hasSpecularAA: boolean;\n /** @internal Aniso bent-normal WGSL (IBL only). */\n readonly _anisoBentNormalCode?: string;\n /** @internal Pre-baked skybox WGSL (IBL only). */\n readonly _iblSkyboxCalc?: string;\n}\n\n/** @internal Bind-group entry build context threaded through `PbrExt.bind`. */\nexport interface _PbrBindCtx {\n /** @internal */\n readonly _engine: import(\"../../engine/engine.js\").EngineContext;\n /** @internal */\n readonly _features: number;\n /** @internal */\n readonly _features2: number;\n /** @internal Mesh feature bits, separate from material feature bits. */\n readonly _meshFeatures: number;\n /** @internal */\n readonly _material: unknown;\n /** @internal Populated for \"vertex\" phase (skeleton, morph). */\n readonly _mesh?: { skeleton?: { boneTexture: GPUTexture } | null; morphTargets?: { texture: GPUTexture; weightsBuffer?: GPUBuffer } | null };\n /** @internal Populated for \"ibl\" phase. */\n readonly _env?: { brdfLutView: GPUTextureView; brdfSampler: GPUSampler; specularCubeView: GPUTextureView; cubeSampler: GPUSampler } | null;\n /** @internal Per-render-task scene-color snapshot for transmissive RTT refraction. */\n readonly _refractionTexture?: Texture2D | null;\n}\n\n/** @internal Unified PBR extension. All hooks optional.\n * An ext is registered once (at its dynamic-import site in pbr-renderable)\n * and invoked by the pipeline/material/renderable hot paths. Zero side\n * effects at module load — registration is explicit. */\nexport interface PbrExt {\n readonly id: string;\n readonly phase: PbrExtPhase;\n /** Contribute feature bits for a given material. Returns `{f,f2}` to OR in. */\n detect?(mat: unknown): { f: number; f2: number };\n /** Contribute a ShaderFragment (null if gated off for this variant). */\n frag?(ctx: _PbrFragCtx): ShaderFragment | null;\n /** Write this ext's slice of the material UBO. */\n writeUbo?(data: Float32Array, mat: unknown, offsets: ReadonlyMap<string, number>): void;\n /** Push group-1 bind entries starting at binding `b`; return new b. */\n bind?(ctx: _PbrBindCtx, entries: GPUBindGroupEntry[], b: number): number;\n /** Enumerate textures for acquire/release. */\n textures?(mat: unknown, out: Texture2D[]): void;\n}\n\n// Lazy-init: a module-level `new Map()` would defeat tree-shaking for any\n// consumer that imports from pbr-flags.ts without actually registering or\n// iterating extensions. See GUIDANCE.md §4 (\"Zero module-level side effects\").\nlet _pbrExts: Map<string, PbrExt> | null = null;\nlet _pbrExtsSorted: readonly PbrExt[] | null = null;\n/** @internal Register a PBR extension. Idempotent (keyed by id). */\nexport function _registerPbrExt(ext: PbrExt): void {\n (_pbrExts ??= new Map()).set(ext.id, ext);\n _pbrExtsSorted = null;\n}\n/** @internal Iterate the registered extensions. */\nexport function _getPbrExts(): ReadonlyMap<string, PbrExt> {\n return (_pbrExts ??= new Map());\n}\n/** @internal Return extensions sorted by id (alphabetical, stable within a build). Memoised. */\nexport function _getPbrExtsSorted(): readonly PbrExt[] {\n if (!_pbrExtsSorted) {\n const map = _pbrExts;\n _pbrExtsSorted = map ? Array.from(map.values()).sort((a, b) => a.id.localeCompare(b.id)) : [];\n }\n return _pbrExtsSorted;\n}\n","/** PBR Material — user-facing props + factory.\n *\n * Same role as StandardMaterialProps for the standard pipeline.\n * Users can create a PbrMaterialProps manually or let loadGltf() build one. */\n\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { MeshGroupBuilder } from \"../../render/renderable.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { Material } from \"../material.js\";\nimport {\n _getPbrExts,\n PBR2_HAS_BASE_COLOR_FACTOR,\n PBR2_HAS_UV_TRANSFORM,\n PBR2_HAS_UV2,\n PBR_HAS_ALPHA_TEST,\n PBR_HAS_ALPHA_BLEND,\n PBR_HAS_ANISOTROPY,\n PBR_HAS_DOUBLE_SIDED,\n PBR_HAS_EMISSIVE,\n PBR_HAS_EMISSIVE_COLOR,\n PBR_HAS_GAMMA_ALBEDO,\n PBR_HAS_NORMAL_MAP,\n PBR_HAS_OCCLUSION,\n PBR_HAS_SKYBOX,\n PBR_HAS_SPECULAR_AA,\n PBR_HAS_SPEC_GLOSS,\n} from \"./pbr-flags.js\";\n\n/** Lazy-imports the PBR renderable builder and builds the pipeline.\n * Thin instances are handled by the fragment composer automatically. */\nexport const pbrGroupBuilder: MeshGroupBuilder = async (scene, meshes) => {\n const envTex = (scene as SceneContext)._envTextures;\n const renderableMod = await import(\"./pbr-renderable.js\");\n const result = await renderableMod.buildPbrRenderables(scene, meshes, envTex);\n // Wire the per-mesh rebuild closure used by material swap + per-pass override.\n pbrGroupBuilder._rebuildSingle = result.rebuildSingle;\n return result;\n};\n\npbrGroupBuilder._materialFamily = \"pbr\";\n\n/** User-facing properties for a physically based (metallic-roughness) material.\n * Create one manually via `createPbrMaterial()` or let `loadGltf()` build it.\n * Optional sub-feature objects (clearcoat, sheen, anisotropy, subsurface) are\n * only bundled when referenced. */\nexport interface PbrMaterialProps extends Material {\n baseColorTexture?: Texture2D;\n /** Linear RGB/A factor multiplied with the base-color texture (glTF baseColorFactor). Default [1,1,1,1]. */\n baseColorFactor?: [number, number, number, number];\n normalTexture?: Texture2D;\n /** Normal map scale (glTF normalTexture.scale). Default 1.0. */\n normalTextureScale?: number;\n /** Occlusion-Roughness-Metallic packed: R=occ, G=rough, B=metal. */\n ormTexture?: Texture2D;\n emissiveTexture?: Texture2D;\n /** Emissive color as float uniform (linear RGB). Used when no emissiveTexture.\n * If both set, emissiveColor multiplies emissiveTexture. */\n emissiveColor?: [number, number, number];\n /** KHR_materials_pbrSpecularGlossiness: RGB=specular, A=glossiness. */\n specGlossTexture?: Texture2D;\n /** Whether material is double-sided (disables back-face culling). */\n doubleSided?: boolean;\n /** Overall material alpha (0=fully transparent, 1=opaque). Default 1.0. */\n alpha?: number;\n /** Enable alpha blending (glTF alphaMode \"BLEND\"). Enables radianceOverAlpha + specularOverAlpha. */\n alphaBlend?: boolean;\n /** Alpha test cutoff (glTF alphaMode \"MASK\"). Fragments with base alpha * material alpha below this value are discarded. */\n alphaCutOff?: number;\n /** Scale factor for environment/IBL contribution. Default 1.0. */\n environmentIntensity?: number;\n /** Scale factor for direct light contribution. Default 1.0. */\n directIntensity?: number;\n /** Whether direct point/spot lights use physical inverse-square falloff.\n * Default true, matching Babylon.js PBRMaterial. Set false for Standard-style\n * linear range + spot exponent falloff (`usePhysicalLightFalloff = false`). */\n usePhysicalLightFalloff?: boolean;\n /** Dielectric F0 reflectance (default 0.04, glass ≈ 0.2). */\n reflectance?: number;\n /** glTF metallicFactor multiplier applied over ORM.b metallic channel. Default 1.0. */\n metallicFactor?: number;\n /** glTF roughnessFactor multiplier applied over ORM.g roughness channel. Default 1.0. */\n roughnessFactor?: number;\n /** Strength of ambient occlusion from ORM R channel. Default 1.0; 0.0 ignores R channel. */\n occlusionStrength?: number;\n /** UV set index for the occlusion texture (0 = UV1, 1 = UV2). Default 0. */\n occlusionTexCoord?: number;\n /** Separate occlusion texture sampled with UV2 when occlusionTexCoord=1.\n * R channel is occlusion. When set, ORM.r is NOT used for occlusion. */\n occlusionTexture?: Texture2D;\n /** Scales dielectric F0 (default 1.0). Maps to BJS metallicF0Factor. */\n metallicF0Factor?: number;\n /** Grazing specular/F90 weight (default follows metallicF0Factor for legacy callers). */\n specularWeight?: number;\n /** Tints dielectric reflectance (linear RGB, default [1,1,1]). Maps to BJS metallicReflectanceColor. */\n metallicReflectanceColor?: [number, number, number];\n /** Texture whose RGB tints reflectance and A scales F0. Maps to BJS metallicReflectanceTexture. */\n metallicReflectanceTexture?: Texture2D;\n /** Texture whose RGB tints reflectance only. Maps to BJS reflectanceTexture. */\n reflectanceTexture?: Texture2D;\n /** When true + both reflectance textures set, metallicReflectanceTexture only contributes A (F0 scalar). */\n useOnlyMetallicFromMetallicReflectanceTexture?: boolean;\n /** Enable specular anti-aliasing on IBL alphaG (matches BJS SPECULARAA). Default false.\n * Set automatically by the glTF loader for materials loaded from glTF files. */\n enableSpecularAA?: boolean;\n /** Clearcoat layer configuration. When set with isEnabled=true, adds a glossy transparent\n * top layer (like car paint or lacquer). Tree-shakable — only bundled when used. */\n clearCoat?: ClearCoatProps;\n /** Sheen layer configuration. When set with isEnabled=true, adds a soft velvet-like\n * sheen layer (like fabric or cloth). Tree-shakable — only bundled when used. */\n sheen?: SheenProps;\n /** Iridescence thin-film configuration. When set with isEnabled=true, replaces\n * base-layer F0 with a wavelength-dependent thin-film Fresnel blend.\n * Maps to BJS PBRMaterial.iridescence and KHR_materials_iridescence.\n * Tree-shakable — only bundled when used. */\n iridescence?: IridescenceProps;\n /** When true, the albedo texture is in sRGB/gamma space (loaded as rgba8unorm)\n * and the shader applies pow(baseColor, 2.2) for sRGB→linear conversion.\n * Matches BJS PBRMaterial's Texture.gammaSpace=true behavior.\n * When false (default), assumes the texture already provides linear values\n * (e.g. rgba8unorm-srgb format or glTF sRGB textures). */\n gammaAlbedo?: boolean;\n /** Anisotropy layer configuration. When set with isEnabled=true, stretches specular\n * highlights along a preferred direction. Tree-shakable — only bundled when used. */\n anisotropy?: AnisotropyProps;\n /** Subsurface configuration. Presence of nested sub-features (translucency, scattering)\n * enables them — no isEnabled booleans needed. Tree-shakable — only bundled when used. */\n subsurface?: SubSurfaceProps;\n /** True transmissive surface: render task provides a scene-color refraction texture\n * just before this material draws. Set by KHR_materials_transmission. */\n transmissive?: boolean;\n /** When true, the material samples the environment cubemap using the view direction\n * (camera→fragment) instead of the reflected view direction. Used for PBR skybox boxes\n * where the mesh surrounds the camera and should display the environment directly.\n * Also zeroes SH irradiance — skybox is pure cubemap + BRDF only. */\n skyboxMode?: boolean;\n /** When true, the material is unlit — the base color is output directly,\n * bypassing all lighting, IBL, tonemap, and shading calculations.\n * Matches `KHR_materials_unlit` glTF extension. Alpha handling is preserved. */\n unlit?: boolean;\n /** Linear-RGB tint applied to baseColor when `unlit` is true (i.e. glTF\n * `baseColorFactor`). When omitted or [1,1,1], no tint is applied.\n * Only bundled/bound when the unlit extension is active. */\n unlitColor?: [number, number, number];\n /** @internal True when any of the material's textures carries `_hasTx=true`\n * (KHR_texture_transform). Stamped once by the glTF loader's slow path\n * so the renderer doesn't re-scan 5 textures per mesh. */\n _hasUvTx?: boolean;\n}\n\n/** @internal Compute PBR material-only feature bits. Mesh/pass bits are added per renderable. */\nexport function _computePbrMaterialFeatures(mat: PbrMaterialProps): { features: number; features2: number } {\n let features =\n (mat.emissiveTexture ? PBR_HAS_EMISSIVE : 0) |\n (mat.emissiveColor ? PBR_HAS_EMISSIVE_COLOR : 0) |\n (mat.normalTexture ? PBR_HAS_NORMAL_MAP : 0) |\n ((mat.alphaCutOff ?? 0) > 0 ? PBR_HAS_ALPHA_TEST : 0) |\n (mat.alphaBlend === true || ((mat.alphaCutOff ?? 0) <= 0 && mat.alpha! < 1) ? PBR_HAS_ALPHA_BLEND : 0) |\n (mat.specGlossTexture ? PBR_HAS_SPEC_GLOSS : 0) |\n (mat.doubleSided ? PBR_HAS_DOUBLE_SIDED : 0);\n if ((mat.occlusionStrength ?? 1.0) > 0) {\n features |= PBR_HAS_OCCLUSION;\n }\n if (mat.enableSpecularAA) {\n features |= PBR_HAS_SPECULAR_AA;\n }\n if (mat.gammaAlbedo) {\n features |= PBR_HAS_GAMMA_ALBEDO;\n }\n if (mat.anisotropy?.isEnabled) {\n features |= PBR_HAS_ANISOTROPY;\n }\n if (mat.skyboxMode) {\n features |= PBR_HAS_SKYBOX;\n }\n\n let features2 = 0;\n for (const ext of _getPbrExts().values()) {\n if (ext.detect) {\n const d = ext.detect(mat);\n features |= d.f;\n features2 |= d.f2;\n }\n }\n if ((mat as { _hasUvTx?: boolean })._hasUvTx) {\n features2 |= PBR2_HAS_UV_TRANSFORM;\n }\n if (mat.occlusionTexCoord) {\n features2 |= PBR2_HAS_UV2;\n }\n if (mat.baseColorFactor) {\n features2 |= PBR2_HAS_BASE_COLOR_FACTOR;\n }\n return { features, features2 };\n}\n\n/** Clearcoat layer properties. Maps to BJS PBRMaterial.clearCoat sub-object. */\nexport interface ClearCoatProps {\n /** Whether clearcoat is active. Default false. */\n isEnabled?: boolean;\n /** Clearcoat layer intensity (0=off, 1=full). Default 1.0. */\n intensity?: number;\n /** Clearcoat layer roughness. Default 0.0 (perfectly smooth). */\n roughness?: number;\n /** Index of refraction of the clearcoat layer. Default 1.5. */\n indexOfRefraction?: number;\n /** Optional clearcoat intensity texture (R channel). Multiplies `intensity`. */\n texture?: Texture2D;\n /** Optional clearcoat roughness texture (G channel). Multiplies `roughness`. */\n roughnessTexture?: Texture2D;\n /** Optional clearcoat normal map (tangent-space). Used to perturb the coat\n * layer normal independently of the base layer. */\n bumpTexture?: Texture2D;\n /** Clearcoat normal texture scale (glTF normalTexture.scale). Default 1.0. */\n bumpTextureScale?: number;\n /** Whether to remap base F0 across the clearcoat interface (CLEARCOAT_REMAP_F0).\n * Matches BJS PBRClearCoatConfiguration.remapF0OnInterfaceChange.\n * Default true. glTF loader sets this to false per KHR_materials_clearcoat. */\n useF0Remap?: boolean;\n}\n\n/** Sheen layer properties. Maps to BJS PBRMaterial.sheen sub-object. */\nexport interface SheenProps {\n /** Whether sheen is active. Default false. */\n isEnabled: boolean;\n /** Sheen color (linear RGB). Default [1, 1, 1]. */\n color?: [number, number, number];\n /** Sheen roughness. Default 0.0. */\n roughness?: number;\n /** Sheen intensity (0=off, 1=full). Default 1.0. */\n intensity?: number;\n /** Optional sheen tint texture (modulates sheen color). Loaded via loadTexture2D(). */\n texture?: Texture2D;\n /** When true (recommended for glTF), applies proper sheen albedo scaling\n * on the base layer and treats the sheen texture as already-linear (no pow).\n * When false (default, legacy), applies pow(rgb, 2.2) to the sheen texture\n * and uses a (1-F0) attenuation on the sheen lobe without base-layer scaling. */\n albedoScaling?: boolean;\n}\n\n/** Iridescence thin-film properties. Maps to BJS PBRMaterial.iridescence and KHR_materials_iridescence. */\nexport interface IridescenceProps {\n /** Whether iridescence is active. Default false. */\n isEnabled?: boolean;\n /** Iridescence blend intensity (0=off, 1=full). Default 1.0 for native PBR; glTF default is supplied by the loader. */\n intensity?: number;\n /** Thin-film index of refraction. Default 1.3. */\n indexOfRefraction?: number;\n /** Minimum film thickness in nanometres. Default 100. */\n minimumThickness?: number;\n /** Maximum film thickness in nanometres. Default 400. */\n maximumThickness?: number;\n /** Optional intensity texture; R channel multiplies intensity. */\n texture?: Texture2D;\n /** Optional thickness texture; G channel lerps minimum→maximum thickness. */\n thicknessTexture?: Texture2D;\n}\n\n/** Anisotropy layer properties. Maps to BJS PBRMaterial.anisotropy sub-object.\n * Stretches specular reflections along the tangent direction. */\nexport interface AnisotropyProps {\n /** Whether anisotropy is active. Default false. */\n isEnabled: boolean;\n /** Anisotropy strength (0=isotropic, 1=fully anisotropic). Default 1.0. */\n intensity?: number;\n /** Anisotropy direction in tangent space (u, v). Default [1, 0]. */\n direction?: [number, number];\n}\n\n/** Translucency sub-feature. Presence enables translucency (no isEnabled boolean). */\nexport interface TranslucencyProps {\n /** Translucency intensity (0=off, 1=full). Default 1.0. */\n intensity?: number;\n /** Translucency color (linear RGB). Tints the transmitted light. Default [1,1,1]. */\n color?: [number, number, number];\n /** Diffusion distance for the Burley transmittance BRDF. Controls how far\n * light travels through the material per RGB channel. Default [1,1,1]. */\n diffusionDistance?: [number, number, number];\n}\n\n/** Scattering sub-feature. Presence enables screen-space subsurface scattering.\n * NOTE: PrePass/SSS pipeline is not yet implemented — this type is reserved. */\nexport interface ScatteringProps {\n /** Per-channel scattering diffusion distance. */\n diffusionDistance?: [number, number, number];\n /** World-space scale factor for the diffusion kernel. Default 1.0. */\n metersPerUnit?: number;\n}\n\n/** Thickness sub-feature. Controls how thick the material is at each point. */\nexport interface ThicknessProps {\n /** Thickness map texture. R channel is sampled by default (matches\n * existing BJS non-glTF path). Set `useGlTFChannel=true` for G-channel\n * sampling as specified by KHR_materials_volume. */\n texture?: Texture2D;\n /** When true, sample the thickness texture's G channel (KHR_materials_volume).\n * Default false — samples R channel (BJS default). Set by the glTF loader. */\n useGlTFChannel?: boolean;\n /** Minimum thickness. Default 0. */\n min?: number;\n /** Maximum thickness. Default 1.0. */\n max?: number;\n}\n\n/** Refraction sub-feature (KHR_materials_transmission + _volume + _ior).\n * Presence enables frame-graph scene-texture transmission. */\nexport interface RefractionProps {\n /** Transmission factor (0=off, 1=fully transmissive). Default 0.\n * Maps to KHR_materials_transmission.transmissionFactor. */\n intensity?: number;\n /** Optional transmission texture (R channel). Multiplies `intensity`. */\n texture?: Texture2D;\n /** Index of refraction (KHR_materials_ior.ior). Default 1.5 (glass). */\n indexOfRefraction?: number;\n /** When true, the thickness value is also used as the refracted\n * sample offset depth (KHR_materials_volume — matches BJS\n * `useThicknessAsDepth`). Default true when volume is present. */\n useThicknessAsDepth?: boolean;\n /** Chromatic dispersion strength (KHR_materials_dispersion.dispersion).\n * Splits the refracted ray into per-RGB index-of-refraction offsets,\n * producing chromatic aberration. Requires volume. Default 0 (off). */\n dispersion?: number;\n}\n\n/** Tint sub-feature. Controls absorption tint color for transmittance. */\nexport interface TintProps {\n /** Tint color (linear RGB). Default [1,1,1]. */\n color?: [number, number, number];\n /** Distance at which the tint color is reached. Default 1.0. */\n atDistance?: number;\n}\n\n/** Subsurface configuration. Nested sub-features — presence = enabled. */\nexport interface SubSurfaceProps {\n /** Translucency: light passing through thin surfaces. */\n translucency?: TranslucencyProps;\n /** Scattering: screen-space subsurface scattering (PrePass). Reserved — not yet implemented. */\n scattering?: ScatteringProps;\n /** Thickness: per-texel thickness for transmittance. */\n thickness?: ThicknessProps;\n /** Tint: absorption tint color for transmittance. */\n tint?: TintProps;\n /** Refraction: physical light transmission through the surface\n * (KHR_materials_transmission + _volume + _ior). Presence enables it.\n * Requires the frame graph to produce a transmission refraction texture. */\n refraction?: RefractionProps;\n}\n\n/** Create a PbrMaterialProps with optional overrides. */\nexport function createPbrMaterial(props?: Partial<PbrMaterialProps>): PbrMaterialProps {\n const mat = {\n ...props,\n _buildGroup: pbrGroupBuilder,\n _uboVersion: 0,\n } as PbrMaterialProps;\n return mat;\n}\n\n/** Collect all non-null textures referenced by a PBR material (for acquire/release). */\nexport function collectPbrBoundTextures(mat: PbrMaterialProps): Texture2D[] {\n const t: Texture2D[] = [];\n if (mat.baseColorTexture) {\n t.push(mat.baseColorTexture);\n }\n if (mat.normalTexture) {\n t.push(mat.normalTexture);\n }\n if (mat.ormTexture) {\n t.push(mat.ormTexture);\n }\n if (mat.occlusionTexture) {\n t.push(mat.occlusionTexture);\n }\n if (mat.emissiveTexture) {\n t.push(mat.emissiveTexture);\n }\n if (mat.specGlossTexture) {\n t.push(mat.specGlossTexture);\n }\n for (const ext of _getPbrExts().values()) {\n ext.textures?.(mat, t);\n }\n return t;\n}\n","import type { MeshGroupBuilder } from \"../../render/renderable.js\";\n\nexport const shaderGroupBuilder: MeshGroupBuilder = async (scene, meshes) => {\n const { buildShaderMaterialRenderables } = await import(\"./shader-renderable.js\");\n const result = buildShaderMaterialRenderables(scene, meshes);\n shaderGroupBuilder._rebuildSingle = result.rebuildSingle;\n return result;\n};\n","import type { Material } from \"../material.js\";\nimport type { MeshGroupBuilder } from \"../../render/renderable.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport { shaderGroupBuilder } from \"./shader-group-builder.js\";\n\n/** Vertex attribute names a ShaderMaterial can bind. */\nexport type ShaderAttributeName = \"position\" | \"normal\" | \"uv\" | \"uv2\" | \"tangent\" | \"color\";\n/** WGSL scalar/vector/matrix types supported for ShaderMaterial uniforms. */\nexport type ShaderUniformType = \"f32\" | \"u32\" | \"i32\" | \"vec2<f32>\" | \"vec3<f32>\" | \"vec4<f32>\" | \"mat4x4<f32>\";\n/** Built-in uniform names automatically populated by the renderer each frame\n * (transforms, camera position, screen size, alpha cutoff). */\nexport type ShaderSystemUniformName = \"world\" | \"view\" | \"projection\" | \"viewProjection\" | \"worldView\" | \"worldViewProjection\" | \"cameraPosition\" | \"screenSize\" | \"alphaCutoff\";\n/** A uniform entry: either a system uniform name or an explicit custom declaration. */\nexport type ShaderUniformOption = ShaderSystemUniformName | ShaderUniformDecl;\n/** Accepted value shape when setting a ShaderMaterial uniform. */\nexport type ShaderUniformValue = number | readonly number[] | Float32Array;\n/** A sampler entry: either a bare sampler name or an explicit declaration. */\nexport type ShaderSamplerOption = string | ShaderSamplerDecl;\n/** Value of a WGSL preprocessor define — boolean toggle or numeric constant. */\nexport type ShaderDefineValue = boolean | number;\n/** Map of WGSL preprocessor define names to their values. */\nexport type ShaderDefineMap = Readonly<Record<string, ShaderDefineValue>>;\n\n/** Options describing a ShaderMaterial: WGSL sources, attributes, uniforms,\n * samplers, defines, and blend/depth state. Passed to `createShaderMaterial()`. */\nexport interface ShaderMaterialOptions {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniforms?: readonly ShaderUniformOption[];\n readonly samplers?: readonly ShaderSamplerOption[];\n readonly defines?: ShaderDefineMap;\n readonly needAlphaBlending?: boolean;\n /** Blend equation used when `needAlphaBlending` is set. \"alpha\" (default) is\n * standard src-over; \"additive\" adds the fragment's premultiplied-by-alpha\n * color to the framebuffer, which is the right choice for glows/light FX. */\n readonly blendMode?: \"alpha\" | \"additive\";\n readonly needAlphaTesting?: boolean;\n readonly backFaceCulling?: boolean;\n readonly depthWrite?: boolean;\n readonly depthCompare?: GPUCompareFunction;\n}\n\n/** A custom uniform declaration: WGSL identifier, type, and optional default. */\nexport interface ShaderUniformDecl {\n readonly name: string;\n readonly type: ShaderUniformType;\n readonly defaultValue?: number | readonly number[];\n}\n\n/** A sampler declaration: WGSL identifier and the bound texture's sample type. */\nexport interface ShaderSamplerDecl {\n readonly name: string;\n readonly sampleType?: \"float\" | \"unfilterable-float\" | \"depth\";\n}\n\n/** A resolved WGSL preprocessor define (name + value). */\nexport interface ShaderDefine {\n readonly name: string;\n readonly value: ShaderDefineValue;\n}\n\nexport interface ShaderUniformSlot {\n readonly decl: ShaderUniformDecl;\n readonly value: Float32Array;\n}\n\nexport interface ShaderTextureSlot {\n readonly decl: ShaderSamplerDecl;\n current: Texture2D | null;\n}\n\n/** A custom WGSL material: compiled from user-supplied vertex/fragment sources\n * with declared attributes, uniforms, samplers, and defines. Update its values\n * via `setShaderUniform()` / `setShaderTexture()` and friends. */\nexport interface ShaderMaterial extends Material {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniformDecls: readonly ShaderUniformDecl[];\n readonly samplerDecls: readonly ShaderSamplerDecl[];\n readonly defines: readonly ShaderDefine[];\n readonly needAlphaBlending: boolean;\n readonly blendMode: \"alpha\" | \"additive\";\n readonly needAlphaTesting: boolean;\n readonly backFaceCulling: boolean;\n readonly depthWrite: boolean;\n readonly depthCompare: GPUCompareFunction;\n /** @internal */\n _uniformValues: Map<string, ShaderUniformSlot>;\n /** @internal */\n _textureSlots: Map<string, ShaderTextureSlot>;\n /** @internal */\n _uniformVersion: number;\n /** @internal */\n _resourceVersion: number;\n}\n\nfunction isIdentifier(name: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);\n}\n\nfunction assertIdentifier(kind: string, name: string): void {\n if (!isIdentifier(name)) {\n throw new Error(`ShaderMaterial: ${kind} name \"${name}\" is not a valid WGSL identifier.`);\n }\n}\n\nfunction isSupportedAttribute(name: string): name is ShaderAttributeName {\n return name === \"position\" || name === \"normal\" || name === \"uv\" || name === \"uv2\" || name === \"tangent\" || name === \"color\";\n}\n\nfunction isSystemUniform(name: string): name is ShaderSystemUniformName {\n return (\n name === \"world\" ||\n name === \"view\" ||\n name === \"projection\" ||\n name === \"viewProjection\" ||\n name === \"worldView\" ||\n name === \"worldViewProjection\" ||\n name === \"cameraPosition\" ||\n name === \"screenSize\" ||\n name === \"alphaCutoff\"\n );\n}\n\nfunction systemUniformType(name: ShaderSystemUniformName): ShaderUniformType {\n if (name === \"cameraPosition\") {\n return \"vec3<f32>\";\n }\n if (name === \"screenSize\") {\n return \"vec2<f32>\";\n }\n if (name === \"alphaCutoff\") {\n return \"f32\";\n }\n return \"mat4x4<f32>\";\n}\n\nexport function _isShaderSystemUniform(name: string): name is ShaderSystemUniformName {\n return isSystemUniform(name);\n}\n\n/** Create a ShaderMaterial from WGSL sources and declarations, validating\n * attributes, uniforms, samplers, and defines.\n * @param options - Sources, attributes, uniforms, samplers, defines, and render state.\n * @returns The constructed `ShaderMaterial`. */\nexport function createShaderMaterial(options: ShaderMaterialOptions): ShaderMaterial {\n if (!options.vertexSource || !options.fragmentSource) {\n throw new Error(\"ShaderMaterial: vertexSource and fragmentSource must be non-empty WGSL strings.\");\n }\n const attributes: ShaderAttributeName[] = [];\n const seenAttributes = new Set<string>();\n for (const attr of options.attributes) {\n if (!isSupportedAttribute(attr)) {\n throw new Error(`ShaderMaterial: unsupported attribute \"${String(attr)}\". Supported attributes: position, normal, uv, uv2, tangent, color.`);\n }\n if (seenAttributes.has(attr)) {\n throw new Error(`ShaderMaterial: duplicate attribute \"${attr}\".`);\n }\n seenAttributes.add(attr);\n attributes.push(attr);\n }\n if (!seenAttributes.has(\"position\")) {\n throw new Error('ShaderMaterial: \"position\" attribute is required for mesh rendering.');\n }\n\n const uniformDecls: ShaderUniformDecl[] = [];\n const uniformValues = new Map<string, ShaderUniformSlot>();\n const usedNames = new Set<string>();\n for (const opt of options.uniforms ?? []) {\n const decl = typeof opt === \"string\" ? normalizeSystemUniform(opt) : normalizeCustomUniform(opt);\n assertUniqueName(usedNames, \"uniform\", decl.name);\n uniformDecls.push(decl);\n uniformValues.set(decl.name, { decl, value: normalizeUniformValue(decl, decl.defaultValue ?? defaultUniformValue(decl)) });\n }\n\n const samplerDecls: ShaderSamplerDecl[] = [];\n const textureSlots = new Map<string, ShaderTextureSlot>();\n for (const opt of options.samplers ?? []) {\n const decl = typeof opt === \"string\" ? { name: opt, sampleType: \"float\" as const } : { name: opt.name, sampleType: opt.sampleType ?? \"float\" };\n assertIdentifier(\"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", `${decl.name}Sampler`);\n samplerDecls.push(decl);\n textureSlots.set(decl.name, { decl, current: null });\n }\n\n const defines: ShaderDefine[] = [];\n for (const [name, value] of Object.entries(options.defines ?? {})) {\n assertIdentifier(\"define\", name);\n assertUniqueName(usedNames, \"define\", name);\n if (typeof value !== \"boolean\" && typeof value !== \"number\") {\n throw new Error(`ShaderMaterial: define \"${name}\" must be a boolean or number.`);\n }\n defines.push({ name, value });\n }\n defines.sort((a, b) => a.name.localeCompare(b.name));\n\n return {\n name: options.name,\n vertexSource: options.vertexSource,\n fragmentSource: options.fragmentSource,\n attributes,\n uniformDecls,\n samplerDecls,\n defines,\n needAlphaBlending: options.needAlphaBlending ?? false,\n blendMode: options.blendMode ?? \"alpha\",\n needAlphaTesting: options.needAlphaTesting ?? false,\n backFaceCulling: options.backFaceCulling ?? true,\n depthWrite: options.depthWrite ?? true,\n depthCompare: options.depthCompare ?? \"greater-equal\",\n _buildGroup: shaderGroupBuilder as MeshGroupBuilder,\n _uboVersion: 0,\n _uniformValues: uniformValues,\n _textureSlots: textureSlots,\n _uniformVersion: 0,\n _resourceVersion: 0,\n };\n}\n\nfunction normalizeSystemUniform(name: string): ShaderUniformDecl {\n if (!isSystemUniform(name)) {\n throw new Error(`ShaderMaterial: custom uniform \"${name}\" must use an explicit typed declaration.`);\n }\n return { name, type: systemUniformType(name) };\n}\n\nfunction normalizeCustomUniform(decl: ShaderUniformDecl): ShaderUniformDecl {\n assertIdentifier(\"uniform\", decl.name);\n if (!isUniformType(decl.type)) {\n throw new Error(`ShaderMaterial: unsupported uniform type \"${String(decl.type)}\" for \"${decl.name}\".`);\n }\n return decl;\n}\n\nfunction isUniformType(type: string): type is ShaderUniformType {\n return type === \"f32\" || type === \"u32\" || type === \"i32\" || type === \"vec2<f32>\" || type === \"vec3<f32>\" || type === \"vec4<f32>\" || type === \"mat4x4<f32>\";\n}\n\nfunction assertUniqueName(usedNames: Set<string>, kind: string, name: string): void {\n if (usedNames.has(name)) {\n throw new Error(`ShaderMaterial: duplicate generated identifier \"${name}\" while adding ${kind}.`);\n }\n usedNames.add(name);\n}\n\nfunction elementCount(type: ShaderUniformType): number {\n switch (type) {\n case \"f32\":\n case \"u32\":\n case \"i32\":\n return 1;\n case \"vec2<f32>\":\n return 2;\n case \"vec3<f32>\":\n return 3;\n case \"vec4<f32>\":\n return 4;\n case \"mat4x4<f32>\":\n return 16;\n }\n}\n\nfunction defaultUniformValue(decl: ShaderUniformDecl): ShaderUniformValue {\n if (decl.name === \"alphaCutoff\") {\n return 0.4;\n }\n const count = elementCount(decl.type);\n return count === 1 ? 0 : new Array(count).fill(0);\n}\n\nfunction normalizeUniformValue(decl: ShaderUniformDecl, value: ShaderUniformValue): Float32Array {\n const count = elementCount(decl.type);\n const arr = typeof value === \"number\" ? new Float32Array([value]) : value instanceof Float32Array ? new Float32Array(value) : new Float32Array(value);\n if (arr.length !== count) {\n throw new Error(`ShaderMaterial: uniform \"${decl.name}\" of type ${decl.type} expects ${count} value(s), got ${arr.length}.`);\n }\n return arr;\n}\n\n/** Set a declared uniform's value, validating its element count against the\n * declared type and bumping the material's UBO version.\n * @param material - Target material.\n * @param name - Declared uniform name.\n * @param value - New value (scalar, array, or `Float32Array`). */\nexport function setShaderUniform(material: ShaderMaterial, name: string, value: ShaderUniformValue): void {\n const slot = material._uniformValues.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: uniform \"${name}\" was not declared.`);\n }\n slot.value.set(normalizeUniformValue(slot.decl, value));\n material._uniformVersion++;\n material._uboVersion = material._uniformVersion;\n}\n\n/** Bind (or clear) the texture for a declared sampler, enforcing that depth and\n * non-depth samplers receive a matching `Texture2D`.\n * @param material - Target material.\n * @param name - Declared sampler name.\n * @param texture - Texture to bind, or `null` to clear. */\nexport function setShaderTexture(material: ShaderMaterial, name: string, texture: Texture2D | null): void {\n const slot = material._textureSlots.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" was not declared.`);\n }\n if (texture) {\n const expectsDepth = slot.decl.sampleType === \"depth\";\n const isDepthTexture = texture._sampleType === \"depth\";\n if (expectsDepth && !isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" expects a depth Texture2D.`);\n }\n if (!expectsDepth && isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" cannot use a depth Texture2D.`);\n }\n }\n slot.current = texture;\n material._resourceVersion++;\n}\n\n/** Set a declared `f32` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderFloat(material: ShaderMaterial, name: string, value: number): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `vec3<f32>` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderVector3(material: ShaderMaterial, name: string, value: readonly [number, number, number]): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `mat4x4<f32>` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderMatrix(material: ShaderMaterial, name: string, value: Float32Array): void {\n setShaderUniform(material, name, value);\n}\n","import type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { ShaderMaterial, ShaderUniformOption, ShaderSamplerOption } from \"../shader/shader-material.js\";\nimport { createShaderMaterial, setShaderTexture } from \"../shader/shader-material.js\";\n\n/** A 3-component color/vector expressed as a readonly tuple. */\nexport type GridVec3 = readonly [number, number, number];\n\n/**\n * Options for {@link createGridMaterial}. Mirrors Babylon.js `GridMaterial`:\n * an unlit, procedural object-space grid. All fields are optional and fall back\n * to the Babylon defaults.\n */\nexport interface GridMaterialOptions {\n readonly name?: string;\n /** Background color between the lines. Default black `[0,0,0]`. */\n readonly mainColor?: GridVec3;\n /** Color of the grid lines. Default teal `[0,0.5,0.5]`. */\n readonly lineColor?: GridVec3;\n /** Spacing of the grid in object-space units. Default `1`. */\n readonly gridRatio?: number;\n /** Object-space offset added before computing the grid. Default `[0,0,0]`. */\n readonly gridOffset?: GridVec3;\n /** Every Nth line is a major line. Rounded with `Math.round`. Default `10`. */\n readonly majorUnitFrequency?: number;\n /** Visibility of the minor (non-major) lines, `0..1`. Default `0.33`. */\n readonly minorUnitVisibility?: number;\n /** Opacity of the grid outside of the lines. `<1` enables the transparent path. Default `1`. */\n readonly opacity?: number;\n /** Cosine-based antialiasing of the lines. Default `true`. */\n readonly antialias?: boolean;\n /** Premultiply rgb by alpha (transparent path only). Default `false`. */\n readonly preMultiplyAlpha?: boolean;\n /** Combine axes with `max` instead of additive sum. Default `false`. */\n readonly useMaxLine?: boolean;\n /** Optional opacity texture; its `.a` channel multiplies the final opacity. */\n readonly opacityTexture?: Texture2D;\n /** Per-material visibility multiplier applied to the final alpha. Default `1`. */\n readonly visibility?: number;\n /** Cull back faces. Default `true`. */\n readonly backFaceCulling?: boolean;\n}\n\n/** Build the VertexOutput struct shared by the vertex and fragment stages. */\nfunction buildVertexOutputStruct(hasOpacity: boolean): string {\n return `struct VertexOutput{@builtin(position) position:vec4<f32>,@location(0) vPosition:vec3<f32>,@location(1) vNormal:vec3<f32>,${\n hasOpacity ? \"@location(2) vUv:vec2<f32>,\" : \"\"\n }};`;\n}\n\nfunction buildVertexSource(hasOpacity: boolean): string {\n return `${buildVertexOutputStruct(hasOpacity)}\n@vertex fn mainVertex(input:VertexInput)->VertexOutput{var out:VertexOutput;out.position=shaderSystem.projection*(shaderSystem.view*(shaderSystem.world*vec4<f32>(input.position,1.0)));out.vPosition=input.position;out.vNormal=input.normal;${\n hasOpacity ? \"out.vUv=input.uv;\" : \"\"\n }return out;}`;\n}\n\nfunction buildFragmentSource(opts: { antialias: boolean; useMaxLine: boolean; transparent: boolean; preMultiplyAlpha: boolean; hasOpacity: boolean }): string {\n const onLine = opts.antialias ? \"fr=clamp(fr,-1.0,1.0);return 0.5+0.5*cos(fr*PI);\" : \"if(abs(fr)<SQRT2/4.0){return 1.0;}return 0.0;\";\n const grid = opts.useMaxLine ? \"let grid=clamp(max(max(x,y),z),0.0,1.0);\" : \"let grid=clamp(x+y+z,0.0,1.0);\";\n const transparent = opts.transparent ? \"opacity=clamp(grid,0.08,shaderUniforms.gridControl.w*grid);\" : \"\";\n const opacityTex = opts.hasOpacity ? \"opacity=opacity*textureSample(opacitySampler,opacitySamplerSampler,input.vUv).a;\" : \"\";\n const premultiply = opts.transparent && opts.preMultiplyAlpha ? \"rgb=rgb*opacity;\" : \"\";\n return `${buildVertexOutputStruct(opts.hasOpacity)}\nconst SQRT2:f32=1.41421356;\nconst PI:f32=3.14159;\nfn gridDynamicVisibility(position:f32)->f32{let f=shaderUniforms.gridControl.y;if(floor(position+0.5)==floor(position/f+0.5)*f){return 1.0;}return shaderUniforms.gridControl.z;}\nfn gridAniso(d:f32)->f32{return clamp(1.0/(d+1.0)-1.0/10.0,0.0,1.0);}\nfn gridIsOnLine(position:f32,d:f32)->f32{var fr=position-floor(position+0.5);fr=fr/d;${onLine}}\nfn gridContrib(position:f32)->f32{var d=length(vec2<f32>(dpdx(position),dpdy(position)));d=d*SQRT2;var r=gridIsOnLine(position,d);r=r*gridDynamicVisibility(position);r=r*gridAniso(d);return r;}\nfn gridNormalImpact(x:f32)->f32{return clamp(1.0-3.0*abs(x*x*x),0.0,1.0);}\n@fragment fn mainFragment(input:VertexOutput)->@location(0) vec4<f32>{let gridRatio=shaderUniforms.gridControl.x;let gridPos=(input.vPosition+shaderUniforms.gridOffset)/gridRatio;var x=gridContrib(gridPos.x);var y=gridContrib(gridPos.y);var z=gridContrib(gridPos.z);let n=normalize(input.vNormal);x=x*gridNormalImpact(n.x);y=y*gridNormalImpact(n.y);z=z*gridNormalImpact(n.z);${grid}var rgb=mix(shaderUniforms.mainColor,shaderUniforms.lineColor,vec3<f32>(grid));var opacity=1.0;${transparent}${opacityTex}${premultiply}return vec4<f32>(rgb,opacity*shaderUniforms.visibility);}`;\n}\n\n/**\n * Create a Babylon.js-equivalent `GridMaterial`: an unlit, procedural object-space\n * grid built on top of {@link createShaderMaterial}. The grid math runs entirely in\n * object space — the vertex stage forwards object-space position and normal, and the\n * fragment stage derives per-axis line contributions weighted by the normal.\n *\n * @param options - Grid appearance and blend options.\n * @returns A configured {@link ShaderMaterial}.\n */\nexport function createGridMaterial(options: GridMaterialOptions = {}): ShaderMaterial {\n const mainColor = options.mainColor ?? [0, 0, 0];\n const lineColor = options.lineColor ?? [0, 0.5, 0.5];\n const gridRatio = options.gridRatio ?? 1;\n const gridOffset = options.gridOffset ?? [0, 0, 0];\n const majorUnitFrequency = options.majorUnitFrequency ?? 10;\n const minorUnitVisibility = options.minorUnitVisibility ?? 0.33;\n const opacity = options.opacity ?? 1;\n const antialias = options.antialias ?? true;\n const preMultiplyAlpha = options.preMultiplyAlpha ?? false;\n const useMaxLine = options.useMaxLine ?? false;\n const visibility = options.visibility ?? 1;\n const backFaceCulling = options.backFaceCulling ?? true;\n const opacityTexture = options.opacityTexture;\n const hasOpacity = !!opacityTexture;\n const transparent = opacity < 1;\n\n // gridControl = (gridRatio, round(majorUnitFrequency), minorUnitVisibility, opacity).\n const gridControl = [gridRatio, Math.round(majorUnitFrequency), minorUnitVisibility, opacity];\n\n const uniforms: ShaderUniformOption[] = [\n \"world\",\n \"view\",\n \"projection\",\n { name: \"gridControl\", type: \"vec4<f32>\", defaultValue: gridControl },\n { name: \"mainColor\", type: \"vec3<f32>\", defaultValue: mainColor },\n { name: \"lineColor\", type: \"vec3<f32>\", defaultValue: lineColor },\n { name: \"gridOffset\", type: \"vec3<f32>\", defaultValue: gridOffset },\n { name: \"visibility\", type: \"f32\", defaultValue: visibility },\n ];\n const samplers: ShaderSamplerOption[] = hasOpacity ? [\"opacitySampler\"] : [];\n\n const material = createShaderMaterial({\n name: options.name ?? \"GridMaterial\",\n vertexSource: buildVertexSource(hasOpacity),\n fragmentSource: buildFragmentSource({ antialias, useMaxLine, transparent, preMultiplyAlpha, hasOpacity }),\n attributes: hasOpacity ? [\"position\", \"normal\", \"uv\"] : [\"position\", \"normal\"],\n uniforms,\n samplers,\n needAlphaBlending: transparent || hasOpacity,\n blendMode: \"alpha\",\n backFaceCulling,\n });\n\n if (opacityTexture) {\n setShaderTexture(material, \"opacitySampler\", opacityTexture);\n }\n\n return material;\n}\n","/** PBR material view helper with no color output.\n *\n * This module is separate from pbr-material.ts so scenes that only create/use\n * ordinary PBR materials do not retain the helper.\n */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport type { PbrMaterialProps } from \"./pbr-material.js\";\nimport { PBR_HAS_ALPHA_BLEND, PBR2_NO_COLOR_OUTPUT } from \"./pbr-flags.js\";\n\n/** Create a no-color view over a PBR source material.\n * The view references the source; material state is never copied. */\nexport function createPbrNoColorMaterialView(source: PbrMaterialProps): MaterialView {\n const features = source._renderFeatures ?? { features: 0, features2: 0 };\n return createMaterialView(source, { features: features.features & ~PBR_HAS_ALPHA_BLEND, features2: (features.features2 ?? 0) | PBR2_NO_COLOR_OUTPUT });\n}\n","/** Node Material parser — BJS snippet JSON → internal NodeGraph.\n *\n * BJS serializes node materials as a flat block list:\n * ```\n * {\n * blocks: [\n * {\n * customType: \"BABYLON.InputBlock\",\n * id: <uniqueId>,\n * name, comments,\n * inputs: [{ name, inputName, targetBlockId, targetConnectionName, ... }],\n * outputs: [{ name }],\n * ...per-class serialized fields (value, mode, type, ...)\n * },\n * ...\n * ],\n * outputNodes: [id, id, ...], // FragmentOutputBlock + VertexOutputBlock ids\n * editorData: { ... } // UI locations; irrelevant to rendering\n * }\n * ```\n *\n * Snippet server wraps this JSON once more:\n * ```\n * { id, version, jsonPayload: \"<stringified { nodeMaterial: \"<stringified JSON above>\" }>\" }\n * ```\n *\n * This parser is network-agnostic; snippet fetching lives in node-snippet.ts.\n */\n\nimport type { NodeBlock, NodeConnection, NodeConnectionRef, NodeGraph } from \"./node-types.js\";\n\n// ─── Block-level JSON shape ──────────────────────────────────────────\n\ninterface RawInput {\n name: string;\n displayName?: string;\n inputName?: string;\n targetBlockId?: number;\n targetConnectionName?: string;\n}\n\ninterface RawOutput {\n name: string;\n displayName?: string;\n}\n\ninterface RawBlock {\n customType: string;\n id: number;\n name: string;\n comments?: string;\n inputs?: RawInput[];\n outputs?: RawOutput[];\n [extra: string]: unknown;\n}\n\ninterface RawSource {\n blocks: RawBlock[];\n outputNodes?: number[];\n}\n\ninterface RawWithAlpha {\n alphaMode?: number;\n _needAlphaBlending?: boolean;\n forceAlphaBlending?: boolean;\n backFaceCulling?: boolean;\n}\n\n// ─── Parse ───────────────────────────────────────────────────────────\n\n/** Parse a deserialized NME JSON root into the internal NodeGraph model. */\nexport function parseNodeMaterialSource(source: unknown): NodeGraph {\n const raw = source as RawSource;\n if (!raw || !Array.isArray(raw.blocks)) {\n throw new Error(\"NodeMaterial: invalid source — expected `.blocks` array\");\n }\n\n const blocks = new Map<number, NodeBlock>();\n\n for (const rb of raw.blocks) {\n if (typeof rb.id !== \"number\") {\n throw new Error(`NodeMaterial: block missing numeric id (name=${rb.name})`);\n }\n const className = stripBabylonPrefix(rb.customType);\n\n const inputs = new Map<string, NodeConnection>();\n for (const ri of rb.inputs ?? []) {\n // BJS serializes some composite input names with trailing whitespace\n // (e.g. \"xyz \", \"rgb \") to avoid collisions with same-named outputs. Normalize.\n const inName = (ri.name ?? \"\").trim();\n const outName = typeof ri.targetConnectionName === \"string\" ? ri.targetConnectionName.trim() : undefined;\n const source: NodeConnectionRef | null =\n typeof ri.targetBlockId === \"number\" && typeof outName === \"string\" ? { blockId: ri.targetBlockId, outputName: outName } : null;\n inputs.set(inName, {\n name: inName,\n source,\n });\n }\n\n const outputs = new Set<string>();\n for (const ro of rb.outputs ?? []) {\n outputs.add((ro.name ?? \"\").trim());\n }\n\n blocks.set(rb.id, {\n id: rb.id,\n className,\n name: rb.name,\n inputs,\n outputs,\n serialized: rb as unknown as Record<string, unknown>,\n });\n }\n\n // Named overridable inputs — any InputBlock in uniform mode is overridable.\n // BJS uses _mode: NodeMaterialBlockConnectionPointMode.Uniform (value === 0).\n const namedInputs = new Map<string, number>();\n for (const b of blocks.values()) {\n if (b.className !== \"InputBlock\") {\n continue;\n }\n const mode = (b.serialized[\"mode\"] ?? b.serialized[\"_mode\"]) as number | undefined;\n // 0 = Uniform, 1 = Attribute, 2 = Varying. Only Uniform is user-overridable.\n // System-value InputBlocks (mode 0 with a `systemValue`) are scene-provided and NOT overridable.\n if (mode === 0 || mode === undefined) {\n if (typeof b.serialized[\"systemValue\"] === \"number\") {\n continue;\n }\n if (b.name) {\n namedInputs.set(b.name, b.id);\n }\n }\n }\n\n // Alpha mode + blending determination.\n // Priority: forceAlphaBlending > explicit _needAlphaBlending > graph-derived.\n const rawAlpha = raw as RawWithAlpha;\n const alphaMode: number = typeof rawAlpha.alphaMode === \"number\" ? rawAlpha.alphaMode : 0;\n let needsAlphaBlending: boolean;\n if (rawAlpha.forceAlphaBlending === true) {\n needsAlphaBlending = true;\n } else if (typeof rawAlpha._needAlphaBlending === \"boolean\") {\n needsAlphaBlending = rawAlpha._needAlphaBlending;\n } else {\n // Derive from graph: blending is needed when FragmentOutputBlock's `a`\n // input is connected AND alphaMode > 0 (non-disabled).\n const fragOut = findBlockByClassName({ blocks, namedInputs, alphaMode, needsAlphaBlending: false, backFaceCulling: true }, \"FragmentOutputBlock\");\n const aConn = fragOut?.inputs.get(\"a\");\n needsAlphaBlending = alphaMode > 0 && !!aConn?.source;\n }\n\n return { blocks, namedInputs, alphaMode, needsAlphaBlending, backFaceCulling: rawAlpha.backFaceCulling !== false };\n}\n\nfunction stripBabylonPrefix(customType: string): string {\n return customType.startsWith(\"BABYLON.\") ? customType.slice(\"BABYLON.\".length) : customType;\n}\n\n// ─── Topological sort ───────────────────────────────────────────────\n\n/** Topologically sort block ids in dependency order (producers before consumers).\n * Throws on cycles. Starts from `roots` (typically the VertexOutput +\n * FragmentOutput block ids) and only includes blocks transitively reached. */\nexport function topoSort(graph: NodeGraph, roots: readonly number[]): number[] {\n const order: number[] = [];\n const state = new Map<number, 0 | 1 | 2>(); // 0=unseen, 1=on-stack, 2=done\n\n const visit = (id: number, path: number[]): void => {\n const s = state.get(id) ?? 0;\n if (s === 2) {\n return;\n }\n if (s === 1) {\n throw new Error(`NodeMaterial: cycle detected through block ${id} (${path.join(\" -> \")})`);\n }\n state.set(id, 1);\n const block = graph.blocks.get(id);\n if (!block) {\n throw new Error(`NodeMaterial: dangling reference to block ${id}`);\n }\n for (const input of block.inputs.values()) {\n if (input.source) {\n visit(input.source.blockId, [...path, id]);\n }\n }\n state.set(id, 2);\n order.push(id);\n };\n\n for (const r of roots) {\n visit(r, [r]);\n }\n return order;\n}\n\n/** Locate a block by className (returns the first match, or null). */\nexport function findBlockByClassName(graph: NodeGraph, className: string): NodeBlock | null {\n for (const b of graph.blocks.values()) {\n if (b.className === className) {\n return b;\n }\n }\n return null;\n}\n","/** Node Material — internal graph + emitter types.\n *\n * All types here are pure data. Block emitters are pure functions imported lazily\n * from `./blocks/*` via the registry. No module-level state lives here.\n */\n\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { UboField, BindingDecl, VertexAttribute, Varying } from \"../../shader/fragment-types.js\";\n\n// ─── Graph (parser output) ───────────────────────────────────────────\n\n/** A single connection point on a block — input only.\n * Output connection types are resolved by the emitter at graph-walk time. */\nexport interface NodeConnection {\n /** Connection name on the owning block (e.g. \"rgb\", \"uv\", \"color\"). */\n readonly name: string;\n /** For inputs only: the upstream block id + output name. Null if unconnected. */\n readonly source: NodeConnectionRef | null;\n}\n\nexport interface NodeConnectionRef {\n readonly blockId: number;\n readonly outputName: string;\n}\n\n/** Parsed block in the graph. */\nexport interface NodeBlock {\n readonly id: number;\n /** BJS class name (e.g. \"InputBlock\", \"TransformBlock\", \"FragmentOutputBlock\"). */\n readonly className: string;\n /** Author-provided block name. */\n readonly name: string;\n /** Inputs by name. */\n readonly inputs: ReadonlyMap<string, NodeConnection>;\n /** Output names (type is resolved by the emitter). */\n readonly outputs: ReadonlySet<string>;\n /** Original serialized JSON for emitters that need extra fields (mode, value, etc.). */\n readonly serialized: Readonly<Record<string, unknown>>;\n}\n\n/** Parsed graph. Roots are FragmentOutputBlock + VertexOutputBlock (located by className). */\nexport interface NodeGraph {\n readonly blocks: ReadonlyMap<number, NodeBlock>;\n /** Named overridable inputs (uniform InputBlocks) — name → block id. */\n readonly namedInputs: ReadonlyMap<string, number>;\n /** BJS alpha mode (0=DISABLE, 2=COMBINE, …). Determines the GPU blend equation. */\n readonly alphaMode: number;\n /** Whether the material requires alpha blending at runtime.\n * Derived from the graph (FragmentOutputBlock.a is connected) plus\n * JSON-level overrides (`_needAlphaBlending`, `forceAlphaBlending`). */\n readonly needsAlphaBlending: boolean;\n /** Babylon.js material back-face culling flag. */\n readonly backFaceCulling: boolean;\n}\n\nexport interface NodePbrMrHelperRequest {\n readonly key: string;\n readonly useEnv: boolean;\n readonly useClearcoat: boolean;\n readonly useSheen: boolean;\n readonly useRefraction: boolean;\n readonly useSubsurface: boolean;\n readonly useAnisotropy: boolean;\n readonly useIridescence: boolean;\n readonly useShAlbedoScaling: boolean;\n readonly useCcBump: boolean;\n readonly useCcTint: boolean;\n readonly useSpecularAA: boolean;\n readonly remapClearcoatF0: boolean;\n}\n\n// ─── WGSL value types ───────────────────────────────────────────────\n\nexport type NodeValueType = \"f32\" | \"vec2f\" | \"vec3f\" | \"vec4f\" | \"mat4f\" | \"texture2d\" | \"textureCube\";\n\n/** Typed WGSL expression produced by an emitter. */\nexport interface NodeExpr {\n readonly expr: string;\n readonly type: NodeValueType;\n}\n\nexport const WGSL: Readonly<Record<NodeValueType, string>> = {\n f32: \"f32\",\n vec2f: \"vec2<f32>\",\n vec3f: \"vec3<f32>\",\n vec4f: \"vec4<f32>\",\n mat4f: \"mat4x4<f32>\",\n texture2d: \"texture_2d<f32>\",\n textureCube: \"texture_cube<f32>\",\n};\n\n// ─── Shader stage ───────────────────────────────────────────────────\n\n/** Which shader stage an emitter writes into. Neutral blocks can run in either;\n * the walker places them in the stage of their consumer (fragment by default). */\nexport type Stage = \"vertex\" | \"fragment\";\n\n// ─── Emitter API ────────────────────────────────────────────────────\n\n/** Accumulators for a single shader stage. */\nexport interface StageState {\n /** Top-level helper declarations (functions, constants) keyed by canonical id. */\n readonly helpers: Map<string, string>;\n /** Statements emitted inside main(). */\n readonly body: string[];\n /** Memoized (blockId, outputName) → expr for already-emitted values in this stage. */\n readonly memo: Map<string, NodeExpr>;\n}\n\nexport interface NodeLoopVariable {\n readonly valueVar: string;\n readonly valueType: NodeValueType;\n readonly indexVar: string;\n}\n\n/** Build state threaded through every emit call. */\nexport interface NodeBuildState {\n readonly vertex: StageState;\n readonly fragment: StageState;\n // Shared across stages:\n readonly vertexAttributes: VertexAttribute[];\n readonly varyings: Varying[];\n readonly nodeUboFields: UboField[];\n readonly bindings: BindingDecl[];\n readonly textures: NodeTextureBinding[];\n /** PBRMetallicRoughnessBlock helper bodies are large, so the block records\n * feature-specific helper requests here and node-material resolves them\n * through dynamic imports after graph emission. */\n readonly pbrMrHelperRequests: NodePbrMrHelperRequest[];\n /** Active LoopBlock storage variables keyed by `${stage}|${blockId}` while\n * the loop body is being emitted. StorageReadBlock/StorageWriteBlock use\n * this to route their loopID object connection to the mutable WGSL var. */\n readonly loopVariables: Map<string, NodeLoopVariable>;\n /** Monotonic counter for SSA temp names, shared across stages. */\n nextTemp: number;\n /** Set by any block that references the scene lights UBO (LightBlock,\n * LightInformationBlock, …). The pipeline builder allocates a binding +\n * struct decls + BGL entry when true. */\n usesLightsUbo: boolean;\n /** Set by ScreenSizeBlock. The pipeline exposes the current canvas size via\n * spare base scene-UBO scalars (no extra bindings / no per-graph UBO size change). */\n usesScreenSize: boolean;\n /** Set by FragDepthBlock. The pipeline switches the fragment return type\n * from a bare color to a `color+@builtin(frag_depth)` output struct. */\n usesFragDepth: boolean;\n usesClipPlanes: boolean;\n usesMeshAttributeExists: boolean;\n /** Set by MorphTargetsBlock. The pipeline allocates two vertex-only\n * bindings (morph texture + morph UBO), declares the struct, and adds\n * a `@builtin(vertex_index)` param to vs_main. */\n usesMorphTargets: boolean;\n /** Set by parseNodeMaterialFromSnippet when shadowGenerators are supplied.\n * The pipeline allocates shadow bindings (texture + sampler + UBO) per\n * shadow-casting light, emits light-space varyings in vs_main, and injects\n * a `nme_computeShadowFactors` helper that LightBlock calls before the\n * lighting loop. Zero entries = no bindings, no WGSL — invisible to scenes\n * without shadows. */\n shadowLights: { lightIndex: number; shadowType: \"esm\" | \"pcf\" }[];\n /** Set by ReflectionBlock or any block that needs scene env textures\n * (specular cube + BRDF LUT + SH irradiance). The pipeline allocates\n * 4 group-1 bindings (env_iblTexture/sampler + env_brdfLUT/sampler) and\n * reads SH coefficients + envRotationY + lodGenerationScale from the\n * canonical frame-graph scene UBO. Materials without env\n * pay zero — empty default. */\n usesEnv: boolean;\n /** Set by ClearCoatBlock; tells PBRMetallicRoughnessBlock to walk into\n * the connected ClearCoatBlock and emit the clear-coat layer code path\n * (extra GGX layer + Fresnel modulation of the base specular). */\n usesClearcoat: boolean;\n /** Set by SheenBlock; tells PBRMetallicRoughnessBlock to add the Charlie\n * NDF + Ashikhmin visibility sheen layer (cloth/velvet look). */\n usesSheen: boolean;\n /** Set by AnisotropyBlock; reserved for future anisotropic GGX path.\n * Currently used only to validate marker plumbing in scene 70 — at\n * intensity=0 the BJS anisotropic path reduces to standard GGX. */\n usesAnisotropy: boolean;\n /** Set by IridescenceBlock; tells PBRMetallicRoughnessBlock to replace the\n * base-layer F0 by the thin-film interference Fresnel color before direct\n * and IBL specular evaluation. */\n usesIridescence: boolean;\n /** Set by SubSurfaceBlock; reserved for future SS path. Marker only. */\n usesSubsurface: boolean;\n /** When false (default), BonesBlock emits a pass-through of its `world`\n * input — no skeleton binding is required. Set to true only when every\n * mesh using this material has a skeleton. */\n hasSkeleton: boolean;\n /** When false (default), InstancesBlock passes through the uniform world\n * matrix. Set to true when thin-instance attributes are bound. */\n hasInstances: boolean;\n}\n\nexport interface NodeTextureBinding {\n readonly name: string;\n readonly kind: \"texture2d\" | \"textureCube\";\n readonly texture: Texture2D | null;\n}\n\n/** A block emitter — pure functions, no per-instance state. */\nexport interface BlockEmitter {\n /** Class name this emitter handles (e.g. \"InputBlock\"). */\n readonly className: string;\n /** Which shader stage this block produces into. Defaults to \"fragment\". */\n readonly stage?: Stage;\n /** Terminal \"side-effect\" block that has no outputs the graph reads (e.g.\n * DiscardBlock). emitGraph force-emits these after the root walk so they\n * participate even without a downstream consumer. */\n readonly sideEffect?: boolean;\n /** Emit the value of `outputName` for `block`, returning a typed WGSL expression. */\n emit(block: NodeBlock, outputName: string, stage: Stage, state: NodeBuildState, ctx: NodeEmitContext): NodeExpr;\n}\n\nexport interface NodeEmitContext {\n /** Resolve an input → WGSL expression (handles memoization + recursive walk). */\n readonly resolve: (block: NodeBlock, inputName: string, stage: Stage, state: NodeBuildState) => NodeExpr;\n /** Resolve a specific (producerBlock, outputName) — used when one block reads another directly. */\n readonly resolveOutput: (producer: NodeBlock, outputName: string, stage: Stage, state: NodeBuildState) => NodeExpr;\n /** Mint a fresh SSA temp name. */\n readonly temp: (state: NodeBuildState, prefix?: string) => string;\n /** Cast a typed expression to a target WGSL type when the shapes differ. */\n readonly cast: (value: NodeExpr, target: NodeValueType) => NodeExpr;\n /** Access the surrounding graph (so emitters can find upstream blocks). */\n readonly graph: NodeGraph;\n /** @internal */\n readonly _loadedEmitters: Map<string, BlockEmitter>;\n}\n","/** Node Material — WGSL emitter core.\n *\n * Given a parsed NodeGraph, walk it topologically from the FragmentOutput +\n * VertexOutput roots, calling each block's emitter to emit WGSL. The emitter\n * API guarantees that every (blockId, outputName) is emitted at most once per\n * stage (memoization), so downstream consumers share the same SSA temp.\n *\n * The result is a pair of WGSL source strings (vertex + fragment) plus the\n * accumulated UBO fields, attributes, varyings, samplers, and texture bindings\n * needed by the pipeline builder. This module intentionally has no WGSL of its\n * own beyond empty scaffolding — every shader string comes from a block emitter\n * so each block tree-shakes independently.\n */\n\nimport type { NodeBlock, NodeBuildState, NodeEmitContext, NodeExpr, NodeGraph, NodeValueType, Stage, StageState, BlockEmitter } from \"./node-types.js\";\nimport { WGSL } from \"./node-types.js\";\n\n// ─── Build-state construction ───────────────────────────────────────\n\nfunction newStageState(): StageState {\n return {\n helpers: new Map(),\n body: [],\n memo: new Map(),\n };\n}\n\nexport function createBuildState(): NodeBuildState {\n return {\n vertex: newStageState(),\n fragment: newStageState(),\n vertexAttributes: [],\n varyings: [],\n nodeUboFields: [],\n bindings: [],\n textures: [],\n pbrMrHelperRequests: [],\n loopVariables: new Map(),\n nextTemp: 0,\n usesLightsUbo: false,\n usesScreenSize: false,\n usesFragDepth: false,\n usesClipPlanes: false,\n usesMeshAttributeExists: false,\n usesMorphTargets: false,\n usesEnv: false,\n usesClearcoat: false,\n usesSheen: false,\n usesAnisotropy: false,\n usesIridescence: false,\n usesSubsurface: false,\n shadowLights: [],\n hasSkeleton: false,\n hasInstances: false,\n };\n}\n\n// ─── Emitter context ────────────────────────────────────────────────\n\nfunction memoKey(blockId: number, outputName: string): string {\n return `${blockId}|${outputName}`;\n}\n\nfunction stageOf(state: NodeBuildState, stage: Stage): StageState {\n return stage === \"vertex\" ? state.vertex : state.fragment;\n}\n\n/** Mint a fresh SSA temp name. */\nexport function mintTemp(state: NodeBuildState, prefix = \"t\"): string {\n const id = state.nextTemp++;\n return `_${prefix}${id}`;\n}\n\n/** Cast a typed WGSL expression to a target type. Throws if no cast is known.\n * Handles the common vector-widen/narrow cases that NME graphs actually use. */\nexport function castExpr(value: NodeExpr, target: NodeValueType): NodeExpr {\n if (value.type === target) {\n return value;\n }\n const t = WGSL[target];\n // Narrowing: vec4 -> vec3/vec2/f32 via .xyz/.xy/.x\n if (value.type === \"vec4f\" && target === \"vec3f\") {\n return { expr: `(${value.expr}).xyz`, type: target };\n }\n if (value.type === \"vec4f\" && target === \"vec2f\") {\n return { expr: `(${value.expr}).xy`, type: target };\n }\n if (value.type === \"vec3f\" && target === \"vec2f\") {\n return { expr: `(${value.expr}).xy`, type: target };\n }\n if ((value.type === \"vec4f\" || value.type === \"vec3f\" || value.type === \"vec2f\") && target === \"f32\") {\n return { expr: `(${value.expr}).x`, type: target };\n }\n // Widening: f32 -> vecN, vec3 -> vec4 (w=1)\n if (value.type === \"f32\" && (target === \"vec2f\" || target === \"vec3f\" || target === \"vec4f\")) {\n return { expr: `${t}(${value.expr})`, type: target };\n }\n if (value.type === \"vec3f\" && target === \"vec4f\") {\n return { expr: `vec4<f32>(${value.expr}, 1.0)`, type: target };\n }\n if (value.type === \"vec2f\" && target === \"vec4f\") {\n return { expr: `vec4<f32>(${value.expr}, 0.0, 1.0)`, type: target };\n }\n if (value.type === \"vec2f\" && target === \"vec3f\") {\n return { expr: `vec3<f32>(${value.expr}, 0.0)`, type: target };\n }\n throw new Error(`NodeMaterial: cannot cast ${value.type} to ${target} for expression \\`${value.expr}\\``);\n}\n\nfunction makeContext(graph: NodeGraph, loadedEmitters: Map<string, BlockEmitter>): NodeEmitContext {\n const ctx: NodeEmitContext = {\n graph,\n _loadedEmitters: loadedEmitters,\n temp: (state, prefix) => mintTemp(state, prefix),\n cast: castExpr,\n resolve: (block, inputName, stage, state) => {\n const input = block.inputs.get(inputName);\n if (!input) {\n throw new Error(`NodeMaterial: block \"${block.className}\" (id=${block.id}) has no input \"${inputName}\"`);\n }\n if (!input.source) {\n throw new Error(`NodeMaterial: block \"${block.className}\" (id=${block.id}) input \"${inputName}\" is not connected`);\n }\n const producer = graph.blocks.get(input.source.blockId);\n if (!producer) {\n throw new Error(`NodeMaterial: dangling connection ${block.id}.${inputName} -> block ${input.source.blockId}`);\n }\n return ctx.resolveOutput(producer, input.source.outputName, stage, state);\n },\n resolveOutput: (producer, outputName, stage, state) => {\n const stageState = stageOf(state, stage);\n const key = memoKey(producer.id, outputName);\n const existing = stageState.memo.get(key);\n if (existing) {\n return existing;\n }\n const emitter = loadedEmitters.get(producer.className);\n if (!emitter) {\n throw new Error(`NodeMaterial: no emitter loaded for block \"${producer.className}\"`);\n }\n // Blocks that declare a stage preference override the requested stage.\n const targetStage = emitter.stage ?? stage;\n const result = emitter.emit(producer, outputName, targetStage, state, ctx);\n // If the producer ran in a different stage, bridge via varying.\n if (targetStage !== stage) {\n const vname = `v_${producer.id}_${outputName}`;\n bridgeVarying(state, vname, result, targetStage, stage);\n const bridged: NodeExpr = { expr: `in.${vname}`, type: result.type };\n stageState.memo.set(key, bridged);\n return bridged;\n }\n stageState.memo.set(key, result);\n return result;\n },\n };\n return ctx;\n}\n\nfunction bridgeVarying(state: NodeBuildState, varyingName: string, value: NodeExpr, from: Stage, to: Stage): void {\n if (from !== \"vertex\" || to !== \"fragment\") {\n throw new Error(\"NodeMaterial: only vertex->fragment varyings are supported\");\n }\n const already = state.varyings.find((v) => v._name === varyingName);\n if (!already) {\n state.varyings.push({ _name: varyingName, _type: WGSL[value.type] });\n state.vertex.body.push(`out.${varyingName} = ${value.expr};`);\n }\n}\n\n// ─── Emitter dispatch ───────────────────────────────────────────────\n\n/** Load all emitters referenced by the graph in a single parallel batch. */\nlet defaultRegistry: Promise<typeof import(\"./node-registry.js\")> | null = null;\nasync function defaultBlockLoader(className: string): Promise<BlockEmitter> {\n defaultRegistry ??= import(\"./node-registry.js\");\n return (await defaultRegistry).loadBlockEmitter(className);\n}\n\nfunction pbrMrBlockNeedsFullEmitter(block: NodeBlock): boolean {\n return (\n (block.serialized as { enableSpecularAntiAliasing?: boolean }).enableSpecularAntiAliasing === true ||\n !!block.inputs.get(\"clearcoat\")?.source ||\n !!block.inputs.get(\"sheen\")?.source ||\n !!block.inputs.get(\"subsurface\")?.source ||\n !!block.inputs.get(\"anisotropy\")?.source ||\n !!block.inputs.get(\"iridescence\")?.source\n );\n}\n\nfunction graphNeedsFullPbrMrEmitter(graph: NodeGraph): boolean {\n for (const block of graph.blocks.values()) {\n if (block.className === \"PBRMetallicRoughnessBlock\" && pbrMrBlockNeedsFullEmitter(block)) {\n return true;\n }\n }\n return false;\n}\n\nexport async function loadGraphEmitters(graph: NodeGraph, blockLoader: (className: string) => Promise<BlockEmitter> = defaultBlockLoader): Promise<Map<string, BlockEmitter>> {\n const classNames = new Set<string>();\n for (const b of graph.blocks.values()) {\n classNames.add(b.className);\n }\n const map = new Map<string, BlockEmitter>();\n const useFullPbrMrEmitter = blockLoader === defaultBlockLoader && graphNeedsFullPbrMrEmitter(graph);\n await Promise.all(\n Array.from(classNames).map(async (className) => {\n const loaderKey = className === \"PBRMetallicRoughnessBlock\" && useFullPbrMrEmitter ? \"PBRMetallicRoughnessBlock__full\" : className;\n const e = await blockLoader(loaderKey);\n map.set(className, e);\n })\n );\n return map;\n}\n\n// ─── Public entry ───────────────────────────────────────────────────\n\nexport interface EmitResult {\n readonly vertexWgsl: string;\n readonly fragmentWgsl: string;\n readonly state: NodeBuildState;\n}\n\n/** Walk the graph from the given root (a FragmentOutput or VertexOutput block)\n * and emit the pair of WGSL shader strings. The caller is responsible for\n * wrapping the result with the pipeline's bind-group / entry-point scaffolding\n * (done by `node-pipeline.ts`). */\nexport function emitGraph(\n graph: NodeGraph,\n loadedEmitters: Map<string, BlockEmitter>,\n fragmentRootId: number,\n vertexRootId: number | null,\n shadowLights?: readonly { lightIndex: number; shadowType: \"esm\" | \"pcf\" }[],\n meshCaps?: { hasSkeleton?: boolean; hasInstances?: boolean }\n): EmitResult {\n const state = createBuildState();\n if (shadowLights) {\n for (const sl of shadowLights) {\n state.shadowLights.push(sl);\n }\n }\n if (meshCaps) {\n if (meshCaps.hasSkeleton) {\n state.hasSkeleton = true;\n }\n if (meshCaps.hasInstances) {\n state.hasInstances = true;\n }\n }\n const ctx = makeContext(graph, loadedEmitters);\n\n // Emit fragment root.\n const fragRoot = graph.blocks.get(fragmentRootId);\n if (!fragRoot) {\n throw new Error(`NodeMaterial: fragment root block ${fragmentRootId} not found`);\n }\n const fragEmitter = loadedEmitters.get(fragRoot.className);\n if (!fragEmitter) {\n throw new Error(`NodeMaterial: no emitter for fragment root \"${fragRoot.className}\"`);\n }\n fragEmitter.emit(fragRoot, \"\", \"fragment\", state, ctx);\n\n if (vertexRootId !== null) {\n const vertRoot = graph.blocks.get(vertexRootId);\n if (!vertRoot) {\n throw new Error(`NodeMaterial: vertex root block ${vertexRootId} not found`);\n }\n const vertEmitter = loadedEmitters.get(vertRoot.className);\n if (!vertEmitter) {\n throw new Error(`NodeMaterial: no emitter for vertex root \"${vertRoot.className}\"`);\n }\n vertEmitter.emit(vertRoot, \"\", \"vertex\", state, ctx);\n }\n\n // Force-emit side-effect blocks (e.g. DiscardBlock) that have no outputs\n // the graph walk would visit. Each such emitter is expected to guard its\n // own body via a memo key so multiple calls are idempotent.\n for (const block of graph.blocks.values()) {\n const e = loadedEmitters.get(block.className);\n if (e?.sideEffect) {\n e.emit(block, \"\", e.stage ?? \"fragment\", state, ctx);\n }\n }\n\n return {\n vertexWgsl: composeStage(state, \"vertex\"),\n fragmentWgsl: composeStage(state, \"fragment\"),\n state,\n };\n}\n\nfunction composeStage(state: NodeBuildState, stage: Stage): string {\n // Helpers are emitted at module scope by the pipeline builder, NOT inside main.\n // composeStage returns only the statements that belong inside the entry point.\n const s = stageOf(state, stage);\n return s.body.join(\"\\n\");\n}\n","export default \"struct SceneUniforms {\\nviewProjection: mat4x4<f32>,\\nview: mat4x4<f32>,\\nvEyePosition: vec4<f32>,\\nenvRotationY: f32,\\n_envPad0: f32, _envPad1: f32, _envPad2: f32,\\nvSphericalL00: vec4<f32>,\\nvSphericalL1_1: vec4<f32>,\\nvSphericalL10: vec4<f32>,\\nvSphericalL11: vec4<f32>,\\nvSphericalL2_2: vec4<f32>,\\nvSphericalL2_1: vec4<f32>,\\nvSphericalL20: vec4<f32>,\\nvSphericalL21: vec4<f32>,\\nvSphericalL22: vec4<f32>,\\nvImageInfos: vec4<f32>, // exposureLinear, contrast, lodGenerationScale, toneMappingEnabled\\nvFogInfos: vec4<f32>,\\nvFogColor: vec4<f32>,\\nclipPlane: vec4<f32>,\\n}\\n@group(0) @binding(0) var<uniform> scene: SceneUniforms;\\n\"","/** Canonical SceneUniforms — TS counterpart to `shaders/scene-uniforms.wgsl`.\n *\n * Only the size + the WGSL source are exported. Per-field byte offsets are\n * hard-coded inline at every write site (see `frame-graph/render-task.ts` and the\n * light extensions). If the WGSL struct changes, update those offsets. */\n\nimport sceneUniformsWgsl from \"../../shaders/scene-uniforms.wgsl?raw\";\nexport { SCENE_UBO_BYTES } from \"./scene-uniforms-size.js\";\n\n/** Canonical WGSL declaration of the SceneUniforms struct + group(0) binding.\n * Prepend to any standalone shader (skybox, ground, etc.) that samples the\n * per-pass scene UBO. The composer-driven materials (std + pbr) inject this\n * same string into their shader templates via the `/*SU* /` slot. */\nexport const SCENE_UBO_WGSL = sceneUniformsWgsl;\n","/**\n * UBO Layout Computation\n *\n * Computes byte offsets and generates WGSL struct bodies from UboField arrays,\n * respecting WGSL uniform buffer alignment rules (std140-like):\n *\n * ```\n * f32 → align 4, size 4\n * u32 / i32 → align 4, size 4\n * vec2<f32> → align 8, size 8\n * vec3<f32> → align 16, size 12\n * vec4<f32> → align 16, size 16\n * vec4<u32> → align 16, size 16\n * mat4x4<f32> → align 16, size 64\n * array<vec4<u32>, N> → align 16, size 16 × N\n * ```\n *\n * The total struct size is rounded up to a multiple of 16 bytes.\n */\n\nimport type { UboField, UboSpec, WgslScalarType } from \"./fragment-types.js\";\n\ninterface TypeInfo {\n readonly align: number;\n readonly size: number;\n}\n\nconst TYPE_INFO: Partial<Record<WgslScalarType, TypeInfo>> = {\n f32: { align: 4, size: 4 },\n u32: { align: 4, size: 4 },\n i32: { align: 4, size: 4 },\n \"vec2<f32>\": { align: 8, size: 8 },\n \"vec3<f32>\": { align: 16, size: 12 },\n \"vec4<f32>\": { align: 16, size: 16 },\n \"vec4<u32>\": { align: 16, size: 16 },\n \"mat4x4<f32>\": { align: 16, size: 64 },\n};\n\nfunction alignUp(offset: number, alignment: number): number {\n return (offset + alignment - 1) & ~(alignment - 1);\n}\n\nfunction typeInfo(type: WgslScalarType): TypeInfo {\n const info = TYPE_INFO[type];\n if (info) {\n return info;\n }\n const m = /^array<vec4<u32>,\\s*(\\d+)>$/.exec(type);\n if (m) {\n return { align: 16, size: Number(m[1]) * 16 };\n }\n throw new Error(`Unknown UBO field type: ${type}`);\n}\n\n/**\n * Compute the UBO byte layout from an ordered array of fields.\n * Returns the total byte size, a map of field name → byte offset,\n * and the WGSL struct body string (fields only, no `struct Name {}` wrapper).\n */\nexport function computeUboLayout(fields: readonly UboField[]): UboSpec {\n const _offsets = new Map<string, number>();\n const lines: string[] = [];\n let cursor = 0;\n\n for (const field of fields) {\n const info = typeInfo(field._type);\n\n cursor = alignUp(cursor, info.align);\n _offsets.set(field._name, cursor);\n lines.push(`${field._name}: ${field._type},`);\n cursor += info.size;\n }\n\n // Round total size up to 16-byte boundary (required for uniform buffers)\n const _totalBytes = fields.length > 0 ? alignUp(cursor, 16) : 0;\n const _structBody = lines.join(\"\\n\");\n\n return {\n _totalBytes,\n _offsets,\n _structBody,\n };\n}\n","/** Node Material — WGSL wrap + GPU pipeline builder.\n *\n * Takes the pair of WGSL bodies produced by `emitGraph` plus the accumulated\n * build state, and produces:\n * • Full WGSL shader text (vertex + fragment, single module)\n * • Bind-group layouts (group 0 = scene, group 1 = mesh/material/textures)\n * • A cached GPURenderPipeline keyed by shader source + format + MSAA\n *\n * This module is loaded lazily by `node-renderable.ts` and is the only place\n * that knows how to substitute engine-owned sentinels (`_NME_FRAG_OUTPUT_`,\n * `_NME_VTX_OUTPUT_`, `_NME_FRONT_FACING_`, …). Keeping all WGSL assembly here\n * leaves block emitters free of cross-cutting knowledge about the pipeline.\n */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport { REVERSE_DEPTH_COMPARE } from \"../../engine/render-target.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { createDefaultPipelineDescriptor } from \"../../render/scene-helpers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { computeUboLayout } from \"../../shader/ubo-layout.js\";\nimport { MAX_LIGHTS } from \"../../light/types.js\";\nimport type { NodeBuildState } from \"./node-types.js\";\n\n// ─── Shared WGSL preamble ───────────────────────────────────────────\n\nfunction buildMeshStruct(): string {\n return `struct MeshU {\n world: mat4x4<f32>,\n receivesShadow: vec4<f32>,\n lc: u32,\n li: array<vec4<u32>, ${Math.ceil(MAX_LIGHTS / 4)}>,\n};\n@group(1) @binding(0) var<uniform> meshU: MeshU;\nfn nli(i: u32) -> u32 { return meshU.li[i / 4u][i % 4u]; }`;\n}\n\n/** Sentinels the builder substitutes away before compile. */\nconst SENTINEL_FRAG_OUTPUT = \"_NME_FRAG_OUTPUT_\";\nconst SENTINEL_FRAG_DEPTH = \"_NME_FRAG_DEPTH_\";\nconst SENTINEL_VTX_OUTPUT = \"_NME_VTX_OUTPUT_\";\nconst SENTINEL_FRONT_FACING = \"_NME_FRONT_FACING_\";\nconst SENTINEL_FRAG_COORD = \"_NME_FRAG_COORD_\";\nconst SENTINEL_SCREEN_SIZE = \"_NME_SCREEN_SIZE_\";\n\n// ─── Compile result ─────────────────────────────────────────────────\n\n/** @internal */\nexport interface NodeCompileResult {\n /** @internal */\n readonly _wgsl: string;\n /** @internal */\n readonly _pipeline: GPURenderPipeline;\n /** @internal */\n readonly _meshBGL: GPUBindGroupLayout;\n /** @internal */\n readonly _nodeUboSize: number;\n /** @internal */\n readonly _nodeUboOffsets: ReadonlyMap<string, number>;\n /** @internal The resolved bind-group slot (within group 1) for the node UBO. `null` if no uniforms. */\n readonly _nodeUboBinding: number | null;\n /** @internal Per-texture binding slots assigned by the pipeline builder. */\n readonly _textureBindings: ReadonlyArray<{ readonly _name: string; readonly _texBinding: number; readonly _sampBinding: number }>;\n /** @internal Slots for the morph-target texture + weights UBO, or `null` when no MorphTargetsBlock is present. */\n readonly _morphBindings: { readonly _textureBinding: number; readonly _uboBinding: number } | null;\n /** @internal Slot assignments for env IBL bindings within group 1, when state.usesEnv is true. */\n readonly _envBindings: {\n /** @internal */\n readonly _iblTexture: number;\n /** @internal */\n readonly _iblSampler: number;\n /** @internal */\n readonly _brdfLUT: number;\n /** @internal */\n readonly _brdfSampler: number;\n } | null;\n /** @internal Per shadow-casting light: slot assignments in group 1 for the shadow texture, sampler, and shadowInfo UBO. Empty when the material uses no shadows. */\n readonly _shadowBindings: readonly import(\"./node-shadow.js\").ShadowBinding[];\n /** @internal */\n readonly _usesClipPlanes: boolean;\n /** @internal */\n readonly _usesMeshAttributeFlags: boolean;\n /** @internal */\n readonly _esmShadowParamsBinding: number | null;\n}\n\n// ─── Pipeline cache ─────────────────────────────────────────────────\n\nlet _cache: Map<string, NodeCompileResult> | null = null;\nlet _cachedDevice: GPUDevice | null = null;\n\nfunction getCache(engine: EngineContext): Map<string, NodeCompileResult> {\n if (!_cache || _cachedDevice !== engine._device) {\n _cache = new Map();\n _cachedDevice = engine._device;\n }\n return _cache;\n}\n\n/** Clear the cached NME pipelines (call on device loss / test cleanup). */\nexport function clearNodePipelineCache(): void {\n _cache?.clear();\n _cache = null;\n _cachedDevice = null;\n}\n\n// ─── WGSL assembly ──────────────────────────────────────────────────\n\nfunction buildVertexIn(state: NodeBuildState): string {\n if (state.vertexAttributes.length === 0) {\n return `struct VertexIn {};`;\n }\n const lines = state.vertexAttributes.map((a, i) => ` @location(${i}) ${a._name}: ${a._type},`);\n return `struct VertexIn {\\n${lines.join(\"\\n\")}\\n};`;\n}\n\nfunction buildVertexOut(state: NodeBuildState): string {\n const lines = [` @builtin(position) position: vec4<f32>,`];\n state.varyings.forEach((v, i) => {\n lines.push(` @location(${i}) ${v._name}: ${v._type},`);\n });\n return `struct VertexOut {\\n${lines.join(\"\\n\")}\\n};`;\n}\n\nfunction buildNodeUbo(state: NodeBuildState, binding: number): { struct: string; size: number; offsets: ReadonlyMap<string, number> } | null {\n if (state.nodeUboFields.length === 0) {\n return null;\n }\n const layout = computeUboLayout(state.nodeUboFields);\n const lines = state.nodeUboFields.map((f) => ` ${f._name}: ${f._type},`);\n const struct = `struct NodeU {\\n${lines.join(\"\\n\")}\\n};\\n@group(1) @binding(${binding}) var<uniform> nodeU: NodeU;`;\n return { struct, size: layout._totalBytes, offsets: layout._offsets };\n}\n\nfunction indent(body: string): string {\n return body\n .split(\"\\n\")\n .map((l) => (l.length === 0 ? l : ` ${l}`))\n .join(\"\\n\");\n}\n\n// ─── Pipeline creation ──────────────────────────────────────────────\n\nexport interface CompileOpts {\n /** @internal */\n readonly _engine: EngineContext;\n /** @internal */\n readonly _format: GPUTextureFormat;\n /** @internal */\n readonly _depthStencilFormat?: GPUTextureFormat;\n /** @internal */\n readonly _depthCompare?: GPUCompareFunction;\n /** @internal */\n readonly _msaaSamples: number;\n /** @internal */\n readonly _backFaceCulling?: boolean;\n /** @internal */\n readonly _noColorOutput?: boolean;\n /** @internal */\n readonly _esmShadowOutput?: boolean;\n /** @internal ESM shadow depth output code. Supplied by the ESM material view so normal Node bundles don't retain it. */\n readonly _esmShadowDepthCode?: string;\n /** @internal BJS alpha mode (0=DISABLE, 2=COMBINE). Determines blend state. */\n readonly _alphaMode?: number;\n /** When `state.usesEnv` is true, this factory produces the env IBL\n * bindings + WGSL. Loaded via `await import(\"./node-env.js\")` from\n * node-material.ts only when `state.usesEnv` was set during emitGraph,\n * so non-env scenes never bundle the env helpers. */\n /** @internal */\n readonly _envEmitter?: typeof import(\"./node-env.js\").emitEnv;\n /** When `state.shadowLights` is non-empty, this factory produces shadow\n * bindings + WGSL. Loaded via `await import(\"./node-shadow.js\")` from\n * `node-material.ts` only when `shadowGenerators` was supplied, so\n * non-shadow scenes never bundle the PCF/ESM helpers. */\n /** @internal */\n readonly _shadowEmitter?: typeof import(\"./node-shadow.js\").emitShadow;\n}\n\nexport function compileNodePipeline(state: NodeBuildState, vertexBody: string, fragmentBody: string, opts: CompileOpts): NodeCompileResult {\n const { _engine, _format, _msaaSamples } = opts;\n const device = _engine._device;\n\n // Binding layout for group 1:\n // slot 0 = mesh UBO (world matrix)\n // slot 1 = node UBO (if nodeUboFields non-empty)\n // slot N, N+1 = texture + sampler (paired) for each entry in state.textures\n // scene group 0 binding 1 = shared lights UBO (if state.usesLightsUbo)\n let nextBinding = 1;\n const _nodeUboBinding = state.nodeUboFields.length > 0 ? nextBinding++ : null;\n const nodeUbo = _nodeUboBinding !== null ? buildNodeUbo(state, _nodeUboBinding) : null;\n const _nodeUboSize = nodeUbo?.size ?? 0;\n const _nodeUboOffsets: ReadonlyMap<string, number> = nodeUbo?.offsets ?? new Map<string, number>();\n\n const _textureBindings: { _name: string; _texBinding: number; _sampBinding: number }[] = [];\n const textureWgslDecls: string[] = [];\n for (const tex of state.textures) {\n const _name = tex.name;\n const _texBinding = nextBinding++;\n const _sampBinding = nextBinding++;\n _textureBindings.push({ _name, _texBinding, _sampBinding });\n const wgslTexType = tex.kind === \"textureCube\" ? \"texture_cube<f32>\" : \"texture_2d<f32>\";\n textureWgslDecls.push(`@group(1) @binding(${_texBinding}) var nodeTex_${_name}: ${wgslTexType};`);\n textureWgslDecls.push(`@group(1) @binding(${_sampBinding}) var nodeSamp_${_name}: sampler;`);\n }\n\n const lightsWgslDecls = state.usesLightsUbo\n ? `struct LightEntry { vLightData: vec4<f32>, vLightDiffuse: vec4<f32>, vLightSpecular: vec4<f32>, vLightDirection: vec4<f32> };\nstruct lightsUniforms { count: u32, _p0: u32, _p1: u32, _p2: u32, lights: array<LightEntry, ${MAX_LIGHTS}> };\n@group(0) @binding(1) var<uniform> nmeLights: lightsUniforms;`\n : \"\";\n\n // Morph-target bindings (vertex-only). Two slots: texture atlas + weights UBO.\n let _morphBindings: { _textureBinding: number; _uboBinding: number } | null = null;\n const morphWgslDecls: string[] = [];\n if (state.usesMorphTargets) {\n const _textureBinding = nextBinding++;\n const _uboBinding = nextBinding++;\n _morphBindings = { _textureBinding, _uboBinding };\n morphWgslDecls.push(\n `@group(1) @binding(${_textureBinding}) var morphTargets: texture_2d<f32>;`,\n `struct morphUniforms { weights: vec4<f32>, count: u32, texWidth: u32, rowsPerBand: u32, _p0: u32 };`,\n `@group(1) @binding(${_uboBinding}) var<uniform> morph: morphUniforms;`,\n // Helpers are emitted inline (module-scope) so they can reference `morph` + `morphTargets`.\n `fn nme_morph_coord(vi: u32) -> vec2<i32> { let col = i32(vi % morph.texWidth); let row = i32(vi / morph.texWidth); return vec2<i32>(col, row); }`,\n `fn nme_morphPosition(base: vec3<f32>, vi: u32) -> vec3<f32> {\\n` +\n ` var acc = base;\\n` +\n ` let co = nme_morph_coord(vi);\\n` +\n ` for (var i = 0u; i < morph.count; i = i + 1u) {\\n` +\n ` let posBase = i32(i * 2u) * i32(morph.rowsPerBand);\\n` +\n ` acc = acc + morph.weights[i] * textureLoad(morphTargets, vec2<i32>(co.x, posBase + co.y), 0).xyz;\\n` +\n ` }\\n` +\n ` return acc;\\n` +\n `}`,\n `fn nme_morphNormal(base: vec3<f32>, vi: u32) -> vec3<f32> {\\n` +\n ` var acc = base;\\n` +\n ` let co = nme_morph_coord(vi);\\n` +\n ` for (var i = 0u; i < morph.count; i = i + 1u) {\\n` +\n ` let normBase = i32(i * 2u + 1u) * i32(morph.rowsPerBand);\\n` +\n ` acc = acc + morph.weights[i] * textureLoad(morphTargets, vec2<i32>(co.x, normBase + co.y), 0).xyz;\\n` +\n ` }\\n` +\n ` return acc;\\n` +\n `}`\n );\n }\n\n // Env IBL bindings (specular cube + sampler, BRDF LUT 2D + sampler).\n // Allocated only when state.usesEnv was set during emitGraph AND the caller\n // supplied envEmitter (lazy-imported by node-material.ts). All env-specific\n // WGSL strings + BGL entries live in node-env.ts so non-env scenes never\n // bundle them.\n let _envBindings: { _iblTexture: number; _iblSampler: number; _brdfLUT: number; _brdfSampler: number } | null = null;\n let envWgslDecls = \"\";\n let envBglEntries: readonly GPUBindGroupLayoutEntry[] = [];\n if (state.usesEnv && opts._envEmitter) {\n const env = opts._envEmitter(nextBinding);\n _envBindings = env.bindings;\n envWgslDecls = env.wgslDecls;\n envBglEntries = env.bglEntries;\n nextBinding += env.bindingCount;\n }\n\n // Shadow bindings (per shadow-casting light). Emission/WGSL live in the\n // dynamically-imported `node-shadow.ts` module so scenes without shadows\n // never bundle the PCF/ESM helper code. `shadowEmitter` is supplied only\n // when `shadowGenerators` was passed to `parseNodeMaterialFromSnippet`.\n const noColorOutput = opts._noColorOutput === true;\n const esmShadowOutput = opts._esmShadowOutput === true;\n const shadowOutput = noColorOutput || esmShadowOutput;\n const shadowEmit = !shadowOutput && state.shadowLights.length > 0 && opts._shadowEmitter ? opts._shadowEmitter(state.shadowLights, nextBinding, state.varyings) : null;\n if (shadowEmit) {\n nextBinding += shadowEmit._bindingCount;\n }\n const _shadowBindings = shadowEmit?._bindings ?? [];\n const shadowWgslDecls = shadowEmit?._wgslDecls ?? \"\";\n const shadowVertexInject = shadowEmit?._vertexInject ?? \"\";\n const esmShadowDepthCode = opts._esmShadowDepthCode ?? \"\";\n const _esmShadowParamsBinding = esmShadowOutput ? nextBinding++ : null;\n const shadowFragmentHelper =\n shadowEmit?._fragmentHelper ??\n (shadowOutput && state.shadowLights.length > 0\n ? `fn nme_computeShadowFactors(input: VertexOut) -> array<f32, ${MAX_LIGHTS}> {\\n return array<f32, ${MAX_LIGHTS}>(${new Array(MAX_LIGHTS).fill(\"1.0\").join(\", \")});\\n}`\n : \"\");\n\n // Module-scope helpers (function defs, struct defs) — dedupe across both\n // stages by key. Fail on same-key/different-source to avoid silent loss.\n const helperSources = new Map<string, string>();\n for (const s of [state.vertex, state.fragment]) {\n for (const [k, v] of s.helpers) {\n const existing = helperSources.get(k);\n if (existing !== undefined && existing !== v) {\n throw new Error(`NodeMaterial: helper key \"${k}\" registered with conflicting source bodies`);\n }\n helperSources.set(k, v);\n }\n }\n\n // Compose WGSL (node UBO struct inserted conditionally between mesh + VertexIn).\n const vertexIn = buildVertexIn(state);\n const vertexOut = buildVertexOut(state);\n const fragmentOut =\n !noColorOutput && state.usesFragDepth\n ? `struct FragmentOut {\n @location(0) color: vec4<f32>,\n @builtin(frag_depth) fragDepth: f32,\n};`\n : \"\";\n const wgslParts: string[] = [\"// Auto-generated by NodeMaterial — DO NOT EDIT\", SCENE_UBO_WGSL, buildMeshStruct()];\n if (nodeUbo) {\n wgslParts.push(nodeUbo.struct);\n }\n if (textureWgslDecls.length > 0) {\n wgslParts.push(textureWgslDecls.join(\"\\n\"));\n }\n if (lightsWgslDecls) {\n wgslParts.push(lightsWgslDecls);\n }\n if (morphWgslDecls.length > 0) {\n wgslParts.push(morphWgslDecls.join(\"\\n\"));\n }\n if (envWgslDecls) {\n wgslParts.push(envWgslDecls);\n }\n wgslParts.push(vertexIn);\n wgslParts.push(vertexOut);\n if (fragmentOut) {\n wgslParts.push(fragmentOut);\n }\n if (shadowWgslDecls) {\n wgslParts.push(shadowWgslDecls);\n }\n if (_esmShadowParamsBinding !== null) {\n wgslParts.push(\n `struct NmeShadowParams { biasAndScale: vec4<f32>, depthValues: vec4<f32> };\\n@group(1) @binding(${_esmShadowParamsBinding}) var<uniform> nmeShadowParams: NmeShadowParams;`\n );\n }\n if (shadowFragmentHelper.length > 0) {\n wgslParts.push(shadowFragmentHelper);\n }\n for (const src of helperSources.values()) {\n wgslParts.push(src);\n }\n\n const vsSig = state.usesMorphTargets ? `(in: VertexIn, @builtin(vertex_index) vertexIndex: u32)` : `(in: VertexIn)`;\n wgslParts.push(\n `@vertex\\nfn vs_main${vsSig} -> VertexOut {\\n` +\n ` var out: VertexOut;\\n` +\n ` var ${SENTINEL_VTX_OUTPUT}: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 1.0);\\n` +\n `${indent(vertexBody)}\\n` +\n (!shadowOutput && shadowVertexInject.length > 0 ? ` ${shadowVertexInject}\\n` : ``) +\n ` out.position = ${SENTINEL_VTX_OUTPUT};\\n` +\n ` return out;\\n` +\n `}`\n );\n const fsReturnType = noColorOutput ? \"\" : state.usesFragDepth && !esmShadowOutput ? \" -> FragmentOut\" : \" -> @location(0) vec4<f32>\";\n const fragDepthDecl = noColorOutput || esmShadowOutput || state.usesFragDepth ? ` var ${SENTINEL_FRAG_DEPTH}: f32 = in.position.z;\\n` : \"\";\n const fsReturn = noColorOutput\n ? \"\"\n : esmShadowOutput\n ? `${indent(esmShadowDepthCode)}\\n`\n : state.usesFragDepth\n ? ` return FragmentOut(${SENTINEL_FRAG_OUTPUT}, ${SENTINEL_FRAG_DEPTH});\\n`\n : ` return ${SENTINEL_FRAG_OUTPUT};\\n`;\n wgslParts.push(\n `@fragment\\nfn fs_main(in: VertexOut, @builtin(front_facing) ${SENTINEL_FRONT_FACING}: bool)${fsReturnType} {\\n` +\n ` var ${SENTINEL_FRAG_OUTPUT}: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 1.0);\\n` +\n fragDepthDecl +\n `${indent(fragmentBody)}\\n` +\n fsReturn +\n `}`\n );\n const rawWgsl = wgslParts.join(\"\\n\\n\");\n // Substitute scene-uniform sentinels emitted by blocks (FogBlock, LightBlock,\n // ReflectionTextureBlock). These all resolve to scene-UBO fields.\n const _wgsl = rawWgsl\n .replaceAll(\"_NME_CAMERA_POS_\", \"scene.vEyePosition.xyz\")\n .replaceAll(\"_NME_FOG_PARAMS_\", \"scene.vFogInfos\")\n .replaceAll(\"sceneU.\", \"scene.\")\n .replaceAll(SENTINEL_FRAG_COORD, \"in.position\")\n .replaceAll(SENTINEL_SCREEN_SIZE, \"vec2<f32>(scene.vFogColor.w, scene._envPad0)\");\n\n const alphaMode = opts._alphaMode ?? 0;\n const depthFormat = opts._depthStencilFormat ?? \"depth24plus-stencil8\";\n const cacheKey = `${_wgsl}|${_format}|${depthFormat}|${_msaaSamples}|${opts._backFaceCulling !== false ? 1 : 0}|${alphaMode}|${noColorOutput ? 1 : esmShadowOutput ? 2 : 0}`;\n const cache = getCache(_engine);\n const existing = cache.get(cacheKey);\n if (existing) {\n return existing;\n }\n\n // Blend state for alpha-blended materials.\n const blend = alphaModeToBlend(alphaMode);\n const depthWriteEnabled = blend === undefined;\n\n const sceneBGL = getSceneBindGroupLayout(_engine);\n\n // group 1 BGL\n const meshBglEntries: GPUBindGroupLayoutEntry[] = [{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } }];\n if (_nodeUboBinding !== null) {\n meshBglEntries.push({ binding: _nodeUboBinding, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } });\n }\n for (const tb of _textureBindings) {\n meshBglEntries.push({ binding: tb._texBinding, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\", viewDimension: \"2d\" } });\n meshBglEntries.push({ binding: tb._sampBinding, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } });\n }\n if (_morphBindings !== null) {\n meshBglEntries.push({\n binding: _morphBindings._textureBinding,\n visibility: GPUShaderStage.VERTEX,\n texture: { sampleType: \"unfilterable-float\", viewDimension: \"2d\" },\n });\n meshBglEntries.push({\n binding: _morphBindings._uboBinding,\n visibility: GPUShaderStage.VERTEX,\n buffer: { type: \"uniform\", minBindingSize: 32 },\n });\n }\n if (_envBindings) {\n meshBglEntries.push(...envBglEntries);\n }\n if (shadowEmit) {\n meshBglEntries.push(...shadowEmit._bglEntries);\n }\n if (_esmShadowParamsBinding !== null) {\n meshBglEntries.push({ binding: _esmShadowParamsBinding, visibility: GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } });\n }\n const _meshBGL = device.createBindGroupLayout({ label: \"node-mesh\", entries: meshBglEntries });\n\n // Vertex buffers: one GPUVertexBufferLayout per declared attribute, each at location=i.\n const _vertexBuffers: GPUVertexBufferLayout[] = state.vertexAttributes.map((a, i) => ({\n arrayStride: a._arrayStride,\n stepMode: a._stepMode ?? \"vertex\",\n attributes: [{ format: a._gpuFormat, offset: a._offset ?? 0, shaderLocation: i }],\n }));\n\n const shaderModule = device.createShaderModule({ label: \"node-material\", code: _wgsl });\n\n const _pipeline = device.createRenderPipeline(\n noColorOutput\n ? {\n label: \"node-material-depth\",\n layout: device.createPipelineLayout({ bindGroupLayouts: [sceneBGL, _meshBGL] }),\n vertex: { module: shaderModule, entryPoint: \"vs_main\", buffers: _vertexBuffers },\n fragment: { module: shaderModule, entryPoint: \"fs_main\", targets: [] },\n depthStencil: { format: depthFormat, depthCompare: opts._depthCompare ?? REVERSE_DEPTH_COMPARE, depthWriteEnabled: true },\n multisample: { count: _msaaSamples },\n primitive: { topology: \"triangle-list\", cullMode: opts._backFaceCulling !== false ? \"back\" : \"none\" },\n }\n : {\n ...createDefaultPipelineDescriptor({\n _label: \"node-material\",\n _engine,\n _bgls: [sceneBGL, _meshBGL],\n _vertModule: shaderModule,\n _fragModule: shaderModule,\n _vertexBuffers,\n _format,\n _depthStencilFormat: opts._depthStencilFormat,\n _depthCompare: opts._depthCompare,\n _msaaSamples,\n _cullMode: opts._backFaceCulling !== false ? \"back\" : \"none\",\n _blend: esmShadowOutput ? undefined : blend,\n _depthWriteEnabled: esmShadowOutput || depthWriteEnabled,\n }),\n vertex: { module: shaderModule, entryPoint: \"vs_main\", buffers: _vertexBuffers },\n fragment: { module: shaderModule, entryPoint: \"fs_main\", targets: [!esmShadowOutput && blend ? { format: _format, blend } : { format: _format }] },\n }\n );\n\n const result: NodeCompileResult = {\n _wgsl,\n _pipeline,\n _meshBGL,\n _nodeUboSize,\n _nodeUboOffsets,\n _nodeUboBinding,\n _textureBindings,\n _morphBindings,\n _envBindings,\n _shadowBindings,\n _usesClipPlanes: state.usesClipPlanes,\n _usesMeshAttributeFlags: state.usesMeshAttributeExists,\n _esmShadowParamsBinding,\n };\n cache.set(cacheKey, result);\n return result;\n}\n\n// ─── Alpha mode → blend state ───────────────────────────────────────\n\n/** Map BJS alpha mode to a WebGPU blend state. Returns undefined for opaque (mode 0). */\nfunction alphaModeToBlend(mode: number): GPUBlendState | undefined {\n switch (mode) {\n case 1: // ALPHA_ADD\n return {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n };\n case 2: // ALPHA_COMBINE (standard)\n return {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n };\n case 7: // ALPHA_PREMULTIPLIED\n return {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n };\n default: // 0 = DISABLE and any unsupported mode\n return undefined;\n }\n}\n","/** Node Material — public API (real implementation).\n *\n * Scenes that don't reference these exports tree-shake the entire\n * `material/node/` subtree to zero bytes.\n *\n * Flow: `parseNodeMaterialFromSnippet`\n * → fetch or inline JSON\n * → parse (`parseNodeMaterialSource`)\n * → load referenced emitters (lazy per-block)\n * → emit WGSL bodies (`emitGraph`)\n * → wrap + compile GPU pipeline (`compileNodePipeline`)\n * → return NodeMaterial with `inputs` map + `_buildGroup` dispatcher.\n */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { MeshGroupBuilder, MeshGroupBuildResult } from \"../../render/renderable.js\";\nimport { parseNodeMaterialSource, findBlockByClassName } from \"./node-parser.js\";\nimport { loadGraphEmitters, emitGraph } from \"./node-emitter.js\";\nimport type { BlockEmitter, NodeBuildState, NodeGraph, NodeValueType } from \"./node-types.js\";\nimport type { Material } from \"../material.js\";\nimport { compileNodePipeline, type NodeCompileResult } from \"./node-pipeline.js\";\nimport type * as NodeEnv from \"./node-env.js\";\n\n// ─── Public API types ───────────────────────────────────────────────\n\n/** A compiled Node Material (Babylon NME graph). Exposes an `inputs` map of\n * named handles for live uniform/texture updates, and dispatches rendering\n * through the inherited `_buildGroup` hook. */\nexport interface NodeMaterial extends Material {\n readonly inputs: Record<string, NodeInputHandle>;\n /** @internal */\n readonly _compile: NodeCompileResult;\n /** @internal */\n readonly _state: NodeBuildState;\n /** @internal */\n readonly _graph: NodeGraph;\n /** @internal */\n readonly _vertexBody: string;\n /** @internal */\n readonly _fragmentBody: string;\n /** @internal Ordered list of vertex attribute names that the pipeline's vertex buffers expect. */\n readonly _vertexAttrNames: readonly string[];\n /** @internal */\n readonly _shadowGenerators: readonly import(\"../../shadow/shadow-generator.js\").ShadowGenerator[];\n /** @internal Whether this material requires alpha blending (derived from graph + JSON flags). */\n readonly _needsAlphaBlending: boolean;\n /** @internal */\n _nodeUBO: GPUBuffer | null;\n /** @internal */\n _uboDirty: boolean;\n /** @internal */\n _uniformValues: Map<string, UniformSlot>;\n /** @internal Per-texture-binding Texture2D slot (populated from options.textures and/or inputs.*.texture). */\n _textureSlots: Map<string, { current: Texture2D | null }>;\n /** @internal Pre-loaded env helpers (only populated when state.usesEnv was set during emitGraph).\n * Forwarded to the renderable so it doesn't have to dynamic-import again. */\n _envHelpers: typeof NodeEnv | null;\n /** @internal ESM shadow depth code emitted from the node graph (when shadow generators are present). */\n readonly _esmShadowDepthCode?: string;\n /** @internal ESM shadow params UBO buffer. */\n readonly _esmShadowParamsUBO?: GPUBuffer;\n}\n\n/** A live handle to one named Node Material input (uniform or texture). Set\n * `value` for scalar/vector inputs or `texture` for `texture2d` inputs; writes\n * flag the material UBO dirty so the change is uploaded next frame. */\nexport interface NodeInputHandle {\n readonly type: \"f32\" | \"vec2f\" | \"vec3f\" | \"vec4f\" | \"texture2d\";\n value?: number | number[];\n texture?: Texture2D | null;\n}\n\n/** Options for `parseNodeMaterialFromSnippet()`. */\nexport interface ParseNodeMaterialOptions {\n readonly snippetServer?: string;\n /** Pre-resolved JSON (object or string). When provided, bypasses the network. */\n readonly json?: string | object;\n /** Texture overrides keyed by TextureBlock / ImageSourceBlock name. */\n readonly textures?: Readonly<Record<string, Texture2D>>;\n /** Shadow generators to integrate into the material. Each contributes\n * one shadow-light slot whose lightIndex is the position of its light in\n * `scene.lights` at the time of rendering. Materials built without this\n * option have zero shadow bindings / zero shadow WGSL. */\n readonly shadowGenerators?: readonly import(\"../../shadow/shadow-generator.js\").ShadowGenerator[];\n /** For each entry in shadowGenerators, the index of the owning light in\n * scene.lights. When omitted, defaults to [0, 1, …] (first N lights). */\n readonly shadowLightIndices?: readonly number[];\n /** When true, BonesBlock produces a skinned world matrix (requires all\n * meshes using this material to have a skeleton). Default false. */\n readonly hasSkeleton?: boolean;\n /** When true, InstancesBlock wires per-instance attributes. Default false. */\n readonly hasInstances?: boolean;\n /** Optional graph-specific block loader. Avoids the full default registry when callers know the exact block set. */\n readonly blockLoader?: (className: string) => Promise<BlockEmitter>;\n}\n\n// ─── Internal shape (what the renderable + updater read) ────────────\n\n/** @internal */\ninterface UniformSlot {\n readonly _name: string;\n readonly _type: NodeValueType;\n readonly _offsetBytes: number;\n readonly _values: Float32Array;\n}\n\n// ─── Parse entry point ──────────────────────────────────────────────\n\n/** Parse a Babylon NME graph (by snippet ID or inline JSON), emit WGSL, compile\n * the GPU pipeline, and return a ready-to-render `NodeMaterial`.\n * @param engine - Engine context.\n * @param snippetId - Snippet server ID; ignored when `options.json` is supplied.\n * @param options - Inline JSON, texture overrides, shadow generators, and graph flags.\n * @returns A promise resolving to the compiled `NodeMaterial`. */\nexport async function parseNodeMaterialFromSnippet(engine: EngineContext, snippetId: string, options: ParseNodeMaterialOptions = {}): Promise<NodeMaterial> {\n const source =\n options.json !== undefined\n ? typeof options.json === \"string\"\n ? JSON.parse(options.json)\n : options.json\n : await (await import(\"./node-snippet.js\")).fetchSnippetSource(snippetId, options.snippetServer);\n\n const graph = parseNodeMaterialSource(source);\n const emitters = await loadGraphEmitters(graph, options.blockLoader);\n\n const fragRoot = findBlockByClassName(graph, \"FragmentOutputBlock\");\n if (!fragRoot) {\n throw new Error(\"NodeMaterial: graph has no FragmentOutputBlock\");\n }\n const vertRoot = findBlockByClassName(graph, \"VertexOutputBlock\");\n\n // Pre-populate shadow metadata BEFORE emitGraph so LightBlock can dispatch\n // to nme_computeShadowFactors(...) during emission. When no shadow\n // generators are supplied, state.shadowLights stays empty and zero shadow\n // WGSL / zero shadow bindings are emitted (tree-shakable).\n const shadowLightsPre: { lightIndex: number; shadowType: \"esm\" | \"pcf\" }[] = [];\n if (options.shadowGenerators && options.shadowGenerators.length > 0) {\n const defaultIdx = options.shadowGenerators.map((_, i) => i);\n const indices = options.shadowLightIndices ?? defaultIdx;\n for (let i = 0; i < options.shadowGenerators.length; i++) {\n shadowLightsPre.push({ lightIndex: indices[i]!, shadowType: options.shadowGenerators[i]!._shadowType });\n }\n }\n\n const { vertexWgsl, fragmentWgsl, state } = emitGraph(graph, emitters, fragRoot.id, vertRoot ? vertRoot.id : null, shadowLightsPre, {\n hasSkeleton: options.hasSkeleton ?? false,\n hasInstances: options.hasInstances ?? false,\n });\n await resolvePbrMrHelpers(state);\n\n // Dynamic import: env IBL helpers in node-env.ts are only loaded when the\n // graph emitted state.usesEnv. Scenes without ReflectionBlock+PBR-MR never\n // bundle this module.\n let envHelpers: typeof import(\"./node-env.js\") | null = null;\n let _envEmitter: typeof import(\"./node-env.js\").emitEnv | undefined;\n if (state.usesEnv) {\n envHelpers = await import(\"./node-env.js\");\n _envEmitter = envHelpers.emitEnv;\n }\n\n // Dynamic import: the PCF/ESM WGSL helpers live in node-shadow.ts and\n // are only loaded when the caller supplied shadowGenerators. Scenes\n // without shadows never bundle this module.\n let _shadowEmitter: typeof import(\"./node-shadow.js\").emitShadow | undefined;\n if (options.shadowGenerators && options.shadowGenerators.length > 0) {\n _shadowEmitter = (await import(\"./node-shadow.js\")).emitShadow;\n }\n\n const compile = compileNodePipeline(state, vertexWgsl, fragmentWgsl, {\n _engine: engine,\n _format: engine.format,\n _msaaSamples: engine.msaaSamples,\n _backFaceCulling: graph.backFaceCulling,\n _alphaMode: graph.needsAlphaBlending ? graph.alphaMode : 0,\n _envEmitter,\n _shadowEmitter,\n });\n\n // Build the `inputs` map: one NodeInputHandle per named uniform.\n const inputs: Record<string, NodeInputHandle> = {};\n const uniformValues = new Map<string, UniformSlot>();\n for (const [name, blockId] of graph.namedInputs) {\n const block = graph.blocks.get(blockId)!;\n const _name = sanitize(block.name || `input${block.id}`);\n const _offsetBytes = compile._nodeUboOffsets.get(_name);\n if (_offsetBytes === undefined) {\n continue;\n }\n const _type = bjsTypeToNodeType((block.serialized[\"type\"] as number | undefined) ?? 0x10);\n if (_type === \"mat4f\") {\n continue;\n }\n const len = floatCount(_type);\n const defaultValues = extractDefault(block.serialized[\"value\"], _type);\n const _values = new Float32Array(len);\n _values.set(defaultValues);\n const slot: UniformSlot = { _name, _type, _offsetBytes, _values };\n uniformValues.set(_name, slot);\n\n const handleType = handleTypeOf(_type);\n // capture material so the setter can mark it dirty.\n const setDirty = () => {\n material._uboDirty = true;\n };\n const handle: NodeInputHandle = {\n type: handleType,\n get value(): number | number[] {\n return handleType === \"f32\" ? slot._values[0]! : Array.from(slot._values);\n },\n set value(v: number | number[]) {\n if (typeof v === \"number\") {\n slot._values[0] = v;\n } else {\n slot._values.set(v);\n }\n setDirty();\n },\n } as NodeInputHandle;\n inputs[name] = handle;\n }\n\n // Second pass: write defaults for unnamed / constant InputBlocks whose\n // values exist in the UBO but were skipped by the namedInputs loop above\n // (e.g. blocks with empty names or isConstant=true).\n for (const block of graph.blocks.values()) {\n if (block.className !== \"InputBlock\") {\n continue;\n }\n const _name = sanitize(block.name || `input${block.id}`);\n if (uniformValues.has(_name)) {\n continue;\n } // already handled above\n const _offsetBytes = compile._nodeUboOffsets.get(_name);\n if (_offsetBytes === undefined) {\n continue;\n }\n const _type = bjsTypeToNodeType((block.serialized[\"type\"] as number | undefined) ?? 0x10);\n if (_type === \"mat4f\") {\n continue;\n }\n const len = floatCount(_type);\n const defaultValues = extractDefault(block.serialized[\"value\"], _type);\n const _values = new Float32Array(len);\n _values.set(defaultValues);\n uniformValues.set(_name, { _name, _type, _offsetBytes, _values });\n }\n\n const attrNames = state.vertexAttributes.map((a) => a._name);\n\n // Per-texture handles (populated from options.textures, then exposed via inputs).\n const textureSlots = new Map<string, { current: Texture2D | null }>();\n for (const tb of compile._textureBindings) {\n const slot = { current: options.textures?.[tb._name] ?? null };\n textureSlots.set(tb._name, slot);\n const handle: NodeInputHandle = {\n type: \"texture2d\",\n get texture(): Texture2D | null {\n return slot.current;\n },\n set texture(v: Texture2D | null) {\n slot.current = v;\n },\n } as NodeInputHandle;\n inputs[tb._name] = handle;\n }\n\n const _buildGroup: MeshGroupBuilder = async (scene, meshes): Promise<MeshGroupBuildResult> => {\n const { buildNodeMeshRenderables } = await import(\"./node-renderable.js\");\n const result = buildNodeMeshRenderables(scene, meshes);\n _buildGroup._rebuildSingle = result.rebuildSingle;\n return result;\n };\n _buildGroup._materialFamily = \"node\";\n\n const material: NodeMaterial = {\n inputs,\n _renderFeatures: { features: 0 },\n _buildGroup,\n _uboVersion: 0,\n _compile: compile,\n _state: state,\n _graph: graph,\n _vertexBody: vertexWgsl,\n _fragmentBody: fragmentWgsl,\n _vertexAttrNames: attrNames,\n _shadowGenerators: options.shadowGenerators ?? [],\n _needsAlphaBlending: graph.needsAlphaBlending,\n _nodeUBO: null,\n _uboDirty: false,\n _uniformValues: uniformValues,\n _textureSlots: textureSlots,\n _envHelpers: envHelpers,\n };\n return material;\n}\n\nfunction isCorePbrMrRequest(request: import(\"./node-types.js\").NodePbrMrHelperRequest): boolean {\n return (\n !request.useClearcoat &&\n !request.useSheen &&\n !request.useRefraction &&\n !request.useSubsurface &&\n !request.useAnisotropy &&\n !request.useShAlbedoScaling &&\n !request.useCcBump &&\n !request.useCcTint &&\n !request.useSpecularAA &&\n !request.remapClearcoatF0\n );\n}\n\nasync function resolvePbrMrHelpers(state: NodeBuildState): Promise<void> {\n if (state.pbrMrHelperRequests.length === 0) {\n return;\n }\n if (state.pbrMrHelperRequests.some((request) => !isCorePbrMrRequest(request))) {\n throw new Error(\"NodeMaterial: advanced PBR-MR helper request must be emitted by the full PBR-MR block\");\n }\n const core = await import(\"./blocks/pbr-mr-helper-core.js\");\n for (const request of state.pbrMrHelperRequests) {\n state.fragment.helpers.set(request.key, core.buildPbrMrHelperCore(request));\n }\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────\n\nfunction sanitize(name: string): string {\n return name.replace(/[^A-Za-z0-9_]/g, \"_\");\n}\n\nfunction bjsTypeToNodeType(t: number): NodeValueType {\n if (t === 0x1 || t === 0x2) {\n return \"f32\";\n }\n if (t === 0x4) {\n return \"vec2f\";\n }\n if (t === 0x8 || t === 0x20) {\n return \"vec3f\";\n }\n if (t === 0x10 || t === 0x40) {\n return \"vec4f\";\n }\n if (t === 0x80) {\n return \"mat4f\";\n }\n throw new Error(`NodeMaterial: unsupported BJS connection point type 0x${t.toString(16)}`);\n}\n\nfunction floatCount(type: NodeValueType): number {\n switch (type) {\n case \"f32\":\n return 1;\n case \"vec2f\":\n return 2;\n case \"vec3f\":\n return 3;\n case \"vec4f\":\n return 4;\n case \"mat4f\":\n return 16;\n default:\n return 0;\n }\n}\n\nfunction handleTypeOf(t: NodeValueType): NodeInputHandle[\"type\"] {\n if (t === \"mat4f\" || t === \"texture2d\" || t === \"textureCube\") {\n return \"vec4f\";\n }\n return t;\n}\n\nfunction extractDefault(raw: unknown, type: NodeValueType): number[] {\n const n = floatCount(type);\n if (typeof raw === \"number\") {\n return [raw];\n }\n if (Array.isArray(raw)) {\n const out = raw.slice(0, n).map((v) => (typeof v === \"number\" ? v : 0));\n while (out.length < n) {\n out.push(0);\n }\n return out;\n }\n if (raw && typeof raw === \"object\") {\n const obj = raw as Record<string, number>;\n const picks: number[] = [];\n for (const k of [\"x\", \"y\", \"z\", \"w\"]) {\n if (typeof obj[k] === \"number\") {\n picks.push(obj[k]);\n }\n }\n if (picks.length > 0) {\n while (picks.length < n) {\n picks.push(0);\n }\n return picks.slice(0, n);\n }\n const rgba: number[] = [];\n for (const k of [\"r\", \"g\", \"b\", \"a\"]) {\n if (typeof obj[k] === \"number\") {\n rgba.push(obj[k]);\n }\n }\n if (rgba.length > 0) {\n while (rgba.length < n) {\n rgba.push(1);\n }\n return rgba.slice(0, n);\n }\n }\n return new Array(n).fill(0);\n}\n\n// ─── UBO writer ─────────────────────────────────────────────────────\n\nexport function writeNodeUBO(engine: EngineContext, buffer: GPUBuffer, material: NodeMaterial): void {\n const size = material._compile._nodeUboSize;\n if (size === 0) {\n return;\n }\n const scratch = new Float32Array(size / 4);\n for (const slot of material._uniformValues.values()) {\n const dstIdx = slot._offsetBytes >> 2;\n scratch.set(slot._values, dstIdx);\n }\n engine._device.queue.writeBuffer(buffer, 0, scratch);\n}\n","/** NodeMaterial render-feature bits. */\n\nexport const NODE_NO_COLOR_OUTPUT = 1 << 0;\nexport const NODE_ESM_SHADOW_OUTPUT = 1 << 1;\n","/** NodeMaterial material view helper with no color output. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { NODE_NO_COLOR_OUTPUT } from \"./node-flags.js\";\nimport type { NodeMaterial } from \"./node-material.js\";\n\n/** Create a no-color view over a NodeMaterial source. */\nexport function createNodeNoColorMaterialView(source: NodeMaterial): MaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n return createMaterialView(source, { features: features.features | NODE_NO_COLOR_OUTPUT });\n}\n","import type { Material } from \"./material.js\";\nimport { getMaterialSource } from \"./material-view.js\";\n\n/** Mark a material source (or one of its views) as needing UBO re-upload.\n * The source owns a monotonic version so multiple renderables/views can observe\n * the same mutation independently without racing on a single cleared boolean. */\nexport function markMaterialUboDirty(materialOrView: Material): void {\n const source = getMaterialSource(materialOrView);\n source._uboVersion++;\n}\n","import type { SceneContext } from \"../scene/scene.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { Material } from \"./material.js\";\nimport { getMaterialSource, isMaterialView } from \"./material-view.js\";\n\nexport interface RebuildMaterialOptions {\n /** Rebuild views created from the same source material. Defaults to true. */\n rebuildViews?: boolean;\n /** Rebuild the frame graph after material renderables are refreshed. Defaults to false so callers can batch updates. */\n rebuildFrameGraph?: boolean;\n}\n\n/** Rebuild renderables whose pipeline/bind-group feature state depends on a material.\n * Use after texture, sampler, bind-group layout, culling, or feature changes.\n * UBO-only scalar/vector changes should use markMaterialUboDirty instead. */\nexport function rebuildMaterial(scene: SceneContext, materialOrView: Material, options?: RebuildMaterialOptions): void {\n const source = getMaterialSource(materialOrView);\n const rebuildViews = options?.rebuildViews !== false;\n let changed = false;\n\n for (const mesh of scene.meshes) {\n if (matchesMaterial(mesh.material, source, materialOrView, rebuildViews)) {\n rebuildSceneMesh(scene, mesh);\n changed = true;\n }\n }\n\n if (changed) {\n scene._renderableVersion++;\n }\n if (options?.rebuildFrameGraph) {\n scene._frameGraph.build();\n }\n}\n\nfunction matchesMaterial(meshMaterial: Material | null, source: Material, materialOrView: Material, rebuildViews: boolean): boolean {\n if (!meshMaterial) {\n return false;\n }\n if (!rebuildViews) {\n return meshMaterial === materialOrView;\n }\n return meshMaterial === source || (isMaterialView(meshMaterial) && meshMaterial.source === source);\n}\n\nfunction rebuildSceneMesh(ctx: SceneContext, mesh: Mesh): void {\n const material = mesh.material;\n if (!material) {\n return;\n }\n const rebuild = material._buildGroup._rebuildSingle;\n if (!rebuild) {\n return;\n }\n const old = ctx._meshDisposables.get(mesh);\n if (old) {\n for (const fn of old) {\n fn();\n }\n ctx._meshDisposables.delete(mesh);\n }\n for (let i = ctx._renderables.length - 1; i >= 0; i--) {\n if (ctx._renderables[i]!.mesh === mesh) {\n ctx._renderables.splice(i, 1);\n }\n }\n const renderable = rebuild(ctx, mesh);\n let i = ctx._renderables.length;\n while (i > 0 && ctx._renderables[i - 1]!.order > renderable.order) {\n i--;\n }\n ctx._renderables.splice(i, 0, renderable);\n}\n","/** Opt-in auto-dirty tracking for material properties.\n *\n * Import and call `enableMaterialTracking(material)` to install property\n * setters that automatically bump the source material UBO version on any mutation —\n * including in-place array writes like `material.diffuseColor[0] = 0.5`.\n *\n * The PBR and Standard tracking logic is dynamically imported so only the\n * relevant code is bundled. Scenes using only PBR materials never pull in\n * Standard tracking code, and vice versa. */\n\nimport type { Material } from \"./material.js\";\nimport { getMaterialSource } from \"./material-view.js\";\n\n/** Enable automatic dirty tracking on a PBR or Standard material.\n * After calling this, any UBO-backed property mutation marks the source material UBO dirty. */\nexport async function enableMaterialTracking(material: Material & { specularPower?: unknown }): Promise<void> {\n const source = getMaterialSource(material) as Material & { specularPower?: unknown };\n if (\"specularPower\" in source) {\n const { installStdTracking } = await import(\"./tracking/std-tracking.js\");\n installStdTracking(source as any);\n } else {\n const { installPbrTracking } = await import(\"./tracking/pbr-tracking.js\");\n installPbrTracking(source as any);\n }\n}\n","/** TransformNode — alias for SceneNode. A scene graph node with TRS, parent, and children.\n *\n * TransformNode is now a pure type alias for SceneNode, giving all scene entities\n * a common base. createTransformNode delegates to createSceneNode. */\n\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { initMeshTransform } from \"../mesh/mesh.js\";\nimport type { SceneNode } from \"./scene-node.js\";\nimport { createSceneNode, createSceneNodeFromMatrix } from \"./scene-node.js\";\n\nexport type { SceneNode } from \"./scene-node.js\";\n\n/** TransformNode is a SceneNode — pure type alias, no extra fields. */\nexport type TransformNode = SceneNode;\n\n/** Create a TransformNode (SceneNode) with TRS values and lazy world matrix.\n * Parameters: name, position (px,py,pz), rotation quaternion (qx,qy,qz,qw), scaling (sx,sy,sz). */\nexport function createTransformNode(name: string, px = 0, py = 0, pz = 0, qx = 0, qy = 0, qz = 0, qw = 1, sx = 1, sy = 1, sz = 1): TransformNode {\n return createSceneNode(name, px, py, pz, qx, qy, qz, qw, sx, sy, sz);\n}\n\n/** Deep-clone a SceneNode tree. Meshes are shallow-cloned (shared GPU buffers).\n * Lights, cameras, and other non-mesh/non-TN children are shallow-cloned. */\nexport function cloneTransformNode(src: SceneNode): SceneNode {\n const clone = src._localMatrix\n ? createSceneNodeFromMatrix(src.name + \"_clone\", src._localMatrix)\n : createTransformNode(\n src.name + \"_clone\",\n src.position.x,\n src.position.y,\n src.position.z,\n src.rotationQuaternion.x,\n src.rotationQuaternion.y,\n src.rotationQuaternion.z,\n src.rotationQuaternion.w,\n src.scaling.x,\n src.scaling.y,\n src.scaling.z\n );\n for (const child of src.children) {\n if (!(\"_gpu\" in child) && !(\"lightType\" in child)) {\n const childClone = cloneTransformNode(child);\n childClone.parent = clone;\n clone.children.push(childClone);\n } else if (\"_gpu\" in child) {\n const mesh = child as unknown as Mesh;\n const meshClone = {\n ...mesh,\n name: mesh.name + \"_clone\",\n _materialDirty: false,\n _gpu: { ...mesh._gpu },\n };\n initMeshTransform(\n meshClone,\n mesh.position.x,\n mesh.position.y,\n mesh.position.z,\n mesh.rotation.x,\n mesh.rotation.y,\n mesh.rotation.z,\n mesh.scaling.x,\n mesh.scaling.y,\n mesh.scaling.z\n );\n meshClone.parent = clone;\n clone.children.push(meshClone);\n } else {\n // Lights, cameras, other node types — shallow clone with fresh children array\n const childClone = { ...(child as Record<string, unknown>), name: (child as SceneNode).name + \"_clone\", children: [] } as unknown as SceneNode;\n childClone.parent = clone;\n clone.children.push(childClone);\n }\n }\n return clone;\n}\n","/**\n * Low-level glTF/GLB parsing helpers:\n * - Accessor resolution (buffer views → typed arrays)\n * - Image extraction (embedded or external)\n * - Node hierarchy traversal with memoized world-matrix computation\n */\nimport type { Mat4 } from \"../math/types.js\";\nimport { mat4ComposeInto } from \"../math/mat4-compose-into.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\n\n// glTF 2.0 component types\nconst FLOAT = 5126;\nconst UNSIGNED_SHORT = 5123;\nconst UNSIGNED_INT = 5125;\nconst UNSIGNED_BYTE = 5121;\n\n// glTF accessor type → component count\nexport const TYPE_SIZES: Record<string, number> = {\n SCALAR: 1,\n VEC2: 2,\n VEC3: 3,\n VEC4: 4,\n MAT2: 4,\n MAT3: 9,\n MAT4: 16,\n};\n\n// --- Accessor Resolution ---\n\nexport interface AccessorView {\n /** @internal */\n _data: ArrayBufferView;\n /** @internal */\n _count: number;\n /** @internal */\n _componentCount: number;\n}\n\nexport function resolveAccessor(json: any, binChunk: DataView, accessorIdx: number): AccessorView {\n const accessor = json.accessors[accessorIdx];\n const bufferView = json.bufferViews[accessor.bufferView];\n const componentCount = TYPE_SIZES[accessor.type] ?? 1;\n const byteOffset = (bufferView.byteOffset ?? 0) + (accessor.byteOffset ?? 0);\n const count = accessor.count;\n\n const baseOffset = binChunk.byteOffset + byteOffset;\n const ab = binChunk.buffer;\n\n switch (accessor.componentType) {\n case FLOAT:\n return { _data: new Float32Array(ab, baseOffset, count * componentCount), _count: count, _componentCount: componentCount };\n case UNSIGNED_SHORT:\n return { _data: new Uint16Array(ab, baseOffset, count * componentCount), _count: count, _componentCount: componentCount };\n case UNSIGNED_INT:\n return { _data: new Uint32Array(ab, baseOffset, count * componentCount), _count: count, _componentCount: componentCount };\n case UNSIGNED_BYTE:\n return { _data: new Uint8Array(ab, baseOffset, count * componentCount), _count: count, _componentCount: componentCount };\n default:\n throw new Error(`Unsupported component type: ${accessor.componentType}`);\n }\n}\n\n// --- Image Extraction ---\n\n/** Resolve the image index for a glTF texture, honoring alternate-source\n * extensions such as EXT_texture_webp (WebP decode is native in\n * createImageBitmap, so no extra module is required — we only need to\n * pick the correct image source). */\nexport function getTextureImageIndex(tex: any): number {\n return tex.extensions?.EXT_texture_webp?.source ?? tex.source;\n}\n\nexport async function resolveImage(json: any, binChunk: DataView, imageIdx: number, baseUrl: string): Promise<ImageBitmap> {\n const image = json.images[imageIdx];\n\n if (image.bufferView !== undefined) {\n // Embedded in binary chunk (GLB)\n const bv = json.bufferViews[image.bufferView];\n const offset = binChunk.byteOffset + (bv.byteOffset ?? 0);\n const slice = binChunk.buffer.slice(offset, offset + bv.byteLength);\n const blob = new Blob([slice as ArrayBuffer], { type: image.mimeType ?? \"image/png\" });\n return createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" });\n }\n\n if (image.uri) {\n // External URI (relative to .gltf base URL)\n const imageUrl = new URL(image.uri, baseUrl + \"x\").href;\n const response = await fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Failed to load image: ${response.status} ${response.statusText}`);\n }\n const blob = await response.blob();\n const bmp = await createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" });\n return bmp;\n }\n\n throw new Error(\"Image has neither bufferView nor uri\");\n}\n\n// --- Node Hierarchy → World Matrix (Memoized) ---\n\n// Babylon.js RH→LH root: rotation [0,1,0,0] + scale [1,1,-1] = diag(-1,1,1,1)\n// prettier-ignore\nconst RH_TO_LH_ROOT = new Float32Array([-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]) as Mat4;\n\n/** Build a parent index map by scanning node.children arrays once. O(n). */\nexport function buildParentMap(json: any): Map<number, number> {\n const parentMap = new Map<number, number>();\n const nodes = json.nodes ?? [];\n for (let i = 0; i < nodes.length; i++) {\n const children = nodes[i].children;\n if (children) {\n for (const childIdx of children) {\n parentMap.set(childIdx as number, i);\n }\n }\n }\n return parentMap;\n}\n\n/** Look up a node's parent using the pre-built parent map. O(1). */\nexport function findParent(parentMap: Map<number, number>, childIdx: number): number {\n return parentMap.get(childIdx) ?? -1;\n}\n\n/**\n * Compute world matrix for a glTF node with memoization.\n * Uses parentMap for O(1) parent lookup and cache for O(1) repeat queries.\n * Total cost across all nodes: O(n) instead of O(n²).\n *\n * Zero-alloc path for the TRS case (common): `local` is composed into a shared\n * scratch via `mat4ComposeInto`, then multiplied into the freshly-allocated\n * `world` via `mat4MultiplyInto`. Only one Float32Array allocation per node\n * (the cached world matrix itself) instead of two. Recursion always resolves\n * `parentWorld` before touching the scratch, so the shared buffer is safe.\n */\nexport function computeNodeWorldMatrix(json: any, nodeIdx: number, parentMap: Map<number, number>, cache: Map<number, Mat4>): Mat4 {\n const cached = cache.get(nodeIdx);\n if (cached) {\n return cached;\n }\n\n const node = json.nodes[nodeIdx];\n const parentIdx = findParent(parentMap, nodeIdx);\n // Resolve parent FIRST so any recursive call can safely reuse the shared scratch below.\n const parentWorld: Mat4 = parentIdx !== -1 ? computeNodeWorldMatrix(json, parentIdx, parentMap, cache) : RH_TO_LH_ROOT;\n\n let localBuf: Float32Array;\n if (node.matrix) {\n // Pre-built matrix — copy into a fresh Float32Array (cannot alias scratch safely across calls).\n localBuf = new Float32Array(node.matrix);\n } else {\n const t = node.translation ?? [0, 0, 0];\n const r = node.rotation ?? [0, 0, 0, 1];\n const s = node.scale ?? [1, 1, 1];\n const scratch = _getLocalScratch();\n mat4ComposeInto(scratch, 0, t[0], t[1], t[2], r[0], r[1], r[2], r[3], s[0], s[1], s[2]);\n localBuf = scratch;\n }\n\n const world = new Float32Array(16) as Mat4;\n mat4MultiplyInto(world, 0, parentWorld, 0, localBuf, 0);\n\n cache.set(nodeIdx, world);\n return world;\n}\n\n// Lazy-init shared scratch for TRS composition. Module-level `new Float32Array` would kill\n// tree-shaking per GUIDANCE — defer until first use.\nlet _localScratch: Float32Array | null = null;\nfunction _getLocalScratch(): Float32Array {\n if (!_localScratch) {\n _localScratch = new Float32Array(16);\n }\n return _localScratch;\n}\n","/**\n * glTF core PBR material assembly:\n * - Extracts core PBR properties (baseColor, MR, normal, ORM, emissive)\n * - Handles alpha modes and double-sided flag\n *\n * All KHR material extensions (clearcoat, sheen, anisotropy, spec-gloss, ...)\n * are handled by separate `gltf-ext-*.ts` modules driven by the GltfFeature\n * registry in load-gltf.ts. This core file knows ZERO extension names.\n */\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getTextureImageIndex, resolveImage } from \"./gltf-parser.js\";\n\n/** Per-load context handed to each material extension's `applyMaterial()`. */\nexport interface GltfMatExtCtx {\n /** @internal Internal engine access for dynamic-only texture extensions that must upload directly. */\n _engine: EngineContext;\n /** Fetch + upload a texture from a glTF textureInfo object.\n * Returns undefined if texInfo is null/undefined. */\n /** @internal */\n _texture(texInfo: unknown, sRGB: boolean): Promise<Texture2D | undefined>;\n /** @internal Upload an arbitrary ImageBitmap (e.g. composited bitmap from an ext). */\n _uploadImage(bitmap: ImageBitmap, sRGB: boolean): Texture2D;\n}\n\n/** Parsed core PBR material data. */\nexport interface GltfMaterialData {\n /** @internal */\n _baseColorFactor: [number, number, number, number];\n /** @internal */\n _metallicFactor: number;\n /** @internal */\n _roughnessFactor: number;\n /** @internal */\n _emissiveFactor: [number, number, number];\n /** @internal */\n _baseColorImage: ImageBitmap | null;\n /** @internal */\n _metallicRoughnessImage: ImageBitmap | null;\n /** @internal */\n _normalImage: ImageBitmap | null;\n /** @internal glTF normalTexture.scale (default 1.0). */\n _normalScale: number;\n /** @internal glTF occlusionTexture.texCoord (default 0). */\n _occlusionTexCoord: number;\n /** @internal */\n _occlusionImage: ImageBitmap | null;\n /** @internal */\n _emissiveImage: ImageBitmap | null;\n /** @internal Whether material is double-sided. */\n _doubleSided: boolean;\n /** @internal glTF alphaMode: \"OPAQUE\" (default), \"BLEND\", or \"MASK\". */\n _alphaMode: string;\n /** @internal glTF alphaCutoff for MASK mode (default 0.5). */\n _alphaCutoff: number;\n /** Raw glTF material definition. Always set so ext modules can read raw\n * extension data + KHR_texture_transform from texture infos. */\n /** @internal */\n _rawMatDef?: any;\n}\n\n/** Assemble core PBR material data from a glTF material definition.\n *\n * Per-material extension parsing/fetching is handled by load-gltf.ts using\n * the GltfMatExt registry — this function only fills in the spec-baseline\n * PBR properties shared by every material. */\nexport async function assembleMaterial(\n json: any,\n binChunk: DataView,\n materialIdx: number,\n baseUrl: string,\n imageCache?: Map<number, Promise<ImageBitmap>>\n): Promise<GltfMaterialData> {\n const mat = json.materials?.[materialIdx];\n if (!mat) {\n return {\n _baseColorFactor: [1, 1, 1, 1],\n _metallicFactor: 1,\n _roughnessFactor: 1,\n _emissiveFactor: [0, 0, 0],\n _baseColorImage: null,\n _metallicRoughnessImage: null,\n _normalImage: null,\n _normalScale: 1,\n _occlusionTexCoord: 0,\n _occlusionImage: null,\n _emissiveImage: null,\n _doubleSided: false,\n _alphaMode: \"OPAQUE\",\n _alphaCutoff: 0.5,\n };\n }\n\n const pbr = mat.pbrMetallicRoughness ?? {};\n const fetchImg = makeImageFetcher(json, binChunk, baseUrl, imageCache);\n\n const [baseColorImg, mrImg, normalImg, occlusionImg, emissiveImg] = await Promise.all([\n fetchImg(pbr.baseColorTexture),\n fetchImg(pbr.metallicRoughnessTexture),\n fetchImg(mat.normalTexture),\n fetchImg(mat.occlusionTexture),\n fetchImg(mat.emissiveTexture),\n ]);\n\n return {\n _baseColorFactor: pbr.baseColorFactor ?? [1, 1, 1, 1],\n _metallicFactor: pbr.metallicFactor ?? 1,\n _roughnessFactor: pbr.roughnessFactor ?? 1,\n _emissiveFactor: mat.emissiveFactor ?? [0, 0, 0],\n _baseColorImage: baseColorImg,\n _metallicRoughnessImage: mrImg,\n _normalImage: normalImg,\n _normalScale: typeof mat.normalTexture?.scale === \"number\" ? mat.normalTexture.scale : 1,\n _occlusionTexCoord: typeof mat.occlusionTexture?.texCoord === \"number\" ? mat.occlusionTexture.texCoord : 0,\n _occlusionImage: occlusionImg,\n _emissiveImage: emissiveImg,\n _doubleSided: !!mat.doubleSided,\n _alphaMode: mat.alphaMode ?? \"OPAQUE\",\n _alphaCutoff: mat.alphaCutoff ?? 0.5,\n _rawMatDef: mat,\n };\n}\n\n/** Build a per-load image fetcher that decodes glTF texture references via\n * the shared image cache. Used by both core assembleMaterial and the ext\n * driver in load-gltf.ts. */\nexport function makeImageFetcher(json: any, binChunk: DataView, baseUrl: string, imageCache?: Map<number, Promise<ImageBitmap>>): (texInfo: any) => Promise<ImageBitmap | null> {\n return (texInfo: any): Promise<ImageBitmap | null> => {\n if (!texInfo) {\n return Promise.resolve(null);\n }\n const imgIdx: number = getTextureImageIndex(json.textures[texInfo.index]);\n if (imageCache) {\n let cached = imageCache.get(imgIdx);\n if (!cached) {\n cached = resolveImage(json, binChunk, imgIdx, baseUrl);\n imageCache.set(imgIdx, cached);\n }\n return cached;\n }\n return resolveImage(json, binChunk, imgIdx, baseUrl);\n };\n}\n","/** Calculate full mip chain count for a given width/height. */\nexport function mipLevelCount(width: number, height: number): number {\n return Math.floor(Math.log2(Math.max(width, height))) + 1;\n}\n\n/** Calculate mip levels needed by transmission refraction, whose shader samples with a fixed LOD bias. */\nexport function biasedMipLevelCount(width: number, height: number, lodBias: number): number {\n const maxDim = Math.max(width, height);\n return Math.max(1, Math.floor(Math.log2(maxDim) - lodBias) + 1);\n}\n","/** Convert linear [0,1] to sRGB [0,255] using the IEC 61966-2-1 transfer curve. */\nexport function linearToSrgbByte(v: number): number {\n const c = Math.max(0, Math.min(1, v));\n return Math.round((c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055) * 255);\n}\n","/** Shared PBR-material assembly + texture upload + ext-layer merging.\n * Used by both the core loader (`load-gltf.ts`) and the variants loader\n * (`gltf-variants.ts`) so they can't drift. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport { pbrGroupBuilder } from \"../material/pbr/pbr-material.js\";\nimport type { GltfMaterialData, GltfMatExtCtx } from \"./gltf-material.js\";\nimport type { GltfFeature } from \"./gltf-feature.js\";\nimport { mipLevelCount } from \"../texture/mip-count.js\";\nimport { linearToSrgbByte } from \"../math/color.js\";\n\n/** Texture post-processor composed from every active feature's `wrapTexture`\n * hook. Identity when no feature contributes one (common case). Kept simple\n * so the core loader stays feature-agnostic and tree-shakes cleanly. */\nexport type TextureWrapFn = (tex: Texture2D, texInfo: unknown) => Texture2D;\nexport const identityTexWrap: TextureWrapFn = (tex) => tex;\n\nexport type GenerateMipmapsFn = (engine: EngineContext, texture: GPUTexture, face?: number) => void;\n\nexport function uploadTex(\n engine: EngineContext,\n bitmap: ImageBitmap | null,\n srgb: boolean,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n fallback?: Uint8Array\n): Texture2D {\n const device = engine._device;\n const w = bitmap?.width ?? 1;\n const h = bitmap?.height ?? 1;\n const fmt: GPUTextureFormat = srgb ? \"rgba8unorm-srgb\" : \"rgba8unorm\";\n const mips = bitmap ? mipLevelCount(w, h) : 1;\n const tex = device.createTexture({\n size: { width: w, height: h },\n format: fmt,\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,\n mipLevelCount: mips,\n });\n if (bitmap) {\n device.queue.copyExternalImageToTexture({ source: bitmap }, { texture: tex, premultipliedAlpha: false }, { width: w, height: h });\n generateMipmaps(engine, tex);\n } else {\n device.queue.writeTexture({ texture: tex }, (fallback ?? new Uint8Array([255, 255, 255, 255])) as Uint8Array<ArrayBuffer>, { bytesPerRow: 4 }, { width: 1, height: 1 });\n }\n const result: Texture2D = {\n texture: tex,\n view: tex.createView(),\n sampler,\n width: w,\n height: h,\n };\n engine._dlr?.b(result, bitmap, srgb, !!bitmap, fallback);\n return result;\n}\n\n/** Assemble a PbrMaterialProps from parsed glTF material data + already-uploaded\n * textures + per-ext fragment overrides. Fast-path: no wrapTex, no occlusionOnUv2,\n * no occlusionTexture. Slow-path additions live in gltf-pbr-builder-ext.ts. */\nexport function assemblePbrProps(\n mat: GltfMaterialData,\n baseColorTexture: Texture2D,\n ormTexture: Texture2D,\n normalTexture: Texture2D | undefined,\n emissiveTexture: Texture2D | undefined,\n extLayers: Partial<PbrMaterialProps> | undefined\n): PbrMaterialProps {\n const ef = mat._emissiveFactor;\n const defaultFactor = (ef[0] === 1 && ef[1] === 1 && ef[2] === 1) || (ef[0] === 0 && ef[1] === 0 && ef[2] === 0);\n return {\n baseColorTexture,\n normalTexture,\n ormTexture,\n emissiveTexture,\n ...(mat._baseColorImage && !isDefaultBaseColorFactor(mat._baseColorFactor) ? { baseColorFactor: mat._baseColorFactor } : undefined),\n doubleSided: mat._doubleSided,\n occlusionStrength: mat._occlusionImage ? 1.0 : 0,\n ...(mat._normalScale !== 1 ? { normalTextureScale: mat._normalScale } : undefined),\n ...(mat._metallicRoughnessImage ? { metallicFactor: mat._metallicFactor, roughnessFactor: mat._roughnessFactor } : undefined),\n ...(!defaultFactor ? { emissiveColor: [ef[0], ef[1], ef[2]] as [number, number, number] } : undefined),\n enableSpecularAA: true,\n ...(mat._alphaMode === \"BLEND\" ? { alphaBlend: true, alpha: mat._baseColorFactor[3] } : undefined),\n ...(mat._alphaMode === \"MASK\" ? { alpha: mat._baseColorFactor[3], alphaCutOff: mat._alphaCutoff } : undefined),\n ...(mat._rawMatDef?.name ? { name: mat._rawMatDef.name as string } : undefined),\n ...extLayers,\n _buildGroup: pbrGroupBuilder,\n _uboVersion: 0,\n } as PbrMaterialProps;\n}\n\nfunction isDefaultBaseColorFactor(f: readonly number[]): boolean {\n return f[0] === 1 && f[1] === 1 && f[2] === 1 && f[3] === 1;\n}\n\n/** Build the always-present default textures (base color + ORM) from a parsed glTF material.\n * Fast-path version: no wrapTex, no occlusion-on-uv2 handling. The slow path lives\n * in gltf-pbr-builder-ext.ts and is lazy-loaded only when needed. */\nexport function buildDefaultPbrTextures(\n engine: EngineContext,\n mat: GltfMaterialData,\n sampler: GPUSampler,\n generateMipmaps: GenerateMipmapsFn,\n getCachedTex: (bitmap: ImageBitmap, srgb: boolean) => Texture2D\n): { baseColorTexture: Texture2D; ormTexture: Texture2D; normalTexture: Texture2D | undefined; emissiveTexture: Texture2D | undefined } {\n const baseColorTexture = mat._baseColorImage\n ? getCachedTex(mat._baseColorImage, true)\n : (() => {\n const f = mat._baseColorFactor;\n return uploadTex(\n engine,\n null,\n true,\n sampler,\n generateMipmaps,\n new Uint8Array([linearToSrgbByte(f[0]), linearToSrgbByte(f[1]), linearToSrgbByte(f[2]), Math.round(Math.max(0, Math.min(1, f[3])) * 255)])\n );\n })();\n const normalTexture = mat._normalImage ? getCachedTex(mat._normalImage, false) : undefined;\n const emissiveTexture = mat._emissiveImage ? getCachedTex(mat._emissiveImage, true) : undefined;\n\n const single = mat._metallicRoughnessImage ?? mat._occlusionImage;\n let ormTexture: Texture2D;\n if (single && (!mat._metallicRoughnessImage || !mat._occlusionImage || mat._metallicRoughnessImage === mat._occlusionImage)) {\n ormTexture = getCachedTex(single, false);\n } else if (!single) {\n const clamp = (v: number) => Math.round(Math.max(0, Math.min(1, v)) * 255);\n ormTexture = uploadTex(engine, null, false, sampler, generateMipmaps, new Uint8Array([255, clamp(mat._roughnessFactor), clamp(mat._metallicFactor), 255]));\n } else {\n ormTexture = getCachedTex(mat._metallicRoughnessImage!, false);\n }\n return { baseColorTexture, ormTexture, normalTexture, emissiveTexture };\n}\n\n/** Run all material-layer features and merge their fragments. */\nexport async function runMatExts(mat: GltfMaterialData, exts: GltfFeature[], ctx: GltfMatExtCtx): Promise<Partial<PbrMaterialProps> | undefined> {\n if (!exts.length) {\n return undefined;\n }\n const fragments = await Promise.all(exts.map((ext) => ext.applyMaterial!(mat, ctx)));\n let layers: Partial<PbrMaterialProps> | undefined;\n for (const f of fragments) {\n if (f) {\n layers ??= {};\n Object.assign(layers, f);\n }\n }\n return layers;\n}\n","import type { Mat4 } from \"../math/types.js\";\nimport { computeAabb } from \"../math/compute-aabb.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { TransformNode } from \"../scene/transform-node.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\nimport { createTransformNode } from \"../scene/transform-node.js\";\nimport { createSceneNodeFromMatrix } from \"../scene/scene-node.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport type { Mesh, MeshGPU } from \"../mesh/mesh.js\";\nimport { initMeshTransform } from \"../mesh/mesh.js\";\nimport { getOrCreateSampler } from \"../resource/gpu-pool.js\";\nimport { createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport { resolveAccessor, buildParentMap, computeNodeWorldMatrix, getTextureImageIndex, TYPE_SIZES } from \"./gltf-parser.js\";\nimport type { AccessorView } from \"./gltf-parser.js\";\nimport type { GltfVb } from \"./gltf-interleave.js\";\nimport type { GltfMaterialData, GltfMatExtCtx } from \"./gltf-material.js\";\nimport { assembleMaterial, makeImageFetcher } from \"./gltf-material.js\";\nimport type { DecodedPrimitive, GltfFeature, GltfLoadCtx } from \"./gltf-feature.js\";\nimport type { TextureWrapFn } from \"./gltf-pbr-builder.js\";\nimport { assemblePbrProps, buildDefaultPbrTextures, identityTexWrap, runMatExts, uploadTex } from \"./gltf-pbr-builder.js\";\nimport type * as GltfPbrBuilderExt from \"./gltf-pbr-builder-ext.js\";\n\n/** Dynamically-imported interleave module — loaded only when an asset actually\n * contains a strided bufferView, so non-interleaved scenes pay zero cost. */\ntype InterleaveModule = typeof import(\"./gltf-interleave.js\");\nlet _interleavePromise: Promise<InterleaveModule> | undefined;\nfunction loadInterleave(): Promise<InterleaveModule> {\n return (_interleavePromise ??= import(\"./gltf-interleave.js\"));\n}\n\n/** Parsed mesh data ready for GPU upload. */\nexport interface GltfMeshData {\n /** @internal Tight CPU positions, or null when sourced from an interleaved\n * bufferView (in which case `_vb._p` holds the strided source for lazy de-striding). */\n _positions: Float32Array | null;\n /** @internal */\n _normals: Float32Array | null;\n /** @internal */\n _tangents: Float32Array | null;\n /** @internal */\n _uvs: Float32Array | null;\n /** @internal */\n _uv2s: Float32Array | null;\n /** @internal */\n _colors: Float32Array | null;\n /** @internal */\n _indices: Uint16Array | Uint32Array;\n /** @internal */\n _vertexCount: number;\n /** @internal */\n _indexCount: number;\n /** @internal */\n _worldMatrix: Mat4;\n /** @internal */\n _material: GltfMaterialData;\n /** @internal Interleaved vertex sources (genuine GPU interleaving + lazy CPU de-stride).\n * Absent → all tight. */\n _vb?: GltfVb;\n /** @internal glTF node index this mesh came from (for hierarchy reconstruction\n * and for features that need to resolve skin/morph data lazily). */\n _nodeIndex: number;\n /** @internal Raw primitive definition — features (skeleton, morph, …) read their\n * own attributes/targets from here without bloating core extraction. */\n _primitive: any;\n /** @internal Pre-decoded primitive (Draco et al.) if a preMesh feature produced one. */\n _decoded?: DecodedPrimitive;\n}\n\n/**\n * Load a .glb or .gltf file, parse it, and upload mesh + material data to GPU.\n * Supports both binary GLB and separate .gltf + .bin + image files.\n * Registers a deferred PBR renderable builder.\n * Automatically parses glTF animations if present.\n *\n * Returns a AssetContainer. Pass it to addToScene() which adds the hierarchy,\n * registers animation ticks, and applies any scene-level settings.\n */\nexport async function loadGltf(engine: EngineContext, url: string): Promise<AssetContainer> {\n const { json, binChunk, baseUrl } = await fetchGltfAsset(url);\n\n // Build parent map + world-matrix cache once for O(n) hierarchy traversal\n const parentMap = buildParentMap(json);\n const worldMatrixCache = new Map<number, Mat4>();\n\n // Discover every triggered feature (material exts, skeleton, morph,\n // animations, variants, …) and dynamic-import them concurrently with\n // mesh extraction. Core loader knows zero feature names.\n const features = await loadGltfFeatures(json);\n\n // Pre-parse hooks (EXT_meshopt_compression decompression, KHR_mesh_quantization\n // dequantization) may rewrite bufferViews/accessors and hand back a replacement\n // binary chunk. Run sequentially in registry order so later features see earlier\n // rewrites. No-op (and zero cost) when no triggered feature defines preParse.\n let activeBin = binChunk;\n for (const f of features) {\n if (f.preParse) {\n const replacement = await f.preParse(json, activeBin);\n if (replacement) {\n activeBin = replacement;\n }\n }\n }\n\n const matExts: GltfFeature[] = features.filter((f) => f.applyMaterial);\n // Compose every feature's wrapTexture hook into a single function. Identity\n // when no feature contributes one (common case) — keeps the hot path free\n // of per-texture work and lets bundlers tree-shake the helpers.\n const texWraps = features.filter((f) => f.wrapTexture).map((f) => f.wrapTexture!);\n const wrapTex: TextureWrapFn = !texWraps.length ? identityTexWrap : (tex, ti) => texWraps.reduce((acc, w) => w(acc, ti), tex);\n\n // Run every feature's pre-mesh hook (e.g. Draco decompression) and merge\n // their primitive-keyed decode caches. Features without `preMesh` contribute\n // nothing; the map stays empty when no primitive-level feature triggered.\n const decodedPrimitives = new Map<unknown, DecodedPrimitive>();\n for (const frag of await Promise.all(features.flatMap((f) => (f.preMesh ? [f.preMesh(json, activeBin, baseUrl)] : [])))) {\n for (const [k, v] of frag) {\n decodedPrimitives.set(k, v);\n }\n }\n\n const meshDatas = await extractAllMeshes(json, activeBin, baseUrl, parentMap, worldMatrixCache, decodedPrimitives);\n\n const ctx: GltfLoadCtx = {\n _engine: engine,\n _json: json,\n _binChunk: activeBin,\n _baseUrl: baseUrl,\n _parentMap: parentMap,\n _worldMatrixCache: worldMatrixCache,\n _matExts: matExts,\n _wrapTex: wrapTex,\n };\n\n const meshes = await uploadMeshes(meshDatas, features, ctx);\n\n // Build TransformNode hierarchy from glTF nodes. Returns both the synthetic root\n // and a glTF-node-index → SceneNode map (used by node-visibility + animation-pointer).\n const { root, nodeMap } = buildNodeHierarchy(json, meshes, meshDatas);\n ctx._nodeMap = nodeMap;\n\n // Run every feature's per-asset hook (animations, variants, …) and merge\n // the returned AssetContainer fragments. `entities` is appended (never\n // overwritten) so features like KHR_lights_punctual can contribute lights\n // without trampling the root TransformNode.\n const assetFragments = await Promise.all(features.flatMap((f) => (f.applyAsset ? [f.applyAsset(meshes, root, ctx)] : [])));\n const container: AssetContainer = { entities: [root] };\n for (const frag of assetFragments) {\n if (frag.entities?.length) {\n container.entities.push(...frag.entities);\n }\n const { entities: _ignored, ...rest } = frag;\n void _ignored;\n Object.assign(container, rest);\n }\n return container;\n}\n\n// --- glTF Feature Driver ---\n\n/** A glTF feature: per-asset gating + dynamic-import of a `GltfFeature` module.\n * Unknown features contribute zero bytes when their `needs(json)` returns false.\n * Stored as a tuple [needs, load] for bundle-size reasons. */\ntype GltfFeatureLoader = [(json: any) => boolean, () => Promise<{ default: GltfFeature }>];\n\n/** Fetch + parse a .glb or .gltf asset. Returns the JSON, binary chunk, and base URL. */\nasync function fetchGltfAsset(url: string): Promise<{ json: any; binChunk: DataView; baseUrl: string }> {\n const baseUrl = url.substring(0, url.lastIndexOf(\"/\") + 1);\n if (url.toLowerCase().endsWith(\".glb\")) {\n const buffer = await fetch(url).then((r) => r.arrayBuffer());\n const { parseGlbContainer } = await import(\"./gltf-glb-parser.js\");\n const { json, binChunk } = parseGlbContainer(buffer);\n return { json, binChunk, baseUrl };\n }\n const json = await fetch(url).then((r) => r.json());\n const bufferDef = json.buffers?.[0];\n let binChunk: DataView;\n if (bufferDef?.uri) {\n const binUrl = new URL(bufferDef.uri, baseUrl + \"x\").href;\n const binBuffer = await fetch(binUrl).then((r) => r.arrayBuffer());\n binChunk = new DataView(binBuffer);\n } else {\n binChunk = new DataView(new ArrayBuffer(0));\n }\n return { json, binChunk, baseUrl };\n}\n\n/** Returns true if any mesh primitive in the asset matches `pred`. */\nfunction anyPrimitive(json: any, pred: (p: any) => boolean): boolean {\n for (const m of json.meshes ?? []) {\n for (const p of m.primitives ?? []) {\n if (pred(p)) {\n return true;\n }\n }\n }\n return false;\n}\n\nconst _MAT_EXT = \"KHR_materials_\";\nconst hasMatExt =\n (suffix: string) =>\n (json: any): boolean =>\n json.extensionsUsed?.includes(_MAT_EXT + suffix);\nconst hasExt =\n (name: string) =>\n (json: any): boolean =>\n json.extensionsUsed?.includes(name);\n\n/** Asset has at least one material that needs ORM compositing\n * (separate metallicRoughnessTexture + occlusionTexture pointing at different images). */\nfunction needsOrmComposite(json: any): boolean {\n const mats = json.materials ?? [];\n const textures = json.textures ?? [];\n for (const m of mats) {\n const mr = m.pbrMetallicRoughness?.metallicRoughnessTexture;\n const occ = m.occlusionTexture;\n if (mr && occ && textures[mr.index] && textures[occ.index] && getTextureImageIndex(textures[mr.index]) !== getTextureImageIndex(textures[occ.index])) {\n return true;\n }\n }\n return false;\n}\n\nconst _features: GltfFeatureLoader[] = [\n // Pre-parse features (buffer-level): order matters — meshopt decompresses\n // bufferViews first, then quantization dequantizes the resulting accessors.\n [hasExt(\"EXT_meshopt_compression\"), () => import(\"./gltf-feature-meshopt.js\")],\n [hasExt(\"KHR_mesh_quantization\"), () => import(\"./gltf-ext-quantization.js\")],\n // Pre-mesh features (geometry decompression)\n [hasExt(\"KHR_draco_mesh_compression\"), () => import(\"./gltf-feature-draco.js\")],\n // Material extensions\n [hasMatExt(\"clearcoat\"), () => import(\"./gltf-ext-clearcoat.js\")],\n [hasMatExt(\"iridescence\"), () => import(\"./gltf-ext-iridescence.js\")],\n [hasMatExt(\"emissive_strength\"), () => import(\"./gltf-ext-emissive-strength.js\")],\n [hasMatExt(\"sheen\"), () => import(\"./gltf-ext-sheen.js\")],\n [hasMatExt(\"anisotropy\"), () => import(\"./gltf-ext-anisotropy.js\")],\n [hasMatExt(\"unlit\"), () => import(\"./gltf-ext-unlit.js\")],\n [hasMatExt(\"pbrSpecularGlossiness\"), () => import(\"./gltf-ext-spec-gloss.js\")],\n // Dielectric cluster (ior/specular/transmission/volume) — any of the four triggers the loader;\n // transmission refraction is wired dynamically by the PBR material path when the loaded material needs it.\n [(j) => [\"transmission\", \"volume\", \"ior\", \"specular\", \"dispersion\"].some((e) => hasMatExt(e)(j)), () => import(\"./gltf-ext-dielectric.js\")],\n [hasExt(\"KHR_texture_transform\"), () => import(\"./gltf-ext-uv-transform.js\")],\n [hasExt(\"KHR_texture_basisu\"), () => import(\"./gltf-ext-basisu.js\")],\n [needsOrmComposite, () => import(\"./gltf-ext-orm.js\")],\n // Per-mesh features (predicates inlined to avoid eager imports)\n [(json) => !!json.skins?.length && anyPrimitive(json, (p) => p.attributes?.JOINTS_0 !== undefined), () => import(\"./gltf-feature-skeleton.js\")],\n [(json) => anyPrimitive(json, (p) => !!p.targets?.length), () => import(\"./gltf-feature-morph.js\")],\n // Per-asset features\n [hasExt(\"KHR_lights_punctual\"), () => import(\"./gltf-feature-lights-punctual.js\")],\n [(json) => !!json.animations?.length, () => import(\"./gltf-feature-animations.js\")],\n [hasMatExt(\"variants\"), () => import(\"./gltf-feature-variants.js\")],\n [hasExt(\"KHR_node_visibility\"), () => import(\"./gltf-ext-node-visibility.js\")],\n [hasExt(\"KHR_animation_pointer\"), () => import(\"./gltf-feature-animation-pointer.js\")],\n [hasExt(\"EXT_mesh_gpu_instancing\"), () => import(\"./gltf-feature-gpu-instancing.js\")],\n [hasExt(\"KHR_xmp_json_ld\"), () => import(\"./gltf-feature-xmp.js\")],\n];\n\n/** Dynamic-import every feature the asset triggers. */\nasync function loadGltfFeatures(json: any): Promise<GltfFeature[]> {\n const mods = await Promise.all(_features.flatMap(([needs, load]) => (needs(json) ? [load()] : [])));\n return mods.map((m) => m.default);\n}\n\n// --- Hierarchy Reconstruction ---\n\n/** Build a TransformNode tree mirroring the glTF node hierarchy.\n * Meshes are attached as children. Non-mesh nodes become\n * pure TransformNodes preserving TRS for cloning/repositioning.\n * Parent links are set by addToScene() when the tree is added to the scene.\n * Also returns a glTF-node-index → SceneNode map used by per-asset features\n * (KHR_node_visibility, KHR_animation_pointer) to address specific nodes. */\nfunction buildNodeHierarchy(json: any, meshes: Mesh[], meshDatas: GltfMeshData[]): { root: TransformNode; nodeMap: (TransformNode | undefined)[] } {\n // Map nodeIndex → uploaded Mesh[]\n const nodeToMeshes = new Map<number, Mesh[]>();\n for (let i = 0; i < meshDatas.length; i++) {\n const ni = meshDatas[i]!._nodeIndex;\n let arr = nodeToMeshes.get(ni);\n if (!arr) {\n arr = [];\n nodeToMeshes.set(ni, arr);\n }\n arr.push(meshes[i]!);\n }\n\n const nodeMap: (TransformNode | undefined)[] = new Array(json.nodes?.length ?? 0);\n\n // Recursive builder\n function buildNode(nodeIdx: number): TransformNode {\n const node = json.nodes[nodeIdx];\n const name = node.name ?? `node_${nodeIdx}`;\n let tn: TransformNode;\n if (node.matrix) {\n tn = createSceneNodeFromMatrix(name, node.matrix as Mat4);\n } else {\n const t = node.translation ?? [0, 0, 0];\n const r = node.rotation ?? [0, 0, 0, 1];\n const s = node.scale ?? [1, 1, 1];\n tn = createTransformNode(name, t[0], t[1], t[2], r[0], r[1], r[2], r[3], s[0], s[1], s[2]);\n }\n nodeMap[nodeIdx] = tn;\n if (node.children) {\n for (const childIdx of node.children) {\n tn.children.push(buildNode(childIdx));\n }\n }\n const nodeMeshes = nodeToMeshes.get(nodeIdx) ?? [];\n tn.children.push(...nodeMeshes);\n return tn;\n }\n\n // Synthetic root (like BJS __root__) — applies RH→LH conversion via scale\n // BJS: rotation [0,1,0,0] + scale [1,1,-1] = diag(-1, 1, 1, 1)\n const sceneRoots: number[] = json.scenes?.[json.scene ?? 0]?.nodes ?? [];\n const rootChildren = sceneRoots.map((ni: number) => buildNode(ni));\n const root = createTransformNode(\"__root__\", 0, 0, 0, 0, 0, 0, 1, -1, 1, 1);\n root.children.push(...rootChildren);\n return { root, nodeMap };\n}\n\n// --- Mesh Extraction ---\n\nasync function extractAllMeshes(\n json: any,\n binChunk: DataView,\n baseUrl: string,\n parentMap: Map<number, number>,\n worldMatrixCache: Map<number, Mat4>,\n decodedPrimitives: Map<unknown, DecodedPrimitive>\n): Promise<GltfMeshData[]> {\n // Per-load image cache — avoids decoding the same glTF image index multiple times\n const imageCache = new Map<number, Promise<ImageBitmap>>();\n\n // Cache material assembly by glTF material index — avoids duplicate image fetches\n const matCache = new Map<number, Promise<GltfMaterialData>>();\n const getMat = (matIdx: number): Promise<GltfMaterialData> => {\n const key = matIdx ?? -1;\n let p = matCache.get(key);\n if (!p) {\n p = assembleMaterial(json, binChunk, matIdx, baseUrl, imageCache);\n matCache.set(key, p);\n }\n return p;\n };\n\n // First pass: do all sync work, fire all material fetches concurrently\n const partials: Array<Omit<GltfMeshData, \"_material\">> = [];\n const matPromises: Promise<GltfMaterialData>[] = [];\n\n // Genuine GPU interleaving is the ONLY reason to touch the interleave module.\n // Many exporters declare `byteStride` even on tightly-packed bufferViews, and a\n // preMesh feature (e.g. the basisu extension's readStridedFloat path) may already\n // de-stride a primitive — so we load the module only for a primitive that is\n // genuinely over-strided AND not already decoded. Other scenes pay zero cost: the\n // module is fetched lazily on the first such primitive (memoized), never before.\n const _accs = json.accessors as any[];\n const _bvs = json.bufferViews as any[] | undefined;\n const _strided = (p: any): boolean => {\n for (const k in p.attributes) {\n const a = _accs[p.attributes[k]];\n const s = _bvs?.[a?.bufferView]?.byteStride;\n if (\n s !== undefined &&\n s !== (TYPE_SIZES[a.type] ?? 1) * (a.componentType === 5126 || a.componentType === 5125 ? 4 : a.componentType === 5123 || a.componentType === 5122 ? 2 : 1)\n ) {\n return true;\n }\n }\n return false;\n };\n\n for (let nodeIdx = 0; nodeIdx < json.nodes.length; nodeIdx++) {\n const node = json.nodes[nodeIdx];\n if (node.mesh === undefined) {\n continue;\n }\n\n const mesh = json.meshes[node.mesh];\n const worldMatrix = computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache);\n\n for (const primitive of mesh.primitives) {\n const attrs = primitive.attributes;\n const decoded = decodedPrimitives.get(primitive);\n\n // Genuine GPU interleaving: only a primitive that genuinely sources ≥1\n // attribute from an over-strided bufferView (and was not already decoded\n // by a preMesh feature) takes this path. The module is imported lazily on\n // first need — non-interleaved assets never fetch it. Tight primitives\n // fall through to the path below (byte-identical to non-interleaved).\n if (!decoded && _strided(primitive)) {\n const ip = (await loadInterleave()).buildInterleavedPartial(json, binChunk, primitive, worldMatrix, nodeIdx);\n if (ip) {\n matPromises.push(getMat(primitive.material));\n partials.push(ip);\n continue;\n }\n }\n\n const resolveAttr = (name: string): AccessorView | null => {\n if (decoded && decoded._attributes.has(name)) {\n const data = decoded._attributes.get(name)!;\n const componentCount = data.length / decoded._vertexCount;\n return { _data: data, _count: decoded._vertexCount, _componentCount: componentCount };\n }\n const idx = attrs[name];\n return idx !== undefined ? resolveAccessor(json, binChunk, idx) : null;\n };\n const posData = resolveAttr(\"POSITION\")!;\n const normData = resolveAttr(\"NORMAL\")!;\n const uvData = resolveAttr(\"TEXCOORD_0\");\n const uv2Data = resolveAttr(\"TEXCOORD_1\");\n const tanData = resolveAttr(\"TANGENT\");\n const colorData = resolveAttr(\"COLOR_0\");\n const idxData = decoded\n ? { _data: decoded._indices, _count: decoded._indexCount, _componentCount: 1 }\n : primitive.indices !== undefined\n ? resolveAccessor(json, binChunk, primitive.indices)\n : null;\n\n // Keep vertex data as-is from glTF — RH→LH conversion handled by root world matrix\n const indices = idxData\n ? idxData._data instanceof Uint32Array\n ? new Uint32Array(idxData._data as Uint32Array)\n : idxData._data instanceof Uint8Array\n ? Uint16Array.from(idxData._data as Uint8Array)\n : new Uint16Array(idxData._data!.buffer, idxData._data!.byteOffset, idxData._count)\n : new Uint16Array(0);\n\n // Fire material fetch without awaiting — all materials load in parallel\n matPromises.push(getMat(primitive.material));\n\n partials.push({\n _positions: posData._data as Float32Array,\n _normals: normData._data as Float32Array,\n _tangents: tanData ? (tanData._data as Float32Array) : null,\n _uvs: uvData ? (uvData._data as Float32Array) : new Float32Array(posData._count * 2),\n _uv2s: uv2Data ? (uv2Data._data as Float32Array) : null,\n _colors: colorData ? (colorData._data as Float32Array) : null,\n _indices: indices,\n _vertexCount: posData._count,\n _indexCount: idxData?._count ?? 0,\n _worldMatrix: worldMatrix,\n _nodeIndex: nodeIdx,\n _primitive: primitive,\n _decoded: decoded,\n });\n }\n }\n\n // Resolve all material fetches in parallel\n const materials = await Promise.all(matPromises);\n return partials.map((p, i) => ({ ...p, _material: materials[i]! }));\n}\n\n// --- GPU Upload ---\n\n// Pre-resolved generateMipmaps function— loaded once before texture uploads\nlet _generateMipmaps: ((engine: EngineContext, texture: GPUTexture, face?: number) => void) | null = null;\n\nasync function ensureMipmapModule(): Promise<void> {\n if (!_generateMipmaps) {\n _generateMipmaps = (await import(\"../texture/generate-mipmaps.js\")).generateMipmaps;\n }\n}\n\nasync function uploadMeshes(meshDatas: GltfMeshData[], features: GltfFeature[], ctx: GltfLoadCtx): Promise<Mesh[]> {\n const { _engine: engine, _json: json, _binChunk: binChunk, _baseUrl: baseUrl, _matExts: matExts, _wrapTex: wrapTex } = ctx;\n const sampler = getOrCreateSampler(engine, {\n magFilter: \"linear\",\n minFilter: \"linear\",\n mipmapFilter: \"linear\",\n addressModeU: \"repeat\",\n addressModeV: \"repeat\",\n maxAnisotropy: 4,\n });\n\n await ensureMipmapModule();\n const meshFeatures = features.filter((f) => f.applyMesh);\n\n // Texture cache: shared textures uploaded once, keyed by (bitmap, srgb)\n const texCache = new Map<number, Texture2D>();\n let texId = 0;\n const bitmapIds = new Map<ImageBitmap, number>();\n\n function getCachedTexture(bitmap: ImageBitmap, srgb: boolean): Texture2D {\n let id = bitmapIds.get(bitmap);\n if (id === undefined) {\n bitmapIds.set(bitmap, (id = texId++));\n }\n const key = id * 2 + +srgb;\n let tex = texCache.get(key);\n if (!tex) {\n tex = uploadTex(engine, bitmap, srgb, sampler, _generateMipmaps!);\n texCache.set(key, tex);\n }\n return tex;\n }\n\n // Per-load image fetcher for ext modules (uses same image cache as core).\n const extImageCache = matExts.length ? new Map<number, Promise<ImageBitmap>>() : null;\n const extFetchImg = extImageCache ? makeImageFetcher(json, binChunk, baseUrl, extImageCache) : null;\n const extCtx: GltfMatExtCtx = {\n _engine: engine,\n async _texture(texInfo, sRGB) {\n if (!texInfo || !extFetchImg) {\n return undefined;\n }\n const img = await extFetchImg(texInfo);\n return img ? wrapTex(getCachedTexture(img, sRGB), texInfo) : undefined;\n },\n _uploadImage(bitmap, sRGB) {\n return uploadTex(engine, bitmap, sRGB, sampler, _generateMipmaps!);\n },\n };\n\n // Slow-path trigger: per-texture UV wrapping (KHR_texture_transform)\n // or any core texture declaring texCoord=1. Scene1 stays identity→fast path.\n let _needsPbrExt = wrapTex !== identityTexWrap;\n if (!_needsPbrExt) {\n const mats = (json as { materials?: unknown[] }).materials;\n if (mats && JSON.stringify(mats).includes('\"texCoord\":1')) {\n _needsPbrExt = true;\n }\n }\n let _pbrExtPromise: Promise<typeof GltfPbrBuilderExt> | null = null;\n const _ensurePbrExt = () => (_pbrExtPromise ??= import(\"./gltf-pbr-builder-ext.js\"));\n\n /** Default ORM upload: single MR-or-occlusion image, or 1×1 fallback baked from\n * metallicFactor/roughnessFactor. The composite case (MR+occlusion separate) is\n * handled by the gltf-ext-orm extension which overrides this via `extLayers`. */\n\n // Build a PbrMaterialProps from parsed glTF material data.\n // Uses shared texture caches so identical bitmaps are uploaded once.\n const builtMaterialCache = new Map<GltfMaterialData, Promise<PbrMaterialProps>>();\n async function buildPbrFromGltfMat(mat: GltfMaterialData): Promise<PbrMaterialProps> {\n let cached = builtMaterialCache.get(mat);\n if (cached) {\n return cached;\n }\n cached = (async () => {\n const extLayers = await runMatExts(mat, matExts, extCtx);\n if (_needsPbrExt) {\n const extMod = await _ensurePbrExt();\n const tex = extMod.buildDefaultPbrTexturesExt(engine, mat, sampler, _generateMipmaps!, getCachedTexture, wrapTex);\n return extMod.assemblePbrPropsExt(mat, tex, extLayers);\n }\n const tex = buildDefaultPbrTextures(engine, mat, sampler, _generateMipmaps!, getCachedTexture);\n return assemblePbrProps(mat, tex.baseColorTexture, tex.ormTexture, tex.normalTexture, tex.emissiveTexture, extLayers);\n })();\n builtMaterialCache.set(mat, cached);\n return cached;\n }\n\n const meshes = await Promise.all(\n meshDatas.map(async (m, i): Promise<Mesh> => {\n const material = await buildPbrFromGltfMat(m._material);\n\n // Interleaved meshes are fully built by the dynamic module (kept out of\n // this bundle for non-interleaved scenes). The tight path below is\n // byte-identical to the non-interleaved engine.\n let mesh: Mesh;\n if (m._vb) {\n mesh = (await loadInterleave()).buildInterleavedMesh(engine, m, i, material) as Mesh;\n } else {\n const [boundMin, boundMax] = computeAabb(m._positions!, m._worldMatrix);\n const gpu: MeshGPU = {\n positionBuffer: createMappedBuffer(engine, m._positions!, GPUBufferUsage.VERTEX),\n normalBuffer: createMappedBuffer(engine, m._normals!, GPUBufferUsage.VERTEX),\n tangentBuffer: m._tangents ? createMappedBuffer(engine, m._tangents, GPUBufferUsage.VERTEX) : null,\n uvBuffer: createMappedBuffer(engine, m._uvs!, GPUBufferUsage.VERTEX),\n uv2Buffer: m._uv2s ? createMappedBuffer(engine, m._uv2s, GPUBufferUsage.VERTEX) : null,\n colorBuffer: m._colors ? createMappedBuffer(engine, m._colors, GPUBufferUsage.VERTEX) : null,\n indexBuffer: createMappedBuffer(engine, m._indices, GPUBufferUsage.INDEX),\n indexCount: m._indexCount,\n indexFormat: (m._indices instanceof Uint32Array ? \"uint32\" : \"uint16\") as GPUIndexFormat,\n };\n\n mesh = {\n name: `gltf_mesh_${i}`,\n material,\n receiveShadows: false,\n boundMin,\n boundMax,\n skeleton: null,\n morphTargets: null,\n _materialDirty: false,\n _gpu: gpu,\n } as unknown as Mesh;\n initMeshTransform(mesh);\n\n // Retain CPU geometry for detailed picking.\n mesh._cpuPositions = m._positions!;\n mesh._cpuNormals = m._normals!;\n mesh._cpuUvs = m._uvs!;\n mesh._cpuIndices = m._indices instanceof Uint32Array ? m._indices : new Uint32Array(m._indices);\n engine._dlr?.m(mesh, m._uv2s, m._tangents, m._colors, m._indices, gpu.indexFormat);\n }\n\n // Run all per-mesh feature hooks (skeleton, morph, …) in parallel.\n // Each hook mutates `mesh` directly (e.g. attaches mesh.skeleton).\n if (meshFeatures.length > 0) {\n await Promise.all(meshFeatures.map((f) => f.applyMesh!(m, mesh, ctx)));\n }\n\n return mesh;\n })\n );\n\n return meshes;\n}\n","/**\n * KHR_materials_variants — runtime variant selection for glTF assets.\n *\n * Variant data is populated by loadGltf() when the extension is present.\n * selectVariant() swaps materials on affected meshes; the render pipeline\n * automatically rebuilds renderables via the material-setter intercept.\n *\n * Tree-shakable: if the app never imports selectVariant / getVariantNames,\n * this module is eliminated from the bundle.\n */\n\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { StandardMaterialProps } from \"../material/standard/standard-material.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\n\ntype AnyMaterial = StandardMaterialProps | PbrMaterialProps;\n\n/** Per-mesh original + variant material entry. */\nexport interface VariantMeshEntry {\n mesh: Mesh;\n material: AnyMaterial;\n}\n\n/**\n * Full variant data for a loaded glTF asset.\n * Populated by loadGltf() when KHR_materials_variants is present.\n *\n * Note: variant data holds direct references to Mesh objects from the load.\n * Cloned hierarchies (via cloneTransformNode) are NOT variant-aware.\n */\nexport interface MaterialVariantData {\n /** Ordered list of available variant names. */\n readonly names: readonly string[];\n /** Per-variant mesh→material mappings. Key = variant name. */\n readonly variants: Readonly<Record<string, readonly VariantMeshEntry[]>>;\n /** Original (default) materials for all variant-participating meshes. */\n readonly originals: readonly VariantMeshEntry[];\n}\n\n/**\n * Get available variant names from a loaded glTF asset.\n * Returns an empty array if the asset has no material variants.\n */\nexport function getVariantNames(container: AssetContainer): readonly string[] {\n return container.materialVariants?.names ?? [];\n}\n\n/**\n * Select a material variant by name on a loaded glTF asset.\n *\n * Two-step operation:\n * 1. Restores ALL variant-participating meshes to their original (default) materials.\n * 2. Applies the selected variant's material overrides.\n *\n * This ensures meshes without a mapping for the new variant revert to their defaults,\n * even when switching between variants (e.g. Red → White).\n *\n * Works both before and after addToScene():\n * - Before: materials are set directly (renderable built later).\n * - After: the property-setter intercept triggers renderable rebuild automatically.\n */\nexport function selectVariant(container: AssetContainer, variantName: string): void {\n const data = container.materialVariants;\n if (!data) {\n return;\n }\n\n // Step 1: restore all participating meshes to their default materials\n for (const entry of data.originals) {\n entry.mesh.material = entry.material;\n }\n\n // Step 2: apply the selected variant\n const entries = data.variants[variantName];\n if (entries) {\n for (const entry of entries) {\n entry.mesh.material = entry.material;\n }\n }\n}\n\n/**\n * Reset all variant-participating meshes to their original (default) materials.\n */\nexport function resetVariant(container: AssetContainer): void {\n const data = container.materialVariants;\n if (!data) {\n return;\n }\n for (const entry of data.originals) {\n entry.mesh.material = entry.material;\n }\n}\n","import type { Mat4 } from \"./types.js\";\nimport { mat4MultiplyInto } from \"./mat4-multiply-into.js\";\n\n/** Multiply two Mat4: out = a * b (column-major). */\nexport function mat4Multiply(a: Mat4, b: Mat4): Mat4 {\n const out = new Float32Array(16) as Mat4;\n mat4MultiplyInto(out, 0, a, 0, b, 0);\n return out;\n}\n","/** Set a mesh's parent while preserving its current world-space position.\n * Equivalent to Babylon.js TransformNode.setParent().\n *\n * Computes the child's current world matrix, sets the parent,\n * then adjusts the child's local position so that its world position\n * remains unchanged.\n *\n * Standalone function for tree-shaking — only bundled when used. */\n\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { IWorldMatrixProvider } from \"./parentable.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { mat4Multiply } from \"../math/mat4-multiply.js\";\nimport type { Mat4 } from \"../math/types.js\";\n\n/**\n * Reparents `child` while preserving its current world-space transform, mirroring\n * Babylon.js `TransformNode.setParent()`.\n * @param child - The mesh to reparent.\n * @param parent - The new parent (any world-matrix provider), or `null` to detach to world space.\n */\nexport function setParent(child: Mesh, parent: IWorldMatrixProvider | null): void {\n // 1. Snapshot child's current world matrix\n const childWorld: Mat4 = child.worldMatrix;\n\n // 2. Set the parent\n child.parent = parent;\n\n // 3. If parent is null, the child's local = its old world transform\n if (!parent) {\n decomposeInto(childWorld, child);\n return;\n }\n\n // 4. Compute new local transform = inverse(parentWorld) * childWorld\n const parentWorld = parent.worldMatrix;\n const invParent = mat4Invert(parentWorld);\n if (!invParent) {\n // Singular parent matrix — just set position from world\n child.position.set(childWorld[12]!, childWorld[13]!, childWorld[14]!);\n return;\n }\n\n const newLocal = mat4Multiply(invParent, childWorld);\n\n // 5. Decompose newLocal into position/rotation/scaling and apply\n decomposeInto(newLocal, child);\n}\n\n/** Extract position, rotation (Euler XYZ), and scale from a 4×4 matrix\n * and write them into a mesh's observable properties. */\nfunction decomposeInto(m: Mat4, mesh: Mesh): void {\n // Position = translation column\n mesh.position.set(m[12]!, m[13]!, m[14]!);\n\n // Column scale lengths\n const sx = Math.sqrt(m[0]! * m[0]! + m[1]! * m[1]! + m[2]! * m[2]!);\n const sy = Math.sqrt(m[4]! * m[4]! + m[5]! * m[5]! + m[6]! * m[6]!);\n const sz = Math.sqrt(m[8]! * m[8]! + m[9]! * m[9]! + m[10]! * m[10]!);\n\n if (sx > 1e-6 && sy > 1e-6 && sz > 1e-6) {\n // Normalized rotation matrix columns\n const r00 = m[0]! / sx,\n r01 = m[4]! / sy,\n r02 = m[8]! / sz;\n const r10 = m[1]! / sx,\n r11 = m[5]! / sy,\n r12 = m[9]! / sz;\n const r22 = m[10]! / sz;\n\n // Euler XYZ (matching BJS decompose convention)\n const ry = Math.asin(Math.max(-1, Math.min(1, r02)));\n let rx: number, rz: number;\n if (Math.abs(r02) < 0.9999) {\n rx = Math.atan2(-r12, r22);\n rz = Math.atan2(-r01, r00);\n } else {\n rx = Math.atan2(r10, r11);\n rz = 0;\n }\n mesh.rotation.set(rx, ry, rz);\n mesh.scaling.set(sx, sy, sz);\n }\n}\n","/**\n * .babylon format loader — parses Babylon.js .babylon scene files.\n *\n * Supports:\n * - Standard materials with diffuse, bump, specular, ambient, lightmap, opacity textures\n * - Inline vertex data (positions, normals, UVs, indices)\n * - Point lights\n * - Scene clear color\n * - SubMesh → multi-material handling\n * - Parent-child hierarchy via parentId\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { AssetContainer } from \"../asset-container.js\";\nimport type { LightBase } from \"../light/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { TransformNode } from \"../scene/transform-node.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport { createTransformNode } from \"../scene/transform-node.js\";\nimport { createStandardMaterial } from \"../material/standard/create-standard-material.js\";\nimport type { StandardMaterialProps } from \"../material/standard/standard-material.js\";\nimport { uploadMeshToGPU, initMeshTransform } from \"../mesh/mesh.js\";\nimport { loadTexture2D } from \"../texture/texture-2d.js\";\n// ─── .babylon JSON Types ───────────────────────────────────────────\n\ninterface BabylonScene {\n clearColor?: number[];\n ambientColor?: number[];\n cameras?: BabylonCamera[];\n lights?: BabylonLight[];\n materials?: BabylonMaterial[];\n multiMaterials?: BabylonMultiMaterial[];\n meshes?: BabylonMesh[];\n activeCameraID?: string;\n}\n\ninterface BabylonCamera {\n name: string;\n id: string;\n type: string;\n position: number[];\n rotation?: number[];\n target?: number[];\n fov?: number;\n minZ?: number;\n maxZ?: number;\n}\n\ninterface BabylonTexture {\n name: string;\n hasAlpha?: boolean;\n getAlphaFromRGB?: boolean;\n isCube?: boolean;\n level?: number;\n coordinatesIndex?: number;\n coordinatesMode?: number;\n uOffset?: number;\n vOffset?: number;\n uScale?: number;\n vScale?: number;\n}\n\ninterface BabylonMaterial {\n name: string;\n id: string;\n diffuse?: number[];\n specular?: number[];\n specularPower?: number;\n emissive?: number[];\n ambient?: number[];\n alpha?: number;\n alphaCutOff?: number;\n diffuseTexture?: BabylonTexture | null;\n bumpTexture?: BabylonTexture | null;\n specularTexture?: BabylonTexture | null;\n ambientTexture?: BabylonTexture | null;\n lightmapTexture?: BabylonTexture | null;\n emissiveTexture?: BabylonTexture | null;\n opacityTexture?: BabylonTexture | null;\n reflectionTexture?: BabylonTexture | null;\n backFaceCulling?: boolean;\n}\n\ninterface BabylonMultiMaterial {\n name: string;\n id: string;\n materials: string[];\n}\n\ninterface BabylonSubMesh {\n materialIndex: number;\n verticesStart: number;\n verticesCount: number;\n indexStart: number;\n indexCount: number;\n}\n\ninterface BabylonMesh {\n name: string;\n id: string;\n parentId?: string | null;\n materialId?: string | null;\n position?: number[];\n rotation?: number[];\n scaling?: number[];\n localMatrix?: number[];\n positions?: number[];\n normals?: number[];\n uvs?: number[];\n uvs2?: number[];\n indices?: number[];\n subMeshes?: BabylonSubMesh[];\n isVisible?: boolean;\n}\n\ninterface BabylonLight {\n name: string;\n id: string;\n type: number;\n position?: number[];\n direction?: number[];\n diffuse?: number[];\n specular?: number[];\n intensity?: number;\n range?: number;\n excludedMeshesIds?: string[];\n includedOnlyMeshesIds?: string[];\n}\n\n// ─── Standard-material texture-slot table ───────────────────────────\n// Declarative description of .babylon -> StandardMaterialProps texture mapping.\n// Each slot maps a source texture field on BabylonMaterial to a destination\n// Texture2D field on StandardMaterialProps, plus optional level/coordIndex/extras.\ntype BabylonTexField = \"diffuseTexture\" | \"bumpTexture\" | \"specularTexture\" | \"ambientTexture\" | \"lightmapTexture\" | \"opacityTexture\" | \"reflectionTexture\";\n\ninterface BabylonTexSlot {\n readonly src: BabylonTexField;\n /** Destination Texture2D field on StandardMaterialProps. */\n readonly dst: string;\n /** StandardMaterialProps field receiving `t.level`, if present. */\n readonly level?: string;\n /** Coordinate-index mapping. `only1`=true → only apply when coordIndex===1. */\n readonly coordIndex?: { readonly dst: string; readonly only1?: boolean };\n /** Skip this slot for a texture if predicate returns true (e.g. cube reflections). */\n readonly skipIf?: (t: BabylonTexture) => boolean;\n /** Apply remaining slot-specific side-effects (uvScale, alphaCutOff, etc.). */\n readonly extra?: (t: BabylonTexture, mat: StandardMaterialProps) => void;\n}\n\nconst TEX_SLOTS: readonly BabylonTexSlot[] = [\n {\n src: \"diffuseTexture\",\n dst: \"diffuseTexture\",\n coordIndex: { dst: \"diffuseCoordIndex\", only1: true },\n extra: (t, m) => {\n m.uvScale = [t.uScale ?? 1, t.vScale ?? 1];\n if (t.hasAlpha) {\n m.alphaCutOff = 0.4;\n }\n },\n },\n { src: \"bumpTexture\", dst: \"bumpTexture\", level: \"bumpLevel\" },\n { src: \"specularTexture\", dst: \"specularTexture\", coordIndex: { dst: \"specularCoordIndex\", only1: true } },\n { src: \"ambientTexture\", dst: \"ambientTexture\", level: \"ambientTexLevel\", coordIndex: { dst: \"ambientCoordIndex\", only1: true } },\n { src: \"lightmapTexture\", dst: \"lightmapTexture\", level: \"lightmapLevel\", coordIndex: { dst: \"lightmapCoordIndex\" } },\n {\n src: \"opacityTexture\",\n dst: \"opacityTexture\",\n level: \"opacityLevel\",\n extra: (t, m) => {\n if (t.getAlphaFromRGB) {\n m.opacityFromRGB = true;\n }\n },\n },\n {\n src: \"reflectionTexture\",\n dst: \"reflectionTexture\",\n level: \"reflectionLevel\",\n skipIf: (t) => t.isCube === true,\n extra: (t, m) => {\n if (t.coordinatesMode === 2) {\n m.reflectionCoordMode = 2;\n }\n },\n },\n];\n\n// ─── Public API ─────────────────────────────────────────────────────\n\nexport interface LoadBabylonOptions {\n /** Maximum number of meshes to load. Default: all. */\n maxMeshes?: number;\n /** Whether to load textures. Default: true. */\n loadTextures?: boolean;\n /** Whether to parse the camera from the file. Default: true. */\n loadCamera?: boolean;\n}\n\n/**\n * Load a .babylon scene file and return a AssetContainer.\n * Pass the result to addToScene() to populate the scene.\n *\n * @param engine - The engine (provides GPU device)\n * @param url - URL to the .babylon file\n * @param opts - Optional loader configuration\n */\nexport async function loadBabylon(engine: EngineContext, url: string, opts: LoadBabylonOptions = {}): Promise<AssetContainer> {\n const baseUrl = url.substring(0, url.lastIndexOf(\"/\") + 1);\n\n const response = await fetch(url);\n const data: BabylonScene = await response.json();\n\n // Scene-level settings\n let clearColor: GPUColorDict | undefined;\n if (data.clearColor) {\n clearColor = {\n r: data.clearColor[0]!,\n g: data.clearColor[1]!,\n b: data.clearColor[2]!,\n a: 1,\n };\n }\n\n // Scene ambient color — BJS multiplies material.ambient by scene.ambientColor\n const sceneAmbient: [number, number, number] = data.ambientColor ? [data.ambientColor[0]!, data.ambientColor[1]!, data.ambientColor[2]!] : [0, 0, 0];\n // Build material map\n const materialMap = new Map<string, StandardMaterialProps>();\n const texturePromises: Promise<void>[] = [];\n\n if (data.materials) {\n for (const md of data.materials) {\n const mat = createStandardMaterial();\n if (md.diffuse) {\n mat.diffuseColor = [md.diffuse[0]!, md.diffuse[1]!, md.diffuse[2]!];\n }\n if (md.specular) {\n mat.specularColor = [md.specular[0]!, md.specular[1]!, md.specular[2]!];\n }\n if (md.specularPower != null) {\n mat.specularPower = md.specularPower;\n }\n if (md.emissive) {\n mat.emissiveColor = [md.emissive[0]!, md.emissive[1]!, md.emissive[2]!];\n }\n if (md.ambient) {\n mat.ambientColor = [md.ambient[0]! * sceneAmbient[0], md.ambient[1]! * sceneAmbient[1], md.ambient[2]! * sceneAmbient[2]];\n }\n if (md.alpha != null) {\n mat.alpha = md.alpha;\n }\n if (md.alphaCutOff != null) {\n mat.alphaCutOff = md.alphaCutOff;\n }\n if (md.backFaceCulling === false) {\n mat.backFaceCulling = false;\n }\n\n if (opts.loadTextures !== false) {\n for (const slot of TEX_SLOTS) {\n const t = md[slot.src];\n if (!t) {\n continue;\n }\n if (slot.skipIf?.(t)) {\n continue;\n }\n if (slot.level && t.level != null) {\n (mat as unknown as Record<string, unknown>)[slot.level] = t.level;\n }\n if (slot.coordIndex) {\n if (slot.coordIndex.only1) {\n if (t.coordinatesIndex === 1) {\n (mat as unknown as Record<string, unknown>)[slot.coordIndex.dst] = 1;\n }\n } else if (t.coordinatesIndex != null) {\n (mat as unknown as Record<string, unknown>)[slot.coordIndex.dst] = t.coordinatesIndex === 1 ? 1 : 0;\n }\n }\n slot.extra?.(t, mat);\n const texUrl = baseUrl + t.name;\n const dst = slot.dst;\n texturePromises.push(\n loadTexture2D(engine, texUrl).then((tex) => {\n (mat as unknown as Record<string, unknown>)[dst] = tex;\n })\n );\n }\n }\n\n if (md.reflectionTexture && opts.loadTextures !== false && md.reflectionTexture.isCube) {\n if (md.reflectionTexture.level != null) {\n mat.reflectionLevel = md.reflectionTexture.level;\n }\n const cubeName = md.reflectionTexture.name;\n texturePromises.push(\n import(\"../texture/cube-texture.js\").then(({ loadCubeTexture }) =>\n loadCubeTexture(engine as EngineContext, baseUrl + cubeName).then((cube) => {\n mat.reflectionCubeTexture = cube;\n })\n )\n );\n }\n\n materialMap.set(md.id, mat);\n }\n }\n\n await Promise.all(texturePromises);\n\n // Multi-material map: multiMat ID → array of sub-material IDs\n const multiMatMap = new Map<string, string[]>();\n if (data.multiMaterials) {\n for (const mm of data.multiMaterials) {\n multiMatMap.set(mm.id, mm.materials);\n }\n }\n\n // Lights (point lights only — dynamically imported)\n const lights: LightBase[] = [];\n if (data.lights?.length) {\n const { createPointLight } = await import(\"../light/point-light.js\");\n for (const ld of data.lights) {\n if (ld.type === 0 && ld.position) {\n const pl = createPointLight([ld.position[0]!, ld.position[1]!, ld.position[2]!], ld.intensity ?? 1);\n if (ld.diffuse) {\n pl.diffuse = [ld.diffuse[0]!, ld.diffuse[1]!, ld.diffuse[2]!];\n }\n if (ld.specular) {\n pl.specular = [ld.specular[0]!, ld.specular[1]!, ld.specular[2]!];\n }\n if (ld.range != null) {\n pl.range = ld.range;\n }\n const { excludedMeshesIds: ex, includedOnlyMeshesIds: io } = ld;\n if (ex?.length) {\n pl.excludedMeshIds = new Set(ex);\n }\n if (io?.length) {\n pl.includedOnlyMeshIds = new Set(io);\n }\n lights.push(pl);\n }\n }\n }\n\n // Meshes — each carries its own TRS; parentId links are used for world-matrix chaining.\n const allMeshes: Mesh[] = [];\n const nodeMap = new Map<string, Mesh | TransformNode>();\n const meshesByNodeId = new Map<string, Mesh[]>();\n const childNodeIds = new Set<string>();\n if (data.meshes) {\n const maxMeshes = opts.maxMeshes ?? Infinity;\n let meshCount = 0;\n\n // Dynamically load localMatrix baking only when the scene needs it\n const hasAnyLocalMatrix = data.meshes.some((m) => m.localMatrix);\n const bakeLocalMatrix = hasAnyLocalMatrix ? (await import(\"./bake-local-matrix.js\")).bakeLocalMatrix : null;\n\n // First pass: create Mesh(es) for geometry nodes; TransformNode for pure containers.\n for (const md of data.meshes) {\n if (meshCount >= maxMeshes) {\n break;\n }\n if (md.isVisible === false) {\n continue;\n }\n\n if (md.positions && md.normals && md.indices && md.indices.length > 0) {\n const positions = new Float32Array(md.positions);\n const normals = new Float32Array(md.normals);\n const allIndices = new Uint32Array(md.indices);\n const uvs = md.uvs ? new Float32Array(md.uvs) : undefined;\n const uvs2 = md.uvs2 ? new Float32Array(md.uvs2) : undefined;\n\n // Bake localMatrix (pivot) into vertex data when present\n if (md.localMatrix && bakeLocalMatrix) {\n bakeLocalMatrix(positions, normals, md.localMatrix);\n }\n\n let matIds: string[] | null = null;\n if (md.materialId) {\n const multi = multiMatMap.get(md.materialId);\n matIds = multi ?? [md.materialId];\n }\n\n const subMeshes = md.subMeshes ?? [\n {\n materialIndex: 0,\n verticesStart: 0,\n verticesCount: positions.length / 3,\n indexStart: 0,\n indexCount: allIndices.length,\n },\n ];\n\n let firstMesh: Mesh | null = null;\n for (const sub of subMeshes) {\n if (sub.indexCount === 0) {\n continue;\n }\n\n const subIndices = allIndices.slice(sub.indexStart, sub.indexStart + sub.indexCount);\n const gpu = uploadMeshToGPU(engine as EngineContext, positions, normals, subIndices, uvs, uvs2);\n\n let mat: StandardMaterialProps;\n if (matIds && sub.materialIndex < matIds.length) {\n mat = materialMap.get(matIds[sub.materialIndex]!) ?? createStandardMaterial();\n } else if (matIds && matIds.length === 1) {\n mat = materialMap.get(matIds[0]!) ?? createStandardMaterial();\n } else {\n mat = createStandardMaterial();\n }\n\n const mesh = {\n name: md.name + (subMeshes.length > 1 ? `_sub${sub.materialIndex}` : \"\"),\n id: md.id,\n material: mat,\n receiveShadows: false,\n _materialDirty: false,\n _gpu: gpu,\n } as unknown as Mesh;\n\n mesh._cpuPositions = positions;\n mesh._cpuNormals = normals;\n mesh._cpuUvs = uvs;\n mesh._cpuIndices = subIndices;\n\n // Each mesh carries its own TRS from the node.\n initMeshTransform(\n mesh,\n md.position?.[0] ?? 0,\n md.position?.[1] ?? 0,\n md.position?.[2] ?? 0,\n md.rotation?.[0] ?? 0,\n md.rotation?.[1] ?? 0,\n md.rotation?.[2] ?? 0,\n md.scaling?.[0] ?? 1,\n md.scaling?.[1] ?? 1,\n md.scaling?.[2] ?? 1\n );\n\n allMeshes.push(mesh as unknown as Mesh);\n if (!meshesByNodeId.has(md.id)) {\n meshesByNodeId.set(md.id, []);\n }\n meshesByNodeId.get(md.id)!.push(mesh as unknown as Mesh);\n if (firstMesh === null) {\n firstMesh = mesh as unknown as Mesh;\n }\n meshCount++;\n }\n\n if (firstMesh !== null) {\n nodeMap.set(md.id, firstMesh);\n }\n } else {\n // Container node (no geometry) — TransformNode used only for parent linking.\n const rx = md.rotation?.[0] ?? 0,\n ry = md.rotation?.[1] ?? 0,\n rz = md.rotation?.[2] ?? 0;\n const cx = Math.cos(rx * 0.5),\n sx_ = Math.sin(rx * 0.5);\n const cy = Math.cos(ry * 0.5),\n sy_ = Math.sin(ry * 0.5);\n const cz = Math.cos(rz * 0.5),\n sz_ = Math.sin(rz * 0.5);\n const qx = sx_ * cy * cz + cx * sy_ * sz_;\n const qy = cx * sy_ * cz - sx_ * cy * sz_;\n const qz = cx * cy * sz_ + sx_ * sy_ * cz;\n const qw = cx * cy * cz - sx_ * sy_ * sz_;\n const tn = createTransformNode(\n md.name,\n md.position?.[0] ?? 0,\n md.position?.[1] ?? 0,\n md.position?.[2] ?? 0,\n qx,\n qy,\n qz,\n qw,\n md.scaling?.[0] ?? 1,\n md.scaling?.[1] ?? 1,\n md.scaling?.[2] ?? 1\n );\n nodeMap.set(md.id, tn);\n }\n }\n\n // Second pass: wire parent links and children so world matrices chain correctly.\n for (const md of data.meshes) {\n if (md.isVisible === false || !md.parentId) {\n continue;\n }\n const parent = nodeMap.get(md.parentId);\n if (!parent) {\n continue;\n }\n childNodeIds.add(md.id);\n // Wire all mesh submeshes belonging to this node to the parent\n const childMeshes = meshesByNodeId.get(md.id) ?? [];\n for (const child of childMeshes) {\n child.parent = parent;\n (parent as unknown as { children: SceneNode[] }).children.push(child);\n }\n // Wire TransformNode children (container nodes with no geometry)\n if (childMeshes.length === 0) {\n const childNode = nodeMap.get(md.id);\n if (childNode) {\n childNode.parent = parent;\n (parent as unknown as { children: SceneNode[] }).children.push(childNode);\n }\n }\n }\n }\n\n // Parse camera (dynamically imported — zero cost when loadCamera=false or no cameras in file)\n const camData =\n opts.loadCamera !== false && data.cameras?.length ? ((data.activeCameraID ? data.cameras.find((c) => c.id === data.activeCameraID) : null) ?? data.cameras[0]!) : null;\n const camera = camData ? (await import(\"./parse-camera.js\")).parseBabylonCamera(camData) : undefined;\n\n // Return AssetContainer — addToScene() handles entity registration, clearColor, and cleanup.\n // Only root entities (not children of any other node) are included; addToScene() recurses.\n const rootMeshes = allMeshes.filter((m) => !childNodeIds.has(m.id!));\n const rootTransformNodes: TransformNode[] = [];\n for (const [id, node] of nodeMap) {\n if (!childNodeIds.has(id) && !meshesByNodeId.has(id)) {\n rootTransformNodes.push(node as TransformNode);\n }\n }\n return { entities: [...lights, ...rootMeshes, ...rootTransformNodes], clearColor, camera };\n}\n","import type { EnvironmentTextures } from \"./load-env.js\";\nimport { polynomialToPreScaledHarmonics } from \"./load-env.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getBilinearSampler, getTrilinearSampler } from \"../resource/samplers.js\";\n\n/** Create the standard sampler pair used by all environment loaders */\nexport function createEnvSamplers(engine: EngineContext): { cubeSampler: GPUSampler; brdfSampler: GPUSampler } {\n return {\n cubeSampler: getTrilinearSampler(engine),\n brdfSampler: getBilinearSampler(engine),\n };\n}\n\n/** Assemble the EnvironmentTextures object from pre-computed components */\nexport function assembleEnvironmentTextures(\n specularCube: GPUTexture,\n brdfLut: GPUTexture,\n irradianceSH: Float32Array,\n lodGenerationScale: number,\n engine: EngineContext\n): EnvironmentTextures {\n const { cubeSampler, brdfSampler } = createEnvSamplers(engine);\n return {\n specularCube,\n specularCubeView: specularCube.createView({ dimension: \"cube\" }),\n brdfLut,\n brdfLutView: brdfLut.createView(),\n cubeSampler,\n brdfSampler,\n irradianceSH,\n sphericalHarmonics: polynomialToPreScaledHarmonics(irradianceSH),\n lodGenerationScale,\n };\n}\n","/** Compute scene bounds → ground / skybox size (for the background environment). */\n\nimport type { SceneContext } from \"../../scene/scene.js\";\n\n/** Compute ground size and skybox size from scene bounds.\n * Matches BJS EnvironmentHelper._setupSizes() with sizeAuto=true.\n * @param userSkyboxSize - Optional user-provided skyboxSize (BJS still applies\n * diagonal override + ×1.5 even for explicit values). */\nexport function computeSceneSize(\n scene: SceneContext,\n userSkyboxSize?: number\n): {\n groundSize: number;\n skyboxSize: number;\n rootPosition: [number, number, number];\n} {\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (const m of scene.meshes) {\n if (!m.boundMin || !m.boundMax) {\n continue;\n }\n const w = m.worldMatrix;\n const tx = w[12]!,\n ty = w[13]!,\n tz = w[14]!;\n const wMinX = m.boundMin[0]! + tx;\n const wMinY = m.boundMin[1]! + ty;\n const wMinZ = m.boundMin[2]! + tz;\n const wMaxX = m.boundMax[0]! + tx;\n const wMaxY = m.boundMax[1]! + ty;\n const wMaxZ = m.boundMax[2]! + tz;\n if (wMinX < minX) {\n minX = wMinX;\n }\n if (wMinY < minY) {\n minY = wMinY;\n }\n if (wMinZ < minZ) {\n minZ = wMinZ;\n }\n if (wMaxX > maxX) {\n maxX = wMaxX;\n }\n if (wMaxY > maxY) {\n maxY = wMaxY;\n }\n if (wMaxZ > maxZ) {\n maxZ = wMaxZ;\n }\n }\n\n if (!isFinite(minX)) {\n return { groundSize: 15, skyboxSize: userSkyboxSize ?? 20, rootPosition: [0, 0, 0] };\n }\n\n const dx = maxX - minX,\n dy = maxY - minY,\n dz = maxZ - minZ;\n const sceneDiagonalLength = Math.sqrt(dx * dx + dy * dy + dz * dz);\n\n let groundSize = 15;\n let skyboxSize = userSkyboxSize ?? 20;\n const cam = scene.camera;\n if (cam && \"upperRadiusLimit\" in cam && (cam as { upperRadiusLimit: number }).upperRadiusLimit) {\n groundSize = (cam as { upperRadiusLimit: number }).upperRadiusLimit * 2;\n skyboxSize = groundSize;\n }\n if (sceneDiagonalLength > groundSize) {\n groundSize = sceneDiagonalLength * 2;\n skyboxSize = groundSize;\n }\n groundSize *= 1.1;\n skyboxSize *= 1.5;\n\n const rootPosition: [number, number, number] = [minX + dx * 0.5, minY - 0.00001, minZ + dz * 0.5];\n\n return { groundSize, skyboxSize, rootPosition };\n}\n","import type { SceneContext } from \"../scene/scene.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { acquireGPUTexture, releaseGPUTexture } from \"../resource/gpu-pool.js\";\nimport { assembleEnvironmentTextures } from \"./env-helpers.js\";\nimport { mipLevelCount } from \"../texture/mip-count.js\";\nimport { computeSceneSize } from \"../material/pbr/scene-size.js\";\n\n/** GPU-resident environment textures. */\nexport interface EnvironmentTextures {\n specularCube: GPUTexture;\n specularCubeView: GPUTextureView;\n brdfLut: GPUTexture;\n brdfLutView: GPUTextureView;\n cubeSampler: GPUSampler;\n brdfSampler: GPUSampler;\n irradianceSH: Float32Array;\n /** Pre-scaled SH coefficients for shader, 36 floats in stride-4 layout:\n * [L00.rgb, 0, L1_1.rgb, 0, L10.rgb, 0, L11.rgb, 0, L2_2.rgb, 0,\n * L2_1.rgb, 0, L20.rgb, 0, L21.rgb, 0, L22.rgb, 0] */\n sphericalHarmonics: Float32Array;\n /** LOD generation scale for specular IBL sampling. Default 0.8 (matches BJS BaseTexture). */\n lodGenerationScale: number;\n}\n\nconst ENV_MAGIC = new Uint8Array([0x86, 0x16, 0x87, 0x96, 0xf6, 0xd6, 0x96, 0x36]);\n\n/**\n * Load a Babylon.js .env environment file and upload cubemap + BRDF LUT to GPU.\n * BRDF LUT is decoded from a pre-baked RGBD PNG (matching BJS's embedded\n * environmentBRDFTexture) for pixel-perfect parity.\n */\nexport async function loadEnvironment(\n scene: SceneContext,\n url: string,\n options: {\n groundTextureUrl?: string;\n skipSkybox?: boolean;\n skipGround?: boolean;\n /**\n * URL for the skybox texture. Extension determines loading strategy:\n * - `.dds`: loads a DDS cube skybox (e.g. BJS CDN backgroundSkybox.dds). Tree-shaken when unused.\n * - `.env`: reuses the already-loaded specular cubemap as an HDR skybox (like BJS `createDefaultSkybox`).\n * Omit for the default flat-color background. Use `skipSkybox` to disable skybox entirely.\n */\n skyboxUrl?: string;\n /** Skybox size matching BJS createDefaultEnvironment skyboxSize option (default 20). */\n skyboxSize?: number;\n brdfUrl: string;\n }\n): Promise<EnvironmentTextures> {\n const engine = scene.engine as EngineContext;\n\n // Fetch .env and BRDF PNG in parallel\n const envPromise = fetch(url).then((r) => r.arrayBuffer());\n const brdfPromise = fetch(options.brdfUrl)\n .then((r) => r.blob())\n .then((b) => createImageBitmap(b, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" }));\n\n const envBuffer = await envPromise;\n const { faceBlobs, irradianceSH, width, mipCount } = parseEnvFile(envBuffer);\n\n // Decode all face images in parallel (raw RGBD bytes — no color space conversion)\n const faceImages = await Promise.all(faceBlobs.map((blob) => createImageBitmap(blob, { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" })));\n\n const { uploadCubemapRGBD, decodeBrdfPng } = await import(\"./rgbd-decode.js\");\n const specularCube = uploadCubemapRGBD(engine, faceImages, width, mipCount);\n for (const img of faceImages) {\n img.close();\n }\n\n const brdfImage = await brdfPromise;\n const brdfLut = decodeBrdfPng(engine, brdfImage);\n brdfImage.close();\n\n const textures = assembleEnvironmentTextures(specularCube, brdfLut, irradianceSH, 0.8, engine);\n\n scene._envTextures = textures;\n\n acquireGPUTexture(specularCube);\n acquireGPUTexture(brdfLut);\n scene._disposables.push(() => {\n releaseGPUTexture(specularCube);\n releaseGPUTexture(brdfLut);\n });\n\n // Enable tonemapping when environment is loaded (matches Babylon.js default behavior)\n scene.imageProcessing.toneMappingEnabled = true;\n scene.imageProcessing.exposure = 0.8;\n scene.imageProcessing.contrast = 1.2;\n\n // Register deferred builder for background renderables (skybox + ground)\n // Re-registers itself if PBR scene BGL isn't ready yet (created by mesh builder)\n const groundUrl = options?.groundTextureUrl;\n // Start fetching ground texture NOW (in parallel with everything else)\n const groundTexPromise = groundUrl\n ? fetch(groundUrl)\n .then((r) => r.blob())\n .then((b) => createImageBitmap(b, { premultiplyAlpha: \"none\" }))\n : undefined;\n const skyboxUrl = options?.skyboxUrl;\n const skyboxIsDds = skyboxUrl != null && skyboxUrl.toLowerCase().endsWith(\".dds\");\n // Skybox is treated as .env when the URL has an .env extension OR when it matches the\n // lighting URL (which we just loaded successfully as .env). The latter handles data URIs\n // and other extensionless URLs where the caller wants to reuse the IBL cubemap as a skybox.\n const skyboxIsEnv = skyboxUrl != null && (skyboxUrl === url || skyboxUrl.toLowerCase().endsWith(\".env\"));\n const bgOptions = {\n skipSkybox: skyboxIsDds || skyboxIsEnv || options?.skipSkybox,\n skipGround: options?.skipGround,\n };\n // Background renderables (skybox + ground) — deferred so they run AFTER the user\n // has finished tweaking `scene.imageProcessing.*` (skybox/ground/dds materials\n // snapshot exposure/contrast at build time into their per-mesh UBO).\n scene._deferredBuilders.push(async () => {\n const primaryColor = scene.environmentPrimaryColor ?? [0.08697355964132344, 0.08697355964132344, 0.2122208331110881];\n const { groundSize, skyboxSize: autoSkyboxSize, rootPosition } = computeSceneSize(scene, options?.skyboxSize);\n const skyHalfSize = autoSkyboxSize / 2;\n\n if (!bgOptions.skipSkybox) {\n const { buildSolidSkyboxRenderable } = await import(\"../material/pbr/background-solid-skybox.js\");\n scene._renderables.push(buildSolidSkyboxRenderable(scene, textures, skyHalfSize, rootPosition, primaryColor));\n }\n if (!bgOptions.skipGround) {\n const { buildGroundRenderable } = await import(\"../material/pbr/background-ground.js\");\n scene._renderables.push(await buildGroundRenderable(engine, groundSize, rootPosition, primaryColor, groundUrl, groundTexPromise));\n }\n if (skyboxIsDds) {\n const { buildDdsSkyboxRenderable } = await import(\"../material/pbr/background-dds-skybox.js\");\n scene._renderables.push(await buildDdsSkyboxRenderable(scene, skyHalfSize, rootPosition, primaryColor, skyboxUrl));\n }\n if (skyboxIsEnv) {\n const { buildHdrSkyboxRenderable } = await import(\"../material/pbr/background-hdr-skybox.js\");\n scene._renderables.push(buildHdrSkyboxRenderable(scene, textures, skyHalfSize, rootPosition, primaryColor));\n }\n });\n\n return textures;\n}\n\n// ─── .env Parsing ───────────────────────────────────────────────────────────\n\ninterface ParsedEnv {\n faceBlobs: Blob[];\n irradianceSH: Float32Array;\n width: number;\n mipCount: number;\n}\n\nfunction parseEnvFile(buffer: ArrayBuffer): ParsedEnv {\n const bytes = new Uint8Array(buffer);\n\n for (let i = 0; i < 8; i++) {\n if (bytes[i] !== ENV_MAGIC[i]) {\n throw new Error(\"Invalid .env file: bad magic\");\n }\n }\n\n // JSON manifest: UTF-8 from byte 8 until null terminator\n let pos = 8;\n while (pos < bytes.length && bytes[pos] !== 0) {\n pos++;\n }\n const jsonStr = new TextDecoder().decode(bytes.subarray(8, pos));\n pos++; // skip null\n const binaryStart = pos;\n\n const manifest = JSON.parse(jsonStr);\n const width: number = manifest.width;\n const mipCount = mipLevelCount(width, width);\n\n // Irradiance spherical harmonics (9 vec3 coefficients = 27 floats)\n const irr = manifest.irradiance;\n const irradianceSH = new Float32Array(27);\n const shKeys = [\"x\", \"y\", \"z\", \"xx\", \"yy\", \"zz\", \"yz\", \"zx\", \"xy\"];\n for (let i = 0; i < 9; i++) {\n const coeff = irr[shKeys[i]!];\n irradianceSH[i * 3] = coeff[0];\n irradianceSH[i * 3 + 1] = coeff[1];\n irradianceSH[i * 3 + 2] = coeff[2];\n }\n\n // Extract face image blobs (flat: mip0_face0..5, mip1_face0..5, ...)\n const mipmaps: { position: number; length: number }[] = manifest.specular.mipmaps;\n const imageType: string = manifest.imageType || \"image/png\";\n const faceBlobs: Blob[] = [];\n\n for (const entry of mipmaps) {\n const start = binaryStart + entry.position;\n const slice = buffer.slice(start, start + entry.length);\n faceBlobs.push(new Blob([slice], { type: imageType }));\n }\n\n return { faceBlobs, irradianceSH, width, mipCount };\n}\n\n// ─── SH Polynomial → Pre-scaled Harmonics Conversion ────────────────────────\n// Matches Babylon.js: SphericalHarmonics.FromPolynomial() + preScaleForRendering()\n\n/** @internal — exported only for env-helpers.ts; not part of the public API. */\nexport function polynomialToPreScaledHarmonics(poly: Float32Array): Float32Array {\n // poly layout (3 floats per group): x, y, z, xx, yy, zz, yz, zx, xy\n // Constants = K_fromPoly * PI * B_basis (pre-computed; signs folded in).\n // Matches Babylon.js SphericalHarmonics.FromPolynomial() + preScaleForRendering().\n const C00xy = 0.3333338747897695;\n const C00z = 0.33333298856284405;\n const C1 = 1.4999984284682104;\n const C2 = 3.999982863580422;\n const C20zz = 1.3333326611423701;\n const C20xy = 0.6666653397393608;\n const C22 = 1.999991431790211;\n\n // Stride-4 layout matching shader UBO (9 vec3s + pad f32 each)\n const out = new Float32Array(36);\n for (let i = 0; i < 3; i++) {\n const x = poly[i]!;\n const y = poly[3 + i]!;\n const z = poly[6 + i]!;\n const xx = poly[9 + i]!;\n const yy = poly[12 + i]!;\n const zz = poly[15 + i]!;\n const yz = poly[18 + i]!;\n const zx = poly[21 + i]!;\n const xy = poly[24 + i]!;\n out[i] = (xx + yy) * C00xy + zz * C00z; // L00\n out[4 + i] = y * C1; // L1_1\n out[8 + i] = z * C1; // L10\n out[12 + i] = x * C1; // L11\n out[16 + i] = xy * C2; // L2_2\n out[20 + i] = yz * C2; // L2_1\n out[24 + i] = zz * C20zz - (xx + yy) * C20xy; // L20\n out[28 + i] = zx * C2; // L21\n out[32 + i] = (xx - yy) * C22; // L22\n }\n return out;\n}\n","/**\n * Shared SH → SphericalPolynomial conversion.\n *\n * Converts 9-band (L0–L2) spherical harmonic coefficients in channel-major\n * layout into the 27-float polynomial form used by the BJS\n * SphericalPolynomial.FromHarmonics convention.\n *\n * Input layout (Float64Array, 27 entries):\n * sh[ch * 9 + band] where ch ∈ `{0=R, 1=G, 2=B}`, band ∈ 0..8\n * Band order: L00, L1_-1, L10, L11, L2_-2, L2_-1, L20, L21, L22\n * Standard (positive) SH basis — no Condon-Shortley negation.\n *\n * Output layout (Float32Array, 27 entries):\n * poly[field * 3 + ch] where field ∈ `{x,y,z,xx,yy,zz,yz,zx,xy}`\n */\nexport function shToPolynomial(sh: Float64Array): Float32Array {\n const invPI = 1 / Math.PI;\n const poly = new Float32Array(27);\n for (let ch = 0; ch < 3; ch++) {\n const o = ch * 9;\n const L00 = sh[o]!,\n L1_1 = sh[o + 1]!,\n L10 = sh[o + 2]!,\n L11 = sh[o + 3]!;\n const L2_2 = sh[o + 4]!,\n L2_1 = sh[o + 5]!,\n L20 = sh[o + 6]!,\n L21 = sh[o + 7]!,\n L22 = sh[o + 8]!;\n\n poly[0 * 3 + ch] = L11 * 1.02333 * invPI; // x\n poly[1 * 3 + ch] = L1_1 * 1.02333 * invPI; // y\n poly[2 * 3 + ch] = L10 * 1.02333 * invPI; // z\n poly[3 * 3 + ch] = (L00 * 0.886227 - L20 * 0.247708 + L22 * 0.429043) * invPI; // xx\n poly[4 * 3 + ch] = (L00 * 0.886227 - L20 * 0.247708 - L22 * 0.429043) * invPI; // yy\n poly[5 * 3 + ch] = (L00 * 0.886227 + L20 * 0.495417) * invPI; // zz\n poly[6 * 3 + ch] = L2_1 * 0.858086 * invPI; // yz\n poly[7 * 3 + ch] = L21 * 0.858086 * invPI; // zx\n poly[8 * 3 + ch] = L2_2 * 0.858086 * invPI; // xy\n }\n return poly;\n}\n","/**\n * HDR / RGBE file parser (CPU-only)\n *\n * Decodes Radiance .hdr files (RGBE format) into Float32 RGB data\n * and computes spherical harmonics from equirectangular panoramas.\n */\n\nimport { shToPolynomial } from \"../math/spherical-harmonics.js\";\n\n// ─── RGBE Parser ────────────────────────────────────────────────────────────\n\nexport interface HdrImage {\n width: number;\n height: number;\n /** Float32 RGB (3 floats per pixel, row-major) */\n data: Float32Array;\n}\n\nexport function parseRGBE(buffer: ArrayBuffer): HdrImage {\n const bytes = new Uint8Array(buffer);\n let pos = 0;\n\n function readLine(): string {\n let line = \"\";\n while (pos < bytes.length) {\n const ch = bytes[pos++]!;\n if (ch === 10) {\n break;\n }\n if (ch !== 13) {\n line += String.fromCharCode(ch);\n }\n }\n return line;\n }\n\n const sig = readLine();\n if (!sig.startsWith(\"#?\")) {\n throw new Error(\"Invalid HDR: missing #? signature\");\n }\n\n let format = \"\";\n while (pos < bytes.length) {\n const line = readLine();\n if (line === \"\") {\n break;\n }\n if (line.startsWith(\"FORMAT=\")) {\n format = line.slice(7);\n }\n }\n if (format && format !== \"32-bit_rle_rgbe\") {\n throw new Error(`Unsupported HDR format: ${format}`);\n }\n\n const resLine = readLine();\n const resMatch = resLine.match(/-Y\\s+(\\d+)\\s+\\+X\\s+(\\d+)/);\n if (!resMatch) {\n throw new Error(`Invalid HDR resolution: ${resLine}`);\n }\n const height = parseInt(resMatch[1]!, 10);\n const width = parseInt(resMatch[2]!, 10);\n\n const data = new Float32Array(width * height * 3);\n const scanlineBuf = new Uint8Array(width * 4);\n for (let y = 0; y < height; y++) {\n pos = decodeScanline(bytes, pos, width, data, y * width * 3, scanlineBuf);\n }\n\n return { width, height, data };\n}\n\nfunction decodeScanline(bytes: Uint8Array, pos: number, width: number, out: Float32Array, outOffset: number, scanline: Uint8Array): number {\n if (width >= 8 && width <= 0x7fff && bytes[pos] === 2 && bytes[pos + 1] === 2 && bytes[pos + 2] === ((width >> 8) & 0xff) && bytes[pos + 3] === (width & 0xff)) {\n pos += 4;\n for (let ch = 0; ch < 4; ch++) {\n let ptr = ch;\n let count = 0;\n while (count < width) {\n const a = bytes[pos++]!;\n if (a > 128) {\n const runLen = a - 128;\n const val = bytes[pos++]!;\n for (let i = 0; i < runLen; i++) {\n scanline[ptr] = val;\n ptr += 4;\n }\n count += runLen;\n } else {\n for (let i = 0; i < a; i++) {\n scanline[ptr] = bytes[pos++]!;\n ptr += 4;\n }\n count += a;\n }\n }\n }\n for (let x = 0; x < width; x++) {\n rgbeToFloat(scanline[x * 4]!, scanline[x * 4 + 1]!, scanline[x * 4 + 2]!, scanline[x * 4 + 3]!, out, outOffset + x * 3);\n }\n } else {\n for (let x = 0; x < width; x++) {\n rgbeToFloat(bytes[pos]!, bytes[pos + 1]!, bytes[pos + 2]!, bytes[pos + 3]!, out, outOffset + x * 3);\n pos += 4;\n }\n }\n return pos;\n}\n\nfunction rgbeToFloat(r: number, g: number, b: number, e: number, out: Float32Array, off: number): void {\n if (e === 0) {\n out[off] = out[off + 1] = out[off + 2] = 0;\n } else {\n const scale = Math.pow(2, e - 136);\n out[off] = r * scale;\n out[off + 1] = g * scale;\n out[off + 2] = b * scale;\n }\n}\n\n// ─── Spherical Harmonics from Equirect (CPU) ────────────────────────────────\n\nexport function computeSHFromEquirect(data: Float32Array, width: number, height: number): Float32Array {\n const Y00 = 0.282094791773878;\n const Y1 = 0.48860251190292;\n const Y2_2c = 1.092548430592079;\n const Y20c = 0.31539156525252;\n const Y22c = 0.54627421529604;\n\n const sh = new Float64Array(27); // [R: L00..L22, G: L00..L22, B: L00..L22]\n let totalWeight = 0;\n\n for (let py = 0; py < height; py++) {\n const phi = ((py + 0.5) / height) * Math.PI;\n const sinPhi = Math.sin(phi);\n const cosPhi = Math.cos(phi);\n const dOmega = sinPhi * (Math.PI / height) * ((2 * Math.PI) / width);\n\n for (let px = 0; px < width; px++) {\n const theta = ((2 * (px + 0.5)) / width - 1) * Math.PI;\n const x = sinPhi * Math.sin(theta);\n const y = cosPhi;\n const z = sinPhi * Math.cos(theta);\n\n const idx = (py * width + px) * 3;\n let cr = data[idx]!,\n cg = data[idx + 1]!,\n cb = data[idx + 2]!;\n const maxCh = Math.max(cr, cg, cb);\n if (maxCh > 4096) {\n const s = 4096 / maxCh;\n cr *= s;\n cg *= s;\n cb *= s;\n }\n\n const w = dOmega;\n totalWeight += w;\n\n const b0 = Y00;\n const b1 = Y1 * y,\n b2 = Y1 * z,\n b3 = Y1 * x;\n const b4 = Y2_2c * x * y,\n b5 = Y2_2c * y * z;\n const b6 = Y20c * (3 * z * z - 1);\n const b7 = Y2_2c * x * z,\n b8 = Y22c * (x * x - y * y);\n const basis = [b0, b1, b2, b3, b4, b5, b6, b7, b8];\n\n for (let i = 0; i < 9; i++) {\n const bw = basis[i]! * w;\n sh[i] = sh[i]! + cr * bw;\n sh[9 + i] = sh[9 + i]! + cg * bw;\n sh[18 + i] = sh[18 + i]! + cb * bw;\n }\n }\n }\n\n // Normalize to 4π\n const correction = (4 * Math.PI) / totalWeight;\n for (let i = 0; i < 27; i++) {\n sh[i] = sh[i]! * correction;\n }\n\n // Irradiance + Lambertian: L0 *= 1, L1 *= 2/3, L2 *= 1/4\n const irradScale = [1, 2 / 3, 2 / 3, 2 / 3, 0.25, 0.25, 0.25, 0.25, 0.25];\n for (let ch = 0; ch < 3; ch++) {\n for (let i = 0; i < 9; i++) {\n sh[ch * 9 + i] = sh[ch * 9 + i]! * irradScale[i]!;\n }\n }\n\n // SH → BJS SphericalPolynomial (FromHarmonics conversion)\n return shToPolynomial(sh);\n}\n","export default \"struct Params {\\n faceSize: u32,\\n equirectWidth: u32,\\n equirectHeight: u32,\\n _pad: u32,\\n}\\n\\n@group(0) @binding(0) var equirect: texture_2d<f32>;\\n@group(0) @binding(1) var cubeFaces: texture_storage_2d_array<rgba16float, write>;\\n@group(0) @binding(2) var<uniform> params: Params;\\n\\nconst PI = 3.14159265359;\\n\\n// BJS panoramaToCubemap.ts face corners, in GPU layer order:\\n// Layer 0: FACE_RIGHT, Layer 1: FACE_LEFT, Layer 2: FACE_UP,\\n// Layer 3: FACE_DOWN, Layer 4: FACE_FRONT, Layer 5: FACE_BACK\\n// (This matches the _FacesMapping + double-reorder chain which nets to identity.)\\nconst CORNERS = array<vec3<f32>, 24>(\\n vec3( 1.0,-1.0, 1.0), vec3(-1.0,-1.0, 1.0), vec3( 1.0, 1.0, 1.0), vec3(-1.0, 1.0, 1.0), // FACE_RIGHT\\n vec3(-1.0,-1.0,-1.0), vec3( 1.0,-1.0,-1.0), vec3(-1.0, 1.0,-1.0), vec3( 1.0, 1.0,-1.0), // FACE_LEFT\\n vec3(-1.0,-1.0,-1.0), vec3(-1.0,-1.0, 1.0), vec3( 1.0,-1.0,-1.0), vec3( 1.0,-1.0, 1.0), // FACE_UP\\n vec3( 1.0, 1.0,-1.0), vec3( 1.0, 1.0, 1.0), vec3(-1.0, 1.0,-1.0), vec3(-1.0, 1.0, 1.0), // FACE_DOWN\\n vec3( 1.0,-1.0,-1.0), vec3( 1.0,-1.0, 1.0), vec3( 1.0, 1.0,-1.0), vec3( 1.0, 1.0, 1.0), // FACE_FRONT\\n vec3(-1.0,-1.0, 1.0), vec3(-1.0,-1.0,-1.0), vec3(-1.0, 1.0, 1.0), vec3(-1.0, 1.0,-1.0), // FACE_BACK\\n);\\n\\n@compute @workgroup_size(8, 8, 1)\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n let face = gid.z;\\n let size = params.faceSize;\\n if (gid.x >= size || gid.y >= size || face >= 6u) { return; }\\n\\n // BJS parameterization: u, v ∈ [0, (size-1)/size]\\n let u = f32(gid.x) / f32(size);\\n let v = f32(gid.y) / f32(size);\\n\\n // Bilinear interpolation of BJS face corners (matches BJS CreateCubemapTexture)\\n let base = face * 4u;\\n let dir = normalize(\\n CORNERS[base] * (1.0 - u) * (1.0 - v) +\\n CORNERS[base + 1u] * u * (1.0 - v) +\\n CORNERS[base + 2u] * (1.0 - u) * v +\\n CORNERS[base + 3u] * u * v\\n );\\n\\n // BJS CalcProjectionSpherical: atan2(z, x), invertY=true\\n let theta = atan2(dir.z, dir.x);\\n let phi = acos(clamp(dir.y, -1.0, 1.0));\\n let eu = theta / PI * 0.5 + 0.5;\\n let ev = phi / PI;\\n\\n let px = clamp(i32(round(eu * f32(params.equirectWidth))), 0, i32(params.equirectWidth) - 1);\\n let py_raw = clamp(i32(round(ev * f32(params.equirectHeight))), 0, i32(params.equirectHeight) - 1);\\n let py = i32(params.equirectHeight) - py_raw - 1; // invertY\\n let color = textureLoad(equirect, vec2<i32>(px, py), 0);\\n\\n textureStore(cubeFaces, vec2<i32>(gid.xy), i32(face), vec4<f32>(color.rgb, 1.0));\\n}\\n\"","export default \"struct Params {\\n faceSize: u32,\\n mipLevel: u32,\\n totalMips: u32,\\n srcSize: u32,\\n}\\n\\n@group(0) @binding(0) var srcCube: texture_cube<f32>;\\n@group(0) @binding(1) var srcSampler: sampler;\\n@group(0) @binding(2) var dstFaces: texture_storage_2d_array<rgba16float, write>;\\n@group(0) @binding(3) var<uniform> params: Params;\\n\\nconst PI = 3.14159265359;\\nconst SAMPLE_COUNT = 1024u;\\n\\n// BJS face corners (same layout as equirect→cubemap shader)\\nconst CORNERS = array<vec3<f32>, 24>(\\n vec3( 1.0,-1.0, 1.0), vec3(-1.0,-1.0, 1.0), vec3( 1.0, 1.0, 1.0), vec3(-1.0, 1.0, 1.0), // FACE_RIGHT → layer 0\\n vec3(-1.0,-1.0,-1.0), vec3( 1.0,-1.0,-1.0), vec3(-1.0, 1.0,-1.0), vec3( 1.0, 1.0,-1.0), // FACE_LEFT → layer 1\\n vec3(-1.0,-1.0,-1.0), vec3(-1.0,-1.0, 1.0), vec3( 1.0,-1.0,-1.0), vec3( 1.0,-1.0, 1.0), // FACE_UP → layer 2\\n vec3( 1.0, 1.0,-1.0), vec3( 1.0, 1.0, 1.0), vec3(-1.0, 1.0,-1.0), vec3(-1.0, 1.0, 1.0), // FACE_DOWN → layer 3\\n vec3( 1.0,-1.0,-1.0), vec3( 1.0,-1.0, 1.0), vec3( 1.0, 1.0,-1.0), vec3( 1.0, 1.0, 1.0), // FACE_FRONT → layer 4\\n vec3(-1.0,-1.0, 1.0), vec3(-1.0,-1.0,-1.0), vec3(-1.0, 1.0, 1.0), vec3(-1.0, 1.0,-1.0), // FACE_BACK → layer 5\\n);\\n\\nfn bjsFaceDir(face: u32, u: f32, v: f32) -> vec3<f32> {\\n let base = face * 4u;\\n return normalize(\\n CORNERS[base] * (1.0 - u) * (1.0 - v) +\\n CORNERS[base + 1u] * u * (1.0 - v) +\\n CORNERS[base + 2u] * (1.0 - u) * v +\\n CORNERS[base + 3u] * u * v\\n );\\n}\\n\\nfn radicalInverseVdC(inputBits: u32) -> f32 {\\n var bits = inputBits;\\n bits = (bits << 16u) | (bits >> 16u);\\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\\n return f32(bits) * 2.3283064365386963e-10;\\n}\\n\\nfn importanceSampleGGX(xi0: f32, xi1: f32, alphaG: f32) -> vec3<f32> {\\n let a2 = alphaG * alphaG;\\n let phi = 2.0 * PI * xi0;\\n let cosTheta = sqrt((1.0 - xi1) / (1.0 + (a2 - 1.0) * xi1));\\n let sinTheta = sqrt(1.0 - cosTheta * cosTheta);\\n return vec3<f32>(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);\\n}\\n\\nfn D_GGX(NdotH: f32, a2: f32) -> f32 {\\n let d = NdotH * NdotH * (a2 - 1.0) + 1.0;\\n return a2 / (PI * d * d);\\n}\\n\\nfn faceDirection(face: u32, u: f32, v: f32) -> vec3<f32> {\\n return bjsFaceDir(face, u, v);\\n}\\n\\n@compute @workgroup_size(8, 8, 1)\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n let face = gid.z;\\n let mipSize = params.faceSize >> params.mipLevel;\\n if (gid.x >= mipSize || gid.y >= mipSize || face >= 6u) { return; }\\n\\n let u = f32(gid.x) / f32(mipSize);\\n let v = f32(gid.y) / f32(mipSize);\\n let N = normalize(faceDirection(face, u, v));\\n\\n let alphaG = pow(2.0, f32(params.mipLevel) / 0.8) / f32(params.srcSize);\\n\\n if (params.mipLevel == 0u) {\\n let color = textureSampleLevel(srcCube, srcSampler, N, 0.0);\\n textureStore(dstFaces, vec2<i32>(gid.xy), i32(face), vec4<f32>(color.rgb, 1.0));\\n return;\\n }\\n\\n var upVec = select(vec3<f32>(1.0, 0.0, 0.0), vec3<f32>(0.0, 0.0, 1.0), abs(N.z) < 0.999);\\n let tangentX = normalize(cross(upVec, N));\\n let tangentY = cross(N, tangentX);\\n\\n var result = vec3<f32>(0.0);\\n var totalWeight = 0.0;\\n let srcDim = f32(params.srcSize);\\n let omegaP = 4.0 * PI / (6.0 * srcDim * srcDim);\\n let maxLod = f32(params.totalMips) - 1.0;\\n\\n for (var i = 0u; i < SAMPLE_COUNT; i++) {\\n let xi0 = f32(i) / f32(SAMPLE_COUNT);\\n let xi1 = radicalInverseVdC(i);\\n let H = importanceSampleGGX(xi0, xi1, alphaG);\\n let H_world = tangentX * H.x + tangentY * H.y + N * H.z;\\n let NdotH = max(dot(N, H_world), 0.0);\\n let L = 2.0 * NdotH * H_world - N;\\n let NdotL = dot(N, L);\\n\\n if (NdotL > 0.0) {\\n let a2 = alphaG * alphaG;\\n let pdf = D_GGX(NdotH, a2) / 4.0;\\n let omegaS = 1.0 / (f32(SAMPLE_COUNT) * max(pdf, 0.0001));\\n let sampleLod = clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0, maxLod);\\n let sampleColor = textureSampleLevel(srcCube, srcSampler, L, sampleLod);\\n result += sampleColor.rgb * NdotL;\\n totalWeight += NdotL;\\n }\\n }\\n\\n if (totalWeight > 0.0) { result /= totalWeight; }\\n textureStore(dstFaces, vec2<i32>(gid.xy), i32(face), vec4<f32>(result, 1.0));\\n}\\n\"","export default \"@group(0) @binding(0) var outputTex: texture_storage_2d<rgba16float, write>;\\n\\nfn radicalInverseVdC(inputBits: u32) -> f32 {\\n var bits = inputBits;\\n bits = (bits << 16u) | (bits >> 16u);\\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\\n return f32(bits) * 2.3283064365386963e-10;\\n}\\n\\nfn importanceSampleGGX(xi0: f32, xi1: f32, a2: f32) -> vec3f {\\n let phi = 2.0 * 3.14159265359 * xi0;\\n let cosTheta = sqrt((1.0 - xi1) / (1.0 + (a2 - 1.0) * xi1));\\n let sinTheta = sqrt(1.0 - cosTheta * cosTheta);\\n return vec3f(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);\\n}\\n\\nfn integrateBRDF(NdotV: f32, roughness: f32) -> vec2f {\\n let V = vec3f(sqrt(1.0 - NdotV * NdotV), 0.0, NdotV);\\n let a = roughness * roughness;\\n let a2 = a * a;\\n var A = 0.0; var B = 0.0;\\n let sampleCount = 1024u;\\n for (var i = 0u; i < sampleCount; i++) {\\n let xi0 = f32(i) / f32(sampleCount);\\n let xi1 = radicalInverseVdC(i);\\n let H = importanceSampleGGX(xi0, xi1, a2);\\n let VdotH = max(dot(V, H), 0.0);\\n let L = 2.0 * VdotH * H - V;\\n let NdotL = max(L.z, 0.0); let NdotH = max(H.z, 0.0);\\n if (NdotL > 0.0 && NdotH > 0.0) {\\n let GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - a2) + a2);\\n let GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - a2) + a2);\\n let V_Vis = (0.5 / max(GGXV + GGXL, 1e-6)) * NdotL * (4.0 * VdotH / NdotH);\\n let Fc = pow(1.0 - VdotH, 5.0);\\n A += (1.0 - Fc) * V_Vis; B += Fc * V_Vis;\\n }\\n }\\n return vec2f(A / f32(sampleCount), B / f32(sampleCount));\\n}\\n\\n@compute @workgroup_size(8, 8)\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n if (gid.x >= 256u || gid.y >= 256u) { return; }\\n let NdotV = max((f32(gid.x) + 0.5) / 256.0, 0.001);\\n let roughness = max((f32(gid.y) + 0.5) / 256.0, 0.04);\\n let result = integrateBRDF(NdotV, roughness);\\n textureStore(outputTex, vec2u(gid.x, gid.y), vec4f(result.y, result.x + result.y, 0.0, 1.0));\\n}\\n\"","/**\n * HDR IBL Pipeline (GPU compute)\n *\n * GPU compute shaders for equirect→cubemap conversion,\n * importance-sampled GGX cubemap prefiltering, and BRDF LUT generation.\n */\n\nimport type { HdrImage } from \"./hdr-parser.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport { createUniformBuffer, createEmptyUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport equirectToCubeWGSL from \"../../shaders/hdr-equirect-to-cube.compute.wgsl?raw\";\nimport prefilterCubeWGSL from \"../../shaders/hdr-prefilter-cube.compute.wgsl?raw\";\nimport brdfLutWGSL from \"../../shaders/hdr-brdf-lut.compute.wgsl?raw\";\n\nexport function equirectToCubemapGPU(engine: EngineContext, hdr: HdrImage, faceSize: number): GPUTexture {\n const device = engine._device;\n // Upload equirect as a 2D texture\n const equirectTex = device.createTexture({\n size: [hdr.width, hdr.height],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n {\n const rgba = new Float32Array(hdr.width * hdr.height * 4);\n for (let i = 0; i < hdr.width * hdr.height; i++) {\n rgba[i * 4] = hdr.data[i * 3]!;\n rgba[i * 4 + 1] = hdr.data[i * 3 + 1]!;\n rgba[i * 4 + 2] = hdr.data[i * 3 + 2]!;\n rgba[i * 4 + 3] = 1;\n }\n device.queue.writeTexture({ texture: equirectTex }, rgba.buffer, { bytesPerRow: hdr.width * 16 }, { width: hdr.width, height: hdr.height });\n }\n\n // Create the output cubemap\n const cubeTex = device.createTexture({\n size: [faceSize, faceSize, 6],\n format: \"rgba16float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_SRC,\n dimension: \"2d\",\n });\n\n // Run compute shader (uses BJS face corners + CalcProjectionSpherical)\n const module = device.createShaderModule({ code: equirectToCubeWGSL });\n const pipeline = device.createComputePipeline({\n layout: \"auto\",\n compute: { module, entryPoint: \"main\" },\n });\n const paramBuf = createUniformBuffer(engine, new Uint32Array([faceSize, hdr.width, hdr.height, 0]));\n\n const bg = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: equirectTex.createView() },\n { binding: 1, resource: cubeTex.createView({ dimension: \"2d-array\", arrayLayerCount: 6 }) },\n { binding: 2, resource: { buffer: paramBuf } },\n ],\n });\n\n const enc = device.createCommandEncoder();\n const pass = enc.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bg);\n pass.dispatchWorkgroups(Math.ceil(faceSize / 8), Math.ceil(faceSize / 8), 6);\n pass.end();\n device.queue.submit([enc.finish()]);\n\n equirectTex.destroy();\n paramBuf.destroy();\n return cubeTex;\n}\n\n// ─── Cubemap Prefiltering (GPU Compute, Importance-Sampled GGX) ─────────────\n\nexport function prefilterCubemapGPU(engine: EngineContext, srcCube: GPUTexture, faceSize: number, mipCount: number): GPUTexture {\n const device = engine._device;\n const dstCube = device.createTexture({\n size: { width: faceSize, height: faceSize, depthOrArrayLayers: 6 },\n mipLevelCount: mipCount,\n format: \"rgba16float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.COPY_DST,\n });\n\n const srcCubeView = srcCube.createView({ dimension: \"cube\" });\n const srcSampler = getBilinearSampler(engine);\n\n const pipeline = device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: prefilterCubeWGSL }), entryPoint: \"main\" },\n });\n\n const paramsBuffer = createEmptyUniformBuffer(engine, 16);\n\n // LOD 0: exact texel copy (no bilinear resampling) to match BJS\n {\n const copyEnc = device.createCommandEncoder();\n copyEnc.copyTextureToTexture({ texture: srcCube }, { texture: dstCube, mipLevel: 0 }, { width: faceSize, height: faceSize, depthOrArrayLayers: 6 });\n device.queue.submit([copyEnc.finish()]);\n }\n\n // LODs 1+: importance-sampled GGX prefilter\n for (let mip = 1; mip < mipCount; mip++) {\n const mipSize = faceSize >> mip;\n if (mipSize < 1) {\n break;\n }\n\n device.queue.writeBuffer(paramsBuffer, 0, new Uint32Array([faceSize, mip, mipCount, faceSize]));\n\n const dstView = dstCube.createView({\n dimension: \"2d-array\",\n baseMipLevel: mip,\n mipLevelCount: 1,\n baseArrayLayer: 0,\n arrayLayerCount: 6,\n });\n\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: srcCubeView },\n { binding: 1, resource: srcSampler },\n { binding: 2, resource: dstView },\n { binding: 3, resource: { buffer: paramsBuffer } },\n ],\n });\n\n // One submit per mip ensures params buffer is consumed before next writeBuffer\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(Math.ceil(mipSize / 8), Math.ceil(mipSize / 8), 6);\n pass.end();\n device.queue.submit([encoder.finish()]);\n }\n\n srcCube.destroy();\n paramsBuffer.destroy();\n return dstCube;\n}\n\n// ─── BRDF LUT ───────────────────────────────────────────────────────────────\n\nlet _brdfPipeline: GPUComputePipeline | null = null;\nlet _brdfPipelineDevice: GPUDevice | null = null;\n\nexport function generateBrdfLut(engine: EngineContext): GPUTexture {\n const device = engine._device;\n if (!_brdfPipeline || _brdfPipelineDevice !== device) {\n _brdfPipeline = device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: brdfLutWGSL }), entryPoint: \"main\" },\n });\n _brdfPipelineDevice = device;\n }\n const size = 256;\n const texture = device.createTexture({\n size: { width: size, height: size },\n format: \"rgba16float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,\n });\n const bindGroup = device.createBindGroup({\n layout: _brdfPipeline.getBindGroupLayout(0),\n entries: [{ binding: 0, resource: texture.createView() }],\n });\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(_brdfPipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(Math.ceil(size / 8), Math.ceil(size / 8));\n pass.end();\n device.queue.submit([encoder.finish()]);\n return texture;\n}\n","/**\n * HDR Environment Loader\n *\n * Loads a Radiance .hdr (RGBE) equirectangular panorama and produces\n * GPU-ready IBL textures identical to BJS HDRCubeTexture.\n *\n * Pipeline:\n * 1. Parse RGBE header + RLE scanlines → Float32 equirect (CPU)\n * 2. Compute spherical harmonics from equirect (CPU)\n * 3. Equirect → cubemap via compute shader (GPU)\n * 4. Prefilter cubemap with importance-sampled GGX (GPU compute)\n * 5. Generate BRDF split-sum LUT (GPU compute)\n * 6. Return EnvironmentTextures (same interface as load-env.ts)\n */\n\nimport type { EnvironmentTextures } from \"../loader-env/load-env.js\";\nimport type { SceneContext } from \"../scene/scene.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { acquireGPUTexture, releaseGPUTexture } from \"../resource/gpu-pool.js\";\nimport { assembleEnvironmentTextures } from \"../loader-env/env-helpers.js\";\nimport { parseRGBE, computeSHFromEquirect } from \"./hdr-parser.js\";\nimport { equirectToCubemapGPU, prefilterCubemapGPU, generateBrdfLut } from \"./hdr-ibl-pipeline.js\";\nimport { mipLevelCount } from \"../texture/mip-count.js\";\n\n// ─── Public API ─────────────────────────────────────────────────────────────\n\nexport interface HdrLoadOptions {\n /** Cubemap face size in pixels. Default 256. */\n faceSize?: number;\n /** When true, render the HDR cubemap as the skybox background. */\n useCubemapSkybox?: boolean;\n /** When true, skip the ground plane. */\n skipGround?: boolean;\n /** Skybox size matching BJS createDefaultEnvironment skyboxSize option. */\n skyboxSize?: number;\n}\n\n/**\n * Loads a Radiance `.hdr` (RGBE) equirectangular panorama and builds GPU-ready IBL textures\n * (prefiltered specular cubemap, BRDF LUT, and irradiance spherical harmonics), then attaches\n * them to the scene and queues optional skybox/ground background renderables.\n * @param scene - The scene to receive the environment textures and background renderables.\n * @param url - URL of the `.hdr` file to fetch.\n * @param options - Optional face size, skybox, and ground settings.\n * @returns The assembled environment textures (also stored on the scene).\n */\nexport async function loadHdrEnvironment(scene: SceneContext, url: string, options?: HdrLoadOptions): Promise<EnvironmentTextures> {\n const engine = scene.engine as EngineContext;\n const faceSize = options?.faceSize ?? 256;\n\n // 1. Fetch and parse RGBE\n const buffer = await fetch(url).then((r) => r.arrayBuffer());\n const hdr = parseRGBE(buffer);\n\n // 2. Compute spherical harmonics from equirect (CPU)\n const irradianceSH = computeSHFromEquirect(hdr.data, hdr.width, hdr.height);\n\n // 3. Equirect → cubemap (GPU compute)\n const srcCube = equirectToCubemapGPU(engine, hdr, faceSize);\n\n // 4. Prefilter cubemap for IBL (GPU compute, importance-sampled GGX)\n const mipCount = mipLevelCount(faceSize, faceSize);\n const specularCube = prefilterCubemapGPU(engine, srcCube, faceSize, mipCount);\n\n // 5. BRDF LUT\n const brdfLut = generateBrdfLut(engine);\n\n // 6. Assemble\n const textures = assembleEnvironmentTextures(specularCube, brdfLut, irradianceSH, 1.0, engine);\n\n scene._envTextures = textures;\n\n acquireGPUTexture(specularCube);\n acquireGPUTexture(brdfLut);\n scene._disposables.push(() => {\n releaseGPUTexture(specularCube);\n releaseGPUTexture(brdfLut);\n });\n\n scene.imageProcessing.toneMappingEnabled = false;\n scene.imageProcessing.exposure = 0.8;\n scene.imageProcessing.contrast = 1.2;\n\n // Background renderables (skybox + ground) — deferred so they run AFTER the user\n // has finished tweaking `scene.imageProcessing.*` (skybox materials snapshot\n // exposure/contrast at build time into their per-mesh UBO).\n const useHdr = !!options?.useCubemapSkybox;\n const skipGround = !!options?.skipGround;\n scene._deferredBuilders.push(async () => {\n if (useHdr && textures.specularCubeView) {\n const { computeSceneSize } = await import(\"../material/pbr/scene-size.js\");\n const { skyboxSize: autoSkyboxSize, rootPosition } = computeSceneSize(scene, options?.skyboxSize);\n const primaryColor = scene.environmentPrimaryColor ?? [0.08697355964132344, 0.08697355964132344, 0.2122208331110881];\n const { buildHdrSkyboxRenderable } = await import(\"../material/pbr/background-hdr-skybox.js\");\n scene._renderables.push(buildHdrSkyboxRenderable(scene, textures, autoSkyboxSize / 2, rootPosition, primaryColor));\n }\n if (!useHdr || !skipGround) {\n const primaryColor = scene.environmentPrimaryColor ?? [0.08697355964132344, 0.08697355964132344, 0.2122208331110881];\n const { computeSceneSize } = await import(\"../material/pbr/scene-size.js\");\n const { groundSize, skyboxSize: autoSkyboxSize, rootPosition } = computeSceneSize(scene, options?.skyboxSize);\n if (!useHdr) {\n const { buildSolidSkyboxRenderable } = await import(\"../material/pbr/background-solid-skybox.js\");\n scene._renderables.push(buildSolidSkyboxRenderable(scene, textures, autoSkyboxSize / 2, rootPosition, primaryColor));\n }\n if (!skipGround) {\n const { buildGroundRenderable } = await import(\"../material/pbr/background-ground.js\");\n scene._renderables.push(await buildGroundRenderable(engine, groundSize, rootPosition, primaryColor));\n }\n }\n });\n\n return textures;\n}\n","/**\n * GPU mipmap generation via render-pass blit.\n * WebGPU has no built-in generateMipmaps() — we render a fullscreen triangle\n * from mip N-1 → mip N for each level. For sRGB textures, the GPU automatically\n * converts sRGB→linear on read and linear→sRGB on write, so filtering is correct.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\n\nconst BLIT_SHADER = `@group(0)@binding(0)var t:texture_2d<f32>;@group(0)@binding(1)var s:sampler;\nstruct V{@builtin(position)p:vec4f,@location(0)u:vec2f};\n@vertex fn vs(@builtin(vertex_index)i:u32)->V{let p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3))[i];return V(vec4f(p,0,1),p*vec2f(.5,-.5)+.5);}\n@fragment fn fs(v:V)->@location(0)vec4f{return textureSample(t,s,v.u);}`;\n\nlet pipelineCache: Map<string, GPURenderPipeline> | null = null;\nlet shaderModule: GPUShaderModule | null = null;\nlet linearSampler: GPUSampler | null = null;\nlet bindGroupLayout: GPUBindGroupLayout | null = null;\nlet cachedDevice: GPUDevice | null = null;\n\nfunction clearCache(): void {\n pipelineCache?.clear();\n pipelineCache = null;\n shaderModule = null;\n linearSampler = null;\n bindGroupLayout = null;\n cachedDevice = null;\n}\n\nfunction ensureResources(engine: EngineContext): void {\n const device = engine._device;\n if (device !== cachedDevice) {\n clearCache();\n cachedDevice = device;\n }\n shaderModule ??= device.createShaderModule({ code: BLIT_SHADER });\n linearSampler ??= getBilinearSampler(engine);\n bindGroupLayout ??= device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: {} },\n ],\n });\n}\n\nfunction getPipeline(engine: EngineContext, format: GPUTextureFormat): GPURenderPipeline {\n const device = engine._device;\n ensureResources(engine);\n pipelineCache ??= new Map();\n let pipeline = pipelineCache.get(format);\n if (!pipeline) {\n pipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout!] }),\n vertex: { module: shaderModule!, entryPoint: \"vs\" },\n fragment: { module: shaderModule!, entryPoint: \"fs\", targets: [{ format }] },\n primitive: { topology: \"triangle-list\" },\n });\n pipelineCache.set(format, pipeline);\n }\n return pipeline;\n}\n\n/** Generate mip chain for a 2D texture via GPU blit. Works for cube faces via optional `face` layer index. */\nexport function generateMipmaps(engine: EngineContext, texture: GPUTexture, face?: number): void {\n const device = engine._device;\n const encoder = device.createCommandEncoder();\n recordMipmaps(engine, texture, encoder, face);\n device.queue.submit([encoder.finish()]);\n}\n\nexport function recordMipmaps(engine: EngineContext, texture: GPUTexture, encoder: GPUCommandEncoder, face?: number): void {\n if (texture.mipLevelCount <= 1) {\n return;\n }\n const device = engine._device;\n const pipeline = getPipeline(engine, texture.format);\n const vp = face != null ? { dimension: \"2d\" as const, baseArrayLayer: face, arrayLayerCount: 1 } : {};\n for (let mip = 1; mip < texture.mipLevelCount; mip++) {\n const srcView = texture.createView({ baseMipLevel: mip - 1, mipLevelCount: 1, ...vp });\n const dstView = texture.createView({ baseMipLevel: mip, mipLevelCount: 1, ...vp });\n const bindGroup = device.createBindGroup({\n layout: bindGroupLayout!,\n entries: [\n { binding: 0, resource: srcView },\n { binding: 1, resource: linearSampler! },\n ],\n });\n const pass = encoder.beginRenderPass({\n colorAttachments: [{ view: dstView, loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.draw(3);\n pass.end();\n }\n}\n","/** CubeTexture — loads 6 face images into a GPU cube texture with mipmaps. */\nimport { getTrilinearSampler } from \"../resource/samplers.js\";\nimport { generateMipmaps } from \"./generate-mipmaps.js\";\nimport { mipLevelCount } from \"./mip-count.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\n\ntype CubeResult = { texture: GPUTexture; view: GPUTextureView; sampler: GPUSampler };\nlet _cc: WeakMap<GPUDevice, Map<string, Promise<CubeResult>>> | null = null;\n\nexport function loadCubeTexture(engine: EngineContext, baseUrl: string, ext = \".jpg\"): Promise<CubeResult> {\n const device = engine._device;\n if (!_cc) {\n _cc = new WeakMap();\n }\n let dc = _cc.get(device);\n if (!dc) {\n dc = new Map();\n _cc.set(device, dc);\n }\n const key = `${baseUrl}\\0${ext}`;\n const hit = dc.get(key);\n if (hit) {\n return hit;\n }\n const p = (async () => {\n const bitmaps = await Promise.all(\n [\"_px\", \"_nx\", \"_py\", \"_ny\", \"_pz\", \"_nz\"].map(async (s) => {\n const r = await fetch(`${baseUrl}${s}${ext}`);\n if (!r.ok) {\n throw new Error(`Cube face load failed: ${baseUrl}${s}${ext}`);\n }\n return createImageBitmap(await r.blob(), { premultiplyAlpha: \"none\", colorSpaceConversion: \"none\" });\n })\n );\n const sz = bitmaps[0]!.width;\n const tex = device.createTexture({\n size: [sz, sz, 6],\n format: \"rgba8unorm\",\n dimension: \"2d\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n mipLevelCount: mipLevelCount(sz, sz),\n });\n for (let i = 0; i < 6; i++) {\n device.queue.copyExternalImageToTexture({ source: bitmaps[i]! }, { texture: tex, origin: [0, 0, i], premultipliedAlpha: false }, [sz, sz, 1]);\n bitmaps[i]!.close();\n generateMipmaps(engine, tex, i);\n }\n return {\n texture: tex,\n view: tex.createView({ dimension: \"cube\", format: \"rgba8unorm\" }),\n sampler: getTrilinearSampler(engine),\n };\n })();\n dc.set(key, p);\n p.catch(() => dc!.delete(key));\n return p;\n}\n","/** High-level skybox loader.\n * Loads a cube texture and registers a skybox for the auto-builder. */\n\nimport type { SceneContext } from \"../scene/scene.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { loadCubeTexture } from \"../texture/cube-texture.js\";\nimport { createBoxData } from \"../mesh/create-box.js\";\nimport { createMappedBuffer } from \"../resource/gpu-buffers.js\";\n\n/** Skybox data stored on the scene for the auto-builder. */\nexport interface SkyboxData {\n cubeView: GPUTextureView;\n cubeSampler: GPUSampler;\n posBuffer: GPUBuffer;\n normBuffer: GPUBuffer;\n idxBuffer: GPUBuffer;\n idxCount: number;\n worldMatrix: Float32Array;\n}\n\n/** Load a skybox cube texture and register it on the scene.\n * The auto-builder will create the pipeline and render it.\n *\n * @param scene - Scene to register the skybox in\n * @param baseUrl - Base URL for cube faces (e.g., 'textures/skybox')\n * @param ext - File extension (e.g., '.jpg', '.png')\n * @param size - Box size (default 100, matches Babylon)\n */\nexport async function loadSkybox(scene: SceneContext, baseUrl: string, ext: string, size = 100): Promise<void> {\n const eng = scene.engine as EngineContext;\n\n const cubeTex = await loadCubeTexture(eng, baseUrl, ext);\n\n const boxData = createBoxData(size);\n const posBuffer = createMappedBuffer(eng, boxData.positions, GPUBufferUsage.VERTEX);\n const normBuffer = createMappedBuffer(eng, boxData.normals, GPUBufferUsage.VERTEX);\n const idxBuffer = createMappedBuffer(eng, boxData.indices, GPUBufferUsage.INDEX);\n\n const world = new Float32Array(16);\n world[0] = 1;\n world[5] = 1;\n world[10] = 1;\n world[15] = 1;\n\n const skyboxData: SkyboxData = {\n cubeView: cubeTex.view,\n cubeSampler: cubeTex.sampler,\n posBuffer,\n normBuffer,\n idxBuffer,\n idxCount: boxData.indices.length,\n worldMatrix: world,\n };\n\n // Build the skybox renderable inline — task supplies sceneBG at draw time, no ordering constraints.\n const { buildSkyboxRenderable } = await import(\"./skybox-renderable.js\");\n scene._renderables.push(buildSkyboxRenderable(scene, skyboxData));\n}\n","/** Standard .ply Gaussian-Splatting parser (no chunks, no SH).\n *\n * Pure function: ArrayBuffer (.ply asset) → `ParsedSplat` containing\n * a 32-byte/splat row buffer (position + scale + colour + quat). Mirrors the\n * algorithm BJS uses in `GaussianSplattingMesh.ConvertPLYToSplat`.\n *\n * Compressed PLY (`element chunk`) and SH coefficients (`element sh` or\n * per-vertex `f_rest_*`) are handled by a separate, dynamic-imported parser\n * (`splat-ply-compressed.ts`) so plain `.ply` scenes (e.g. scene 120) don't\n * bundle the additional decoder code. `isPlyCompressedOrSH` lets callers\n * decide which path to take. */\n\nimport type { ParsedSplat } from \"./splat-data.js\";\n\nconst SH_C0 = 0.28209479177387814;\n\n/** True when the buffer starts with a PLY ASCII header that contains `end_header\\n`. */\nexport function isPly(data: ArrayBuffer): boolean {\n const ubuf = new Uint8Array(data, 0, Math.min(data.byteLength, 1024 * 10));\n const header = new TextDecoder().decode(ubuf);\n return header.startsWith(\"ply\") && header.indexOf(\"end_header\\n\") >= 0;\n}\n\n/** True when the PLY header declares either an `element chunk` block\n * (compressed PLY) or any spherical-harmonics data (`element sh` block or\n * per-vertex `f_rest_*` properties). Callers route these assets through the\n * separately-imported compressed parser. */\nexport function isPlyCompressedOrSH(data: ArrayBuffer): boolean {\n const ubuf = new Uint8Array(data, 0, Math.min(data.byteLength, 1024 * 10));\n const header = new TextDecoder().decode(ubuf);\n const end = header.indexOf(\"end_header\\n\");\n if (end < 0) {\n return false;\n }\n const slice = header.slice(0, end);\n return slice.indexOf(\"element chunk \") >= 0 || slice.indexOf(\"element sh \") >= 0 || slice.indexOf(\"f_rest_\") >= 0;\n}\n\n/** Decode a standard PLY ArrayBuffer into the engine's internal splat row\n * layout. Returns `{ data: ArrayBuffer(0) }` when the property layout is\n * unsupported; returns `{ data }` echoing the input untouched when the buffer\n * isn't a PLY at all (so callers can chain a `.splat` fast-path). */\nexport function convertPlyToSplat(data: ArrayBuffer): ParsedSplat {\n const ubuf = new Uint8Array(data);\n const header = new TextDecoder().decode(ubuf.slice(0, 1024 * 10));\n const headerEnd = \"end_header\\n\";\n const headerEndIndex = header.indexOf(headerEnd);\n if (headerEndIndex < 0) {\n return { data };\n }\n\n const vmatch = /element vertex (\\d+)\\n/.exec(header);\n if (!vmatch) {\n return { data };\n }\n const vertexCount = parseInt(vmatch[1]!, 10);\n\n const offsets: Record<string, number> = { double: 8, int: 4, uint: 4, float: 4, short: 2, ushort: 2, uchar: 1 };\n const properties: { name: string; type: string; offset: number }[] = [];\n let rowOffset = 0;\n for (const line of header.slice(0, headerEndIndex).split(\"\\n\")) {\n if (!line.startsWith(\"property \")) {\n continue;\n }\n const [, type, name] = line.split(\" \");\n if (!type || !name || offsets[type] === undefined) {\n return { data: new ArrayBuffer(0) };\n }\n properties.push({ name, type, offset: rowOffset });\n rowOffset += offsets[type]!;\n }\n\n const dv = new DataView(data, headerEndIndex + headerEnd.length);\n const ROW_OUTPUT_LENGTH = 32;\n const out = new ArrayBuffer(ROW_OUTPUT_LENGTH * vertexCount);\n\n let off = 0;\n for (let i = 0; i < vertexCount; i++) {\n const position = new Float32Array(out, i * ROW_OUTPUT_LENGTH, 3);\n const scale = new Float32Array(out, i * ROW_OUTPUT_LENGTH + 12, 3);\n const rgba = new Uint8ClampedArray(out, i * ROW_OUTPUT_LENGTH + 24, 4);\n const rot = new Uint8ClampedArray(out, i * ROW_OUTPUT_LENGTH + 28, 4);\n\n let r0 = 255,\n r1 = 0,\n r2 = 0,\n r3 = 0;\n\n for (const prop of properties) {\n let value: number;\n switch (prop.type) {\n case \"float\":\n value = dv.getFloat32(off + prop.offset, true);\n break;\n case \"int\":\n value = dv.getInt32(off + prop.offset, true);\n break;\n case \"uint\":\n value = dv.getUint32(off + prop.offset, true);\n break;\n case \"uchar\":\n value = dv.getUint8(off + prop.offset);\n break;\n case \"short\":\n value = dv.getInt16(off + prop.offset, true);\n break;\n case \"ushort\":\n value = dv.getUint16(off + prop.offset, true);\n break;\n case \"double\":\n value = dv.getFloat64(off + prop.offset, true);\n break;\n default:\n continue;\n }\n switch (prop.name) {\n case \"x\":\n position[0] = value;\n break;\n case \"y\":\n position[1] = value;\n break;\n case \"z\":\n position[2] = value;\n break;\n case \"scale_0\":\n scale[0] = Math.exp(value);\n break;\n case \"scale_1\":\n scale[1] = Math.exp(value);\n break;\n case \"scale_2\":\n scale[2] = Math.exp(value);\n break;\n case \"red\":\n case \"diffuse_red\":\n rgba[0] = value;\n break;\n case \"green\":\n case \"diffuse_green\":\n rgba[1] = value;\n break;\n case \"blue\":\n case \"diffuse_blue\":\n rgba[2] = value;\n break;\n case \"f_dc_0\":\n rgba[0] = (0.5 + SH_C0 * value) * 255;\n break;\n case \"f_dc_1\":\n rgba[1] = (0.5 + SH_C0 * value) * 255;\n break;\n case \"f_dc_2\":\n rgba[2] = (0.5 + SH_C0 * value) * 255;\n break;\n case \"f_dc_3\":\n rgba[3] = (0.5 + SH_C0 * value) * 255;\n break;\n case \"opacity\":\n rgba[3] = (1 / (1 + Math.exp(-value))) * 255;\n break;\n case \"rot_0\":\n r0 = value;\n break;\n case \"rot_1\":\n r1 = value;\n break;\n case \"rot_2\":\n r2 = value;\n break;\n case \"rot_3\":\n r3 = value;\n break;\n }\n }\n\n const len = Math.hypot(r0, r1, r2, r3) || 1;\n const inv = 1 / len;\n rot[0] = r0 * inv * 127.5 + 127.5;\n rot[1] = r1 * inv * 127.5 + 127.5;\n rot[2] = r2 * inv * 127.5 + 127.5;\n rot[3] = r3 * inv * 127.5 + 127.5;\n\n off += rowOffset;\n }\n\n return { data: out };\n}\n","/** Splat row-buffer → GPU-ready typed arrays + bbox.\n *\n * Input : ArrayBuffer in the standard splat row layout\n * (32 bytes/splat — see `splat-ply-parser.ts`).\n * Output : positions/covA/covB (RGBA32F-packed, 4 floats per texel)\n * + colours (RGBA32F, 0..1)\n * + texture dimensions large enough to hold all splats one-per-texel\n * + axis-aligned bounding box (used for camera framing).\n *\n * The math mirrors BJS `GaussianSplattingMesh._loadData`: rotate-then-scale\n * the unit covariance matrix and store its 6 unique upper-triangle entries as\n * two RGB triples (covA[xy/zw split via vec3+vec3]). */\n\nconst ROW_LENGTH = 32;\n\n/** Result of parsing a Gaussian-Splatting asset (PLY / SPZ / SOG / .splat).\n *\n * `data` is the standard 32-byte/splat row buffer that `buildSplatGeometry`\n * consumes. `sh`, if present, is a *flat* coefficient buffer with BJS encoding\n * (`value * 127.5 + 127.5` clamped to 0..255) laid out as\n * `splatCount * shCoefficientCount` bytes in\n * `[R0,G0,B0, R1,G1,B1, …, R(N-1),G(N-1),B(N-1)]` order per splat. The\n * `gaussian-splatting-pipeline-sh` module packs it into 1..5 `rgba32uint`\n * textures at attach time. */\nexport interface ParsedSplat {\n /** 32-byte/splat row buffer (position + scale + colour + quat). */\n data: ArrayBuffer;\n /** Flat SH coefficient bytes (splatCount * shVectorCount * 3 bytes),\n * BJS-quantized. Each byte's shader decode is `(v * 2/255) - 1`. */\n sh?: Uint8Array;\n /** Spherical-harmonics degree (1..4) when `sh` is set, else absent. */\n shDegree?: number;\n}\n\nexport interface SplatGeometry {\n /** Number of splats parsed from the buffer. */\n vertexCount: number;\n /** Tight AABB across all splat centres (PLY-space). */\n boundMin: [number, number, number];\n boundMax: [number, number, number];\n /** Texture dimensions. width × height ≥ vertexCount, padded to texture row. */\n textureWidth: number;\n textureHeight: number;\n /** Splat centre positions, flat XYZ Float32 (length = 3 × vertexCount). */\n positions: Float32Array;\n /** RGBA32F texture data, one texel per splat. */\n centersRGBA: Float32Array;\n covARGBA: Float32Array;\n covBRGBA: Float32Array;\n colorsRGBA: Float32Array;\n}\n\n/** Pick a (width, height) so that width × height ≥ length and width is a\n * power of two ≤ 4096 (matches the upper bound BJS uses on WebGL2/WebGPU,\n * conservative enough for any device exposed via WebGPU). */\nfunction chooseTextureSize(length: number): { width: number; height: number } {\n const width = 4096;\n const height = Math.max(1, Math.ceil(length / width));\n return { width, height };\n}\n\n/** Decode a splat row buffer into the textures + auxiliary arrays needed by the renderer. */\nexport function buildSplatGeometry(splatBuffer: ArrayBuffer): SplatGeometry {\n const u = new Uint8Array(splatBuffer);\n const f = new Float32Array(splatBuffer);\n const vertexCount = (u.byteLength / ROW_LENGTH) | 0;\n if (vertexCount === 0) {\n throw new Error(\"splat buffer is empty\");\n }\n\n const { width, height } = chooseTextureSize(vertexCount);\n const texelCount = width * height;\n\n const positions = new Float32Array(vertexCount * 3);\n const centersRGBA = new Float32Array(texelCount * 4);\n const covARGBA = new Float32Array(texelCount * 4);\n const covBRGBA = new Float32Array(texelCount * 4);\n const colorsRGBA = new Float32Array(texelCount * 4);\n\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n // Scratch matrices: rotation R, scaling S, M = R * S, then Σ = M · Mᵀ.\n // We only ever need the 6 upper-triangle entries of Σ, packed into covA/covB.\n const M = new Float32Array(9);\n\n for (let i = 0; i < vertexCount; i++) {\n const fi = i * 8; // 8 floats per row before the colour/rot tail\n const ui = i * ROW_LENGTH;\n\n const x = f[fi]!;\n const y = -f[fi + 1]!;\n const z = f[fi + 2]!;\n\n positions[i * 3] = x;\n positions[i * 3 + 1] = y;\n positions[i * 3 + 2] = z;\n if (x < minX) {\n minX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n\n // centresTexture: vec4(xyz, 1).\n centersRGBA[i * 4] = x;\n centersRGBA[i * 4 + 1] = y;\n centersRGBA[i * 4 + 2] = z;\n centersRGBA[i * 4 + 3] = 1;\n\n // colour: 0..255 → 0..1\n colorsRGBA[i * 4] = u[ui + 24]! / 255;\n colorsRGBA[i * 4 + 1] = u[ui + 25]! / 255;\n colorsRGBA[i * 4 + 2] = u[ui + 26]! / 255;\n colorsRGBA[i * 4 + 3] = u[ui + 27]! / 255;\n\n // Quaternion from biased uint8 (BJS layout: w, x, y, z at bytes 28..31).\n // Bias matches BJS exactly (× 127.5 + 127.5). We then normalise the\n // dequantised quaternion — the byte → float round-trip can leave |q|\n // up to ~0.4% per component off-unit, and BJS does the same `q.normalize()`\n // in `_makeSplat`, so this keeps Σ values byte-equal to BJS.\n // No sign flips: BJS's `(qx, qy, qz, -qw)` decode + Babylon's column-major\n // matrix-multiply (which actually computes S · R, not R · S) results in\n // Σ = R_orig · diag((2s)²) · R_orig^T via column-norms. Our path computes\n // Σ via row-norms of M = R · diag(2s) — both converge to the same Σ.\n let qw = -(u[ui + 28]! - 127.5) / 127.5; // flip here to compensate flip on Y position\n let qx = (u[ui + 29]! - 127.5) / 127.5;\n let qy = -(u[ui + 30]! - 127.5) / 127.5; // flip here to compensate flip on Y position\n let qz = (u[ui + 31]! - 127.5) / 127.5;\n const qLen = Math.hypot(qw, qx, qy, qz) || 1;\n const qInv = 1 / qLen;\n qw *= qInv;\n qx *= qInv;\n qy *= qInv;\n qz *= qInv;\n\n // Rotation matrix (column-major, like BJS), pre-multiplied with diag(2 * scale).\n const sx = f[fi + 3]! * 2;\n const sy = f[fi + 4]! * 2;\n const sz = f[fi + 5]! * 2;\n\n const xx = qx * qx,\n yy = qy * qy,\n zz = qz * qz;\n const xy = qx * qy,\n xz = qx * qz,\n yz = qy * qz;\n const wx = qw * qx,\n wy = qw * qy,\n wz = qw * qz;\n\n // R, column-major\n const r00 = 1 - 2 * (yy + zz);\n const r01 = 2 * (xy + wz);\n const r02 = 2 * (xz - wy);\n const r10 = 2 * (xy - wz);\n const r11 = 1 - 2 * (xx + zz);\n const r12 = 2 * (yz + wx);\n const r20 = 2 * (xz + wy);\n const r21 = 2 * (yz - wx);\n const r22 = 1 - 2 * (xx + yy);\n\n // M = R * diag(scale*2). Column j of M = column j of R * scale[j].\n M[0] = r00 * sx;\n M[1] = r01 * sx;\n M[2] = r02 * sx;\n M[3] = r10 * sy;\n M[4] = r11 * sy;\n M[5] = r12 * sy;\n M[6] = r20 * sz;\n M[7] = r21 * sz;\n M[8] = r22 * sz;\n\n // Σ = M · Mᵀ → store the 6 unique entries\n // covA = (Σ00, Σ01, Σ02), covB = (Σ11, Σ12, Σ22).\n const a0 = M[0]! * M[0]! + M[3]! * M[3]! + M[6]! * M[6]!;\n const a1 = M[0]! * M[1]! + M[3]! * M[4]! + M[6]! * M[7]!;\n const a2 = M[0]! * M[2]! + M[3]! * M[5]! + M[6]! * M[8]!;\n const b0 = M[1]! * M[1]! + M[4]! * M[4]! + M[7]! * M[7]!;\n const b1 = M[1]! * M[2]! + M[4]! * M[5]! + M[7]! * M[8]!;\n const b2 = M[2]! * M[2]! + M[5]! * M[5]! + M[8]! * M[8]!;\n\n covARGBA[i * 4] = a0;\n covARGBA[i * 4 + 1] = a1;\n covARGBA[i * 4 + 2] = a2;\n covARGBA[i * 4 + 3] = 1;\n covBRGBA[i * 4] = b0;\n covBRGBA[i * 4 + 1] = b1;\n covBRGBA[i * 4 + 2] = b2;\n covBRGBA[i * 4 + 3] = 1;\n }\n\n return {\n vertexCount,\n boundMin: [minX, minY, minZ],\n boundMax: [maxX, maxY, maxZ],\n textureWidth: width,\n textureHeight: height,\n positions,\n centersRGBA,\n covARGBA,\n covBRGBA,\n colorsRGBA,\n };\n}\n","import type { Mat4 } from \"./types.js\";\n\n/** Create a scaling matrix. */\nexport function mat4Scale(x: number, y: number, z: number): Mat4 {\n const out = new Float32Array(16) as Mat4;\n out[0] = x;\n out[5] = y;\n out[10] = z;\n out[15] = 1;\n return out;\n}\n","/** GaussianSplattingMesh — pure data describing a renderable Gaussian splat cloud.\n *\n * Plain state with TRS + parent + children (`SceneNode`-shaped, no methods),\n * plus splat-specific GPU resources and a worker handle for back-to-front sort.\n * All behaviour lives in standalone functions in this file or in\n * `gaussian-splatting-pipeline.ts`.\n *\n * Renderable + dispose hook registration is performed by `loadSplat()` via\n * `attachGaussianSplattingMesh()` — scene-core stays GS-agnostic so non-GS\n * scenes never pull in this pipeline. */\n\nimport type { SceneNode } from \"../../scene/scene-node.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Mat4 } from \"../../math/types.js\";\nimport { mat4Identity, mat4Compose } from \"../../math/mat4.js\";\nimport { ObservableVec3 } from \"../../math/observable-vec3.js\";\nimport { ObservableQuat } from \"../../math/observable-quat.js\";\nimport { createWorldMatrixState, attachWorldMatrixState } from \"../../scene/world-matrix-state.js\";\nimport { eulerToQuat, createEulerProxy } from \"../../scene/scene-node.js\";\nimport { buildSplatGeometry, type SplatGeometry, type ParsedSplat } from \"../../loader-splat/splat-data.js\";\n\n/** Names of the four WGSL slots a `GsShaderFragment` may inject into the\n * Gaussian-splat fragment shader. Markers in the WGSL source look like\n * `\\/*GS_FRAGMENT_MAIN_END*\\/` — valid comments when no plugin is present. */\nexport type GsFragmentSlot = \"GS_FRAGMENT_DEFINITIONS\" | \"GS_FRAGMENT_MAIN_BEGIN\" | \"GS_FRAGMENT_BEFORE_FRAGCOLOR\" | \"GS_FRAGMENT_MAIN_END\";\n\n/** Data-only descriptor of a GS shader plugin. Lite equivalent of a BJS\n * `MaterialPluginBase`: snippets get spliced into the four GS fragment slots. */\nexport interface GsShaderFragment {\n readonly id: string;\n readonly fragmentSlots?: Partial<Record<GsFragmentSlot, string>>;\n readonly helperFunctions?: string;\n}\n\n/** Per-mesh GPU resources owned by a GaussianSplattingMesh. */\nexport interface GaussianSplattingGpu {\n /** @internal */\n _centersTex: GPUTexture;\n /** @internal */\n _centersView: GPUTextureView;\n /** @internal */\n _covATex: GPUTexture;\n /** @internal */\n _covAView: GPUTextureView;\n /** @internal */\n _covBTex: GPUTexture;\n /** @internal */\n _covBView: GPUTextureView;\n /** @internal */\n _colorsTex: GPUTexture;\n /** @internal */\n _colorsView: GPUTextureView;\n /** @internal */\n _sampler: GPUSampler;\n /** @internal Quad vertex buffer (4 vec2 corners). */\n _quadBuffer: GPUBuffer;\n /** @internal Quad index buffer (uint16 [0,1,2,0,2,3]). */\n _indexBuffer: GPUBuffer;\n /** @internal Per-instance splatIndex (Float32 × vertexCount), back-to-front order. */\n _splatIndexBuffer: GPUBuffer;\n /** @internal CPU-side scratch matching `splatIndexBuffer`. */\n _splatIndexCpu: Float32Array;\n /** Packed view-dependent SH textures (1..5 rgba32uint), `null` when\n * the cloud has no SH data. Layout: 16 bytes per splat per texture. */\n /** @internal */\n _shTextures: GPUTexture[] | null;\n /** @internal */\n _shViews: GPUTextureView[] | null;\n}\n\n/** Public Gaussian-splatting mesh handle. `_kind` is a brand so consumers can\n * narrow on it; the renderable is wired up by `loadSplat()` directly. */\nexport interface GaussianSplattingMesh extends SceneNode {\n /** @internal */\n readonly _kind: \"gs-mesh\";\n /** Number of splats in the cloud. */\n readonly vertexCount: number;\n /** RGBA32F texture dimensions used for centers/covA/covB/colors. */\n readonly textureWidth: number;\n readonly textureHeight: number;\n /** World-space AABB across all splat centres (for camera framing). */\n boundMin: [number, number, number];\n boundMax: [number, number, number];\n /** Spherical-harmonics degree (0 means no view-dependent SH). Set at load\n * time and immutable afterwards — `updateData` rejects a degree change. */\n readonly shDegree: number;\n /** @internal Sort worker. Owned by the mesh; terminated on dispose. */\n _worker: Worker;\n /** @internal Scratch for the worker round-trip. high-32 = depth, low-32 = index. */\n _depthMix: BigInt64Array;\n /** Snapshot of the world matrix posted to the worker on the last sort.\n * Used to decide whether a re-sort is needed this frame. Mirrors BJS\n * `ICameraViewInfo.sortWorldMatrix`. */\n /** @internal */\n _sortWorldMatrix: Float32Array;\n /** @internal Snapshot of the camera-forward vector (`view[2,6,10]`) on the last sort. */\n _sortCameraForward: Float32Array;\n /** @internal Snapshot of the camera world-space position on the last sort. */\n _sortCameraPosition: Float32Array;\n /** @internal True between postMessage and onmessage; throttles re-sort requests. */\n _canPostToWorker: boolean;\n /** Resolves on the first sort completion. The lab scene awaits this\n * before flagging `dataset.ready`. */\n readonly firstSortReady: Promise<void>;\n /** @internal Resolver for {@link firstSortReady}; called once the first sort completes, then cleared to null. */\n _firstSortResolve: (() => void) | null;\n /** @internal GPU resources, populated by `createGaussianSplattingMesh`. */\n _gs: GaussianSplattingGpu;\n /** Raw 32-byte/splat row buffer. Mirrors BJS `splatsData` (with\n * `keepInRam:true`) — exposed for inspection + `updateData` round-trips. */\n readonly splatsData: ArrayBuffer;\n /** Replace the splat data in place. Re-uploads centres / covariance /\n * colour textures, re-posts positions to the sort worker, and updates the\n * AABB. Vertex count must match the original buffer. Mirrors BJS\n * `GaussianSplattingMesh.updateData(buffer, _sh, opts)`. */\n updateData(splatBuffer: ArrayBuffer): void;\n}\n\n/** Create a GaussianSplattingMesh from a parsed splat asset. Uploads textures +\n * initial identity splat-index buffer, spawns the sort worker, and (when the\n * asset includes SH coefficients) packs SH into rgba32uint textures.\n *\n * `parsed.data` is retained on the mesh as `splatsData` so callers can mutate\n * the row data and round-trip it via `mesh.updateData(buffer)` — matches\n * `keepInRam:true` semantics on BJS `GaussianSplattingMesh`. */\nexport function createGaussianSplattingMesh(engine: EngineContext, name: string, geom: SplatGeometry, worker: Worker, parsed: ParsedSplat): GaussianSplattingMesh {\n const device = engine._device;\n const queue = device.queue;\n const { textureWidth, textureHeight, vertexCount } = geom;\n\n // ── Textures (RGBA32F, one texel per splat) ──────────────────────\n const makeRgba32f = (data: Float32Array): { tex: GPUTexture; view: GPUTextureView } => {\n const tex = device.createTexture({\n size: [textureWidth, textureHeight],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n queue.writeTexture({ texture: tex }, data.buffer, { bytesPerRow: textureWidth * 16 }, { width: textureWidth, height: textureHeight });\n return { tex, view: tex.createView() };\n };\n const centers = makeRgba32f(geom.centersRGBA);\n const covA = makeRgba32f(geom.covARGBA);\n const covB = makeRgba32f(geom.covBRGBA);\n const colors = makeRgba32f(geom.colorsRGBA);\n\n const sampler = device.createSampler({\n magFilter: \"nearest\",\n minFilter: \"nearest\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n });\n\n // ── Quad geometry (shared by all instances) ──────────────────────\n const quadBuffer = device.createBuffer({ size: 32, usage: GPUBufferUsage.VERTEX, mappedAtCreation: true });\n new Float32Array(quadBuffer.getMappedRange()).set([-2, -2, 2, -2, 2, 2, -2, 2]);\n quadBuffer.unmap();\n\n const indexBuffer = device.createBuffer({ size: 12, usage: GPUBufferUsage.INDEX, mappedAtCreation: true });\n new Uint16Array(indexBuffer.getMappedRange()).set([0, 1, 2, 0, 2, 3]);\n indexBuffer.unmap();\n\n // ── Instance buffer: identity splatIndex until the first sort lands. ──\n const splatIndexCpu = new Float32Array(vertexCount);\n for (let i = 0; i < vertexCount; i++) {\n splatIndexCpu[i] = i;\n }\n const splatIndexBuffer = device.createBuffer({\n size: splatIndexCpu.byteLength,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n queue.writeBuffer(splatIndexBuffer, 0, splatIndexCpu.buffer, 0, splatIndexCpu.byteLength);\n\n // ── First-sort gate ──────────────────────────────────────────────\n let firstResolve: (() => void) | null = null;\n const firstSortReady = new Promise<void>((res) => {\n firstResolve = res;\n });\n\n // ── Retained source buffer (for splatsData + updateData) ─────────\n let retainedSplatsData = parsed.data;\n\n // ── Compose mesh ─────────────────────────────────────────────────\n // `shDegree` comes from the parser (0 means \"no view-dependent SH\").\n // The SH attacher is dynamic-imported when needed and patches `_gs` in place,\n // keeping SH-specific code out of static splat scenes.\n const mesh = {\n _kind: \"gs-mesh\",\n name,\n vertexCount,\n textureWidth,\n textureHeight,\n boundMin: geom.boundMin.slice() as [number, number, number],\n boundMax: geom.boundMax.slice() as [number, number, number],\n shDegree: parsed.shDegree ?? 0,\n _worker: worker,\n _depthMix: new BigInt64Array(vertexCount),\n _sortWorldMatrix: new Float32Array(16),\n _sortCameraForward: new Float32Array(3),\n _sortCameraPosition: new Float32Array(3),\n _canPostToWorker: true,\n firstSortReady,\n _firstSortResolve: firstResolve,\n _gs: {\n _centersTex: centers.tex,\n _centersView: centers.view,\n _covATex: covA.tex,\n _covAView: covA.view,\n _covBTex: covB.tex,\n _covBView: covB.view,\n _colorsTex: colors.tex,\n _colorsView: colors.view,\n _sampler: sampler,\n _quadBuffer: quadBuffer,\n _indexBuffer: indexBuffer,\n _splatIndexBuffer: splatIndexBuffer,\n _splatIndexCpu: splatIndexCpu,\n _shTextures: null,\n _shViews: null,\n },\n } as unknown as GaussianSplattingMesh;\n\n // splatsData getter — always returns the most-recently-loaded raw row buffer.\n Object.defineProperty(mesh, \"splatsData\", {\n get: () => retainedSplatsData,\n });\n\n // updateData: replace splat data in place. Vertex count must match.\n (mesh as { updateData: (b: ArrayBuffer) => void }).updateData = (newBuffer: ArrayBuffer): void => {\n const newGeom = buildSplatGeometry(newBuffer);\n if (newGeom.vertexCount !== mesh.vertexCount) {\n throw Error(\"GS vertex count mismatch\");\n }\n const gs = mesh._gs;\n const writeTex = (tex: GPUTexture, data: Float32Array): void => {\n queue.writeTexture({ texture: tex }, data.buffer, { bytesPerRow: newGeom.textureWidth * 16 }, { width: newGeom.textureWidth, height: newGeom.textureHeight });\n };\n writeTex(gs._centersTex, newGeom.centersRGBA);\n writeTex(gs._covATex, newGeom.covARGBA);\n writeTex(gs._covBTex, newGeom.covBRGBA);\n writeTex(gs._colorsTex, newGeom.colorsRGBA);\n\n mesh.boundMin = newGeom.boundMin.slice() as [number, number, number];\n mesh.boundMax = newGeom.boundMax.slice() as [number, number, number];\n\n // Re-init the worker with the new positions buffer. The previous\n // positions array was transferred and is gone on this side, so we\n // hand the worker a fresh transferable. If a sort is currently in\n // flight, the message queues behind it and the worker swaps to the\n // new positions when it lands.\n mesh._worker.postMessage({ p: newGeom.positions, n: newGeom.vertexCount }, [newGeom.positions.buffer]);\n // Force a re-sort on the next eligible frame by zeroing the snapshot\n // state — any real camera/world state will differ by more than the\n // gating threshold. (`_canPostToWorker` is left untouched — it's owned\n // by the worker protocol and toggling it here would risk double-posting\n // a `_depthMix` buffer that's still detached on the worker side.)\n mesh._sortWorldMatrix.fill(0);\n mesh._sortCameraForward.fill(0);\n mesh._sortCameraPosition.fill(0);\n\n retainedSplatsData = newBuffer;\n };\n\n initSplatTransform(mesh);\n\n // Ship the positions buffer to the worker once. After this `geom.positions`\n // is detached on this side — that's fine, we never need it again.\n worker.postMessage({ p: geom.positions, n: vertexCount }, [geom.positions.buffer]);\n\n worker.onmessage = (e: MessageEvent) => {\n const data = e.data as { d: BigInt64Array };\n mesh._depthMix = data.d;\n const indices = new Uint32Array(data.d.buffer);\n const cpu = mesh._gs._splatIndexCpu;\n for (let j = 0; j < mesh.vertexCount; j++) {\n cpu[j] = indices[2 * j]!;\n }\n queue.writeBuffer(mesh._gs._splatIndexBuffer, 0, cpu.buffer, 0, cpu.byteLength);\n mesh._canPostToWorker = true;\n if (mesh._firstSortResolve) {\n mesh._firstSortResolve();\n mesh._firstSortResolve = null;\n }\n };\n\n return mesh;\n}\n\n/** Free all GPU + worker resources owned by a GS mesh. */\nexport function disposeGaussianSplattingMesh(mesh: GaussianSplattingMesh): void {\n const gs = mesh._gs;\n [gs._centersTex, gs._covATex, gs._covBTex, gs._colorsTex, gs._quadBuffer, gs._indexBuffer, gs._splatIndexBuffer, ...(gs._shTextures ?? [])].forEach((resource) =>\n resource.destroy()\n );\n mesh._worker.terminate();\n}\n\n// Same TRS + worldMatrix wiring as `initMeshTransform` in mesh/mesh.ts but\n// duplicated here to avoid pulling the Mesh module into the GS code path.\nfunction initSplatTransform(node: GaussianSplattingMesh): void {\n const wm = createWorldMatrixState(() => {\n const p = node.position,\n rq = node.rotationQuaternion,\n s = node.scaling;\n const isIdentity = p.x === 0 && p.y === 0 && p.z === 0 && rq.x === 0 && rq.y === 0 && rq.z === 0 && rq.w === 1 && s.x === 1 && s.y === 1 && s.z === 1;\n return isIdentity ? mat4Identity() : mat4Compose(p.x, p.y, p.z, rq.x, rq.y, rq.z, rq.w, s.x, s.y, s.z);\n });\n const onDirty = (): void => wm.markLocalDirty();\n const [iqx, iqy, iqz, iqw] = eulerToQuat(0, 0, 0);\n const rq = new ObservableQuat(iqx, iqy, iqz, iqw, onDirty);\n (node as unknown as Record<string, unknown>).rotationQuaternion = rq;\n (node as unknown as Record<string, unknown>).rotation = createEulerProxy(rq);\n (node as unknown as Record<string, unknown>).position = new ObservableVec3(0, 0, 0, onDirty);\n (node as unknown as Record<string, unknown>).scaling = new ObservableVec3(1, 1, 1, onDirty);\n (node as unknown as Record<string, unknown>).children = [];\n\n Object.defineProperty(node, \"parent\", {\n get() {\n return wm.parent;\n },\n set(v) {\n wm.parent = v;\n },\n configurable: true,\n enumerable: true,\n });\n Object.defineProperty(node, \"worldMatrix\", {\n get(): Mat4 {\n return wm.getWorldMatrix();\n },\n configurable: true,\n enumerable: false,\n });\n Object.defineProperty(node, \"worldMatrixVersion\", {\n get(): number {\n return wm.getWorldMatrixVersion();\n },\n configurable: true,\n enumerable: false,\n });\n // Tag so children parented to this splat mesh get push invalidation.\n attachWorldMatrixState(node, wm);\n}\n","export default \"// Gaussian Splatting — vertex + fragment WGSL.\\n// Mirrors the math in BJS gaussianSplatting.vertex.fx / .fragment.fx\\n// (static splat path: no SH, no compound transforms).\\nstruct U {\\n world: mat4x4<f32>,\\n view: mat4x4<f32>,\\n projection: mat4x4<f32>,\\n viewport: vec2<f32>,\\n focal: vec2<f32>,\\n dataSize: vec2<f32>,\\n alpha: f32,\\n _pad: f32,\\n};\\n@group(1) @binding(0) var<uniform> u: U;\\n@group(1) @binding(1) var samp: sampler;\\n@group(1) @binding(2) var centersTex: texture_2d<f32>;\\n@group(1) @binding(3) var covATex: texture_2d<f32>;\\n@group(1) @binding(4) var covBTex: texture_2d<f32>;\\n@group(1) @binding(5) var colorsTex: texture_2d<f32>;\\n\\nstruct VOut {\\n @builtin(position) pos: vec4<f32>,\\n @location(0) vColor: vec4<f32>,\\n @location(1) vPos: vec2<f32>,\\n};\\n\\nfn dataUv(idx: f32) -> vec2<f32> {\\n let y = floor(idx / u.dataSize.x);\\n let x = idx - y * u.dataSize.x;\\n return vec2<f32>((x + 0.5) / u.dataSize.x, (y + 0.5) / u.dataSize.y);\\n}\\n\\n@vertex\\nfn vs(@location(0) corner: vec2<f32>, @location(1) splatIndex: f32) -> VOut {\\n var out: VOut;\\n let uv = dataUv(splatIndex);\\n let center = textureSampleLevel(centersTex, samp, uv, 0.0).xyz;\\n let color = textureSampleLevel(colorsTex, samp, uv, 0.0);\\n let covA = textureSampleLevel(covATex, samp, uv, 0.0).xyz;\\n let covB = textureSampleLevel(covBTex, samp, uv, 0.0).xyz;\\n\\n let worldPos = u.world * vec4<f32>(center, 1.0);\\n let modelView = u.view * u.world;\\n let camspace = u.view * worldPos;\\n let pos2d = u.projection * camspace;\\n\\n let bounds = 1.2 * pos2d.w;\\n if (pos2d.z < 0.0\\n || pos2d.x < -bounds || pos2d.x > bounds\\n || pos2d.y < -bounds || pos2d.y > bounds) {\\n out.pos = vec4<f32>(0.0, 0.0, 2.0, 1.0);\\n out.vColor = vec4<f32>(0.0);\\n out.vPos = vec2<f32>(0.0);\\n return out;\\n }\\n\\n let Vrk = mat3x3<f32>(\\n vec3<f32>(covA.x, covA.y, covA.z),\\n vec3<f32>(covA.y, covB.x, covB.y),\\n vec3<f32>(covA.z, covB.y, covB.z));\\n\\n let invZ = 1.0 / camspace.z;\\n let invZ2 = invZ * invZ;\\n // J is written in the SAME transposed-storage form BJS uses in\\n // gaussianSplatting.fx — i.e. the perspective-correction terms\\n // -focal·x/z² and -focal·y/z² sit in math row 2 (columns 0,1), not in\\n // math column 2. This is required because the next two lines compute\\n // `T = transpose(mv3) * J` and `cov2d = transpose(T) * Vrk * T`,\\n // which only collapses to the correct EWA projection\\n // cov2d = (J_std · mv3) · Σ · (J_std · mv3)ᵀ\\n // when J here equals J_stdᵀ. Using J in standard form would compute\\n // the wrong product Jᵀ·mv3·Σ·mv3ᵀ·J, agreeing with BJS only for splats\\n // on the optical axis (x=y=0) and producing visible per-splat\\n // orientation differences off-centre.\\n let J = mat3x3<f32>(\\n vec3<f32>(u.focal.x * invZ, 0.0, -u.focal.x * camspace.x * invZ2),\\n vec3<f32>(0.0, u.focal.y * invZ, -u.focal.y * camspace.y * invZ2),\\n vec3<f32>(0.0, 0.0, 0.0));\\n\\n let mv3 = mat3x3<f32>(modelView[0].xyz, modelView[1].xyz, modelView[2].xyz);\\n let T = transpose(mv3) * J;\\n var cov2d = transpose(T) * Vrk * T;\\n\\n // BJS GaussianSplattingMaterial defaults: KernelSize = 0.3 (low-pass dilation\\n // — keeps sub-pixel splats from disappearing, see gaussianSplatting.fx).\\n // The +epsilon in the eigenvalues mirrors the same shader's numerical safety.\\n let kernelSize: f32 = 0.3;\\n cov2d[0][0] += kernelSize;\\n cov2d[1][1] += kernelSize;\\n\\n let mid = (cov2d[0][0] + cov2d[1][1]) * 0.5;\\n let dxy = (cov2d[0][0] - cov2d[1][1]) * 0.5;\\n let radius = length(vec2<f32>(dxy, cov2d[0][1]));\\n let epsilon: f32 = 0.0001;\\n let lambda1 = mid + radius + epsilon;\\n let lambda2 = mid - radius + epsilon;\\n if (lambda2 < 0.0) {\\n out.pos = vec4<f32>(0.0, 0.0, 2.0, 1.0);\\n out.vColor = vec4<f32>(0.0);\\n out.vPos = vec2<f32>(0.0);\\n return out;\\n }\\n\\n let diag = normalize(vec2<f32>(cov2d[0][1], lambda1 - cov2d[0][0]));\\n let majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diag;\\n let minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2<f32>(diag.y, -diag.x);\\n\\n let vCenter = pos2d.xy;\\n out.pos = vec4<f32>(\\n vCenter + (corner.x * majorAxis + corner.y * minorAxis) * pos2d.w / u.viewport,\\n pos2d.z, pos2d.w);\\n out.vColor = vec4<f32>(color.rgb, color.a * u.alpha);\\n out.vPos = corner;\\n return out;\\n}\\n\\n/*GS_FRAGMENT_DEFINITIONS*/\\n@fragment\\nfn fs(in: VOut) -> @location(0) vec4<f32> {\\n /*GS_FRAGMENT_MAIN_BEGIN*/\\n let A = -dot(in.vPos, in.vPos);\\n var finalColor: vec4<f32>;\\n if (A > -4.0) {\\n let B = exp(A) * in.vColor.a;\\n finalColor = vec4<f32>(in.vColor.rgb, B);\\n } else {\\n finalColor = vec4<f32>(0.0);\\n }\\n /*GS_FRAGMENT_BEFORE_FRAGCOLOR*/\\n /*GS_FRAGMENT_MAIN_END*/\\n return finalColor;\\n}\\n\"","/** Gaussian-Splatting render pipeline + Renderable.\n *\n * WGSL port of the BJS `gaussianSplatting.vertex.fx` / `.fragment.fx`\n * pair, restricted to the static splat path (no SH, no compound parts).\n * Math is unchanged: the EWA / Vrk projection of the 3D anisotropic\n * Gaussian is computed exactly as in BJS, then the per-fragment\n * density `exp(-r²) * α` is multiplied with the splat colour.\n *\n * Per-frame the binding's `update` hook:\n * 1. refreshes the per-mesh UBO (world / view / projection / focal / viewport),\n * 2. checks whether the world matrix, camera-forward (view[2,6,10]) or\n * camera world position has drifted past `SORT_EPS` since the last sort\n * (mirrors BJS `_isSortStateDirty`) and, if so, posts a fresh sort job,\n * 3. lets the GS-mesh `onmessage` handler upload the freshly-sorted\n * splatIndex buffer back to the GPU.\n *\n * The pipeline is cached per `RenderTargetSignature`. */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene-core.js\";\nimport type { Renderable, DrawBinding } from \"../../render/renderable.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\nimport { getViewMatrix, getProjectionMatrix, getCameraPosition } from \"../../camera/camera.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { getRenderTargetSize } from \"../../engine/engine.js\";\nimport { disposeGaussianSplattingMesh, type GaussianSplattingMesh, type GsShaderFragment } from \"./gaussian-splatting-mesh.js\";\nimport WGSL from \"../../../shaders/gaussian-splatting.wgsl?raw\";\n\ninterface PipelineEntry {\n pipeline: GPURenderPipeline;\n meshBindGroupLayout: GPUBindGroupLayout;\n}\n\n// Per-device pipeline cache keyed by RenderTargetSignature string. Tree-shake-friendly\n// lazy init (no top-level `new Map`) — see GUIDANCE §4.\nlet _cache: { device: GPUDevice; modules: Map<string, GPUShaderModule>; entries: Map<string, PipelineEntry> } | null = null;\n\nexport function applyGsFragments(wgsl: string, fragments: readonly GsShaderFragment[]): string {\n const slotCode: Record<string, string> = {};\n for (const frag of fragments) {\n if (frag.helperFunctions) {\n slotCode[\"GS_FRAGMENT_DEFINITIONS\"] = (slotCode[\"GS_FRAGMENT_DEFINITIONS\"] ?? \"\") + frag.helperFunctions + \"\\n\";\n }\n for (const [slot, code] of Object.entries(frag.fragmentSlots ?? {})) {\n slotCode[slot] = (slotCode[slot] ?? \"\") + code + \"\\n\";\n }\n }\n const spliced = wgsl.replace(/\\/\\*(GS_FRAGMENT_\\w+)\\*\\//g, (_, slot: string) => slotCode[slot] ?? \"\");\n\n // Field-name mangler for the GS shader. Mirrors `mangleGaussianSplattingWgsl`\n // in `scripts/bundle-scenes-core.ts` (build-time mangling of the base WGSL).\n //\n // The build-time mangler renames struct fields like `u.projection → u.p` in\n // the bundled `gaussian-splatting.wgsl`. Fragment-plugin code (e.g.\n // `gsLinearDepthFragment`) lives in TS string constants that reference the\n // un-mangled names (`u.projection`), so without normalisation the spliced\n // WGSL has both `u.projection` (from the fragment) and `u.p` (from the base),\n // causing a WebGPU parse error.\n //\n // Running the same mangler at runtime on the final spliced string makes both\n // parts use the mangled names. The substitution is idempotent (single-letter\n // mangled names don't match the `\\bfullName\\b` regexes) and harmless in dev\n // mode (where the base WGSL is un-mangled, so this just normalises everything\n // to the mangled form — WebGPU accepts both).\n //\n // KEEP IN SYNC with `scripts/bundle-scenes-core.ts:mangleGaussianSplattingWgsl`.\n //\n // Inlined here (rather than a top-level constant) so it tree-shakes out when\n // fragments are never used — scenes that don't use depth/picking fragments\n // (e.g. scenes 120-126) pay zero runtime cost for this mangling table.\n const mangles: [string, string][] = [\n [\"world\", \"w\"],\n [\"view\", \"v\"],\n [\"projection\", \"p\"],\n [\"viewport\", \"vp\"],\n [\"focal\", \"f\"],\n [\"dataSize\", \"ds\"],\n [\"alpha\", \"a\"],\n [\"_pad\", \"_p\"],\n [\"vColor\", \"vc\"],\n [\"vPos\", \"vq\"],\n [\"dataUv\", \"du\"],\n [\"splatIndex\", \"si\"],\n [\"corner\", \"co\"],\n [\"center\", \"ce\"],\n [\"color\", \"cl\"],\n [\"covA\", \"ca\"],\n [\"covB\", \"cb\"],\n [\"worldPos\", \"wp\"],\n [\"modelView\", \"mv\"],\n [\"camspace\", \"cs\"],\n [\"pos2d\", \"p2\"],\n [\"bounds\", \"bd\"],\n [\"Vrk\", \"vr\"],\n [\"invZ2\", \"iz2\"],\n [\"invZ\", \"iz\"],\n [\"cov2d\", \"c2\"],\n [\"kernelSize\", \"ks\"],\n [\"radius\", \"ra\"],\n [\"epsilon\", \"ep\"],\n [\"lambda1\", \"l1\"],\n [\"lambda2\", \"l2\"],\n [\"diag\", \"dg\"],\n [\"majorAxis\", \"ma\"],\n [\"minorAxis\", \"mi\"],\n [\"vCenter\", \"vc2\"],\n ];\n\n let mangled = spliced;\n for (const [from, to] of mangles) {\n mangled = mangled.replace(new RegExp(`\\\\b${from}\\\\b`, \"g\"), to);\n }\n return mangled;\n}\n\nfunction getOrCreatePipeline(engine: EngineContext, sig: RenderTargetSignature, fragments?: readonly GsShaderFragment[]): PipelineEntry {\n const device = engine._device;\n if (!_cache || _cache.device !== device) {\n _cache = { device, modules: new Map(), entries: new Map() };\n }\n const fragKey = fragments && fragments.length > 0 ? \"|\" + fragments.map((f) => f.id).join(\",\") : \"\";\n const key = targetSignatureKey(sig) + fragKey;\n let entry = _cache.entries.get(key);\n if (entry) {\n return entry;\n }\n let module = _cache.modules.get(fragKey);\n if (!module) {\n module = device.createShaderModule({ code: fragments && fragments.length > 0 ? applyGsFragments(WGSL, fragments) : WGSL });\n _cache.modules.set(fragKey, module);\n }\n const meshBindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.VERTEX, sampler: { type: \"non-filtering\" } },\n { binding: 2, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"unfilterable-float\" } },\n { binding: 3, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"unfilterable-float\" } },\n { binding: 4, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"unfilterable-float\" } },\n { binding: 5, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"unfilterable-float\" } },\n ],\n });\n const pipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), meshBindGroupLayout] }),\n vertex: {\n module,\n entryPoint: \"vs\",\n buffers: [\n {\n arrayStride: 8,\n stepMode: \"vertex\",\n attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x2\" }],\n },\n {\n arrayStride: 4,\n stepMode: \"instance\",\n attributes: [{ shaderLocation: 1, offset: 0, format: \"float32\" }],\n },\n ],\n },\n fragment: {\n module,\n entryPoint: \"fs\",\n targets: [\n {\n format: sig._colorFormat!,\n blend: {\n // BJS GS material uses ALPHA_COMBINE: src*srcAlpha + dst*(1-srcAlpha)\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n },\n writeMask: GPUColorWrite.ALL,\n },\n ],\n },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n depthStencil: {\n format: sig._depthStencilFormat ?? \"depth24plus-stencil8\",\n depthCompare: sig._depthCompare ?? \"greater-equal\",\n depthWriteEnabled: false,\n },\n multisample: { count: sig._sampleCount },\n });\n entry = { pipeline, meshBindGroupLayout };\n _cache.entries.set(key, entry);\n return entry;\n}\n\n/** Build the Renderable for a GaussianSplattingMesh. Called from the deferred\n * builder installed by `addToScene`. Owns the per-mesh UBO and a per-signature\n * bind-group cache. */\nexport function buildGaussianSplattingRenderable(scene: SceneContext, mesh: GaussianSplattingMesh, fragments?: readonly GsShaderFragment[]): Renderable {\n const engine = scene.engine;\n const device = engine._device;\n\n const UBO_BYTES = 16 * 4 * 3 + 8 * 4; // 3 mat4 + viewport,focal,dataSize,alpha,pad → 224 bytes\n const ubo = device.createBuffer({\n size: UBO_BYTES,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n const cpu = new Float32Array(UBO_BYTES / 4);\n\n // dataSize is constant for the lifetime of this mesh; pre-write it.\n cpu[48 + 4] = mesh.textureWidth;\n cpu[48 + 5] = mesh.textureHeight;\n cpu[48 + 6] = 1; // alpha\n cpu[48 + 7] = 0; // pad\n\n // One per-mesh bind group per pipeline (== per RenderTargetSignature).\n const bindGroups = new Map<GPURenderPipeline, GPUBindGroup>();\n\n const getBindGroup = (entry: PipelineEntry): GPUBindGroup => {\n let bg = bindGroups.get(entry.pipeline);\n if (bg) {\n return bg;\n }\n bg = device.createBindGroup({\n layout: entry.meshBindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: ubo } },\n { binding: 1, resource: mesh._gs._sampler },\n { binding: 2, resource: mesh._gs._centersView },\n { binding: 3, resource: mesh._gs._covAView },\n { binding: 4, resource: mesh._gs._covBView },\n { binding: 5, resource: mesh._gs._colorsView },\n ],\n });\n bindGroups.set(entry.pipeline, bg);\n return bg;\n };\n\n // Per-element epsilon used to decide whether the camera/world state has\n // changed enough to warrant a fresh sort. Mirrors BJS `viewUpdateThreshold`\n // default (`_DefaultViewUpdateThreshold = 1e-4`).\n const SORT_EPS = 1e-4;\n\n const update = (): void => {\n const cam = scene.camera;\n if (!cam) {\n return;\n }\n const size = getRenderTargetSize(engine);\n const aspect = size.width / size.height;\n const view = getViewMatrix(cam) as unknown as Float32Array;\n const proj = getProjectionMatrix(cam, aspect) as unknown as Float32Array;\n const world = mesh.worldMatrix as unknown as Float32Array;\n\n cpu.set(world, 0);\n cpu.set(view, 16);\n cpu.set(proj, 32);\n cpu[48] = size.width;\n cpu[48 + 1] = size.height;\n cpu[48 + 2] = size.width * 0.5 * proj[0]!;\n cpu[48 + 3] = size.height * 0.5 * proj[5]!;\n // dataSize / alpha pre-written at construction.\n device.queue.writeBuffer(ubo, 0, cpu.buffer, 0, UBO_BYTES);\n\n // ── Sort gating ────────────────────────────────────────────\n // Mirrors BJS `_isSortStateDirty` (gaussianSplattingMeshBase.ts:849):\n // re-sort when any element of the world matrix changes, or when the\n // camera's world-space forward (view[2,6,10]) or world-space position\n // moves by more than SORT_EPS. The previous Lite gating used a single\n // `|dot - 1| ≥ 0.01` check on the modelView 3rd row, which missed\n // pure-translation moves and non-identity world matrix changes.\n if (!mesh._canPostToWorker) {\n return;\n }\n\n const camPos = getCameraPosition(cam);\n const cf0 = view[2]!,\n cf1 = view[6]!,\n cf2 = view[10]!;\n\n let dirty = false;\n const lastW = mesh._sortWorldMatrix;\n for (let i = 0; i < 16; i++) {\n if (Math.abs(lastW[i]! - world[i]!) > SORT_EPS) {\n dirty = true;\n break;\n }\n }\n if (!dirty) {\n const lastCf = mesh._sortCameraForward;\n if (Math.abs(lastCf[0]! - cf0) > SORT_EPS || Math.abs(lastCf[1]! - cf1) > SORT_EPS || Math.abs(lastCf[2]! - cf2) > SORT_EPS) {\n dirty = true;\n }\n }\n if (!dirty) {\n const lastCp = mesh._sortCameraPosition;\n if (Math.abs(lastCp[0]! - camPos.x) > SORT_EPS || Math.abs(lastCp[1]! - camPos.y) > SORT_EPS || Math.abs(lastCp[2]! - camPos.z) > SORT_EPS) {\n dirty = true;\n }\n }\n if (!dirty) {\n return;\n }\n\n mesh._sortWorldMatrix.set(world);\n mesh._sortCameraForward[0] = cf0;\n mesh._sortCameraForward[1] = cf1;\n mesh._sortCameraForward[2] = cf2;\n mesh._sortCameraPosition[0] = camPos.x;\n mesh._sortCameraPosition[1] = camPos.y;\n mesh._sortCameraPosition[2] = camPos.z;\n mesh._canPostToWorker = false;\n mesh._worker.postMessage(\n {\n m: new Float32Array(world),\n f: new Float32Array([cf0, cf1, cf2]),\n c: new Float32Array([camPos.x, camPos.y, camPos.z]),\n d: mesh._depthMix,\n },\n [mesh._depthMix.buffer]\n );\n };\n\n const r: Renderable = {\n order: 200,\n isTransparent: true,\n bind(eng: EngineContext, sig: RenderTargetSignature): DrawBinding {\n const entry = getOrCreatePipeline(eng, sig, fragments);\n const bindGroup = getBindGroup(entry);\n return {\n renderable: r,\n pipeline: entry.pipeline,\n update,\n draw(pass) {\n pass.setBindGroup(1, bindGroup);\n pass.setVertexBuffer(0, mesh._gs._quadBuffer);\n pass.setVertexBuffer(1, mesh._gs._splatIndexBuffer);\n pass.setIndexBuffer(mesh._gs._indexBuffer, \"uint16\");\n pass.drawIndexed(6, mesh.vertexCount);\n return 1;\n },\n };\n },\n };\n return r;\n}\n\n/** Wire a `GaussianSplattingMesh` into a scene: pushes its renderable +\n * registers a disposer that frees per-mesh GPU buffers and the worker.\n * Called from the deferred builder installed by `addToScene`. */\nexport function attachGaussianSplattingMesh(scene: SceneContext, mesh: GaussianSplattingMesh, fragments?: readonly GsShaderFragment[]): void {\n const ctx = scene as unknown as { _renderables: Renderable[]; _disposables: (() => void)[]; _gsMeshes: GaussianSplattingMesh[] };\n ctx._renderables.push(buildGaussianSplattingRenderable(scene, mesh, fragments));\n ctx._gsMeshes.push(mesh);\n ctx._disposables.push(() => {\n const i = ctx._gsMeshes.indexOf(mesh);\n if (i >= 0) {\n ctx._gsMeshes.splice(i, 1);\n }\n disposeGaussianSplattingMesh(mesh);\n });\n}\n","/** Public Gaussian-Splatting loader.\n *\n * `loadSplat(scene, url)` fetches a `.ply` (or pre-converted `.splat`) asset,\n * parses it on the main thread, uploads its textures + thin-instance buffer\n * to the GPU, spawns the sort worker, registers the GS renderable on the\n * scene, and returns the resulting `GaussianSplattingMesh`.\n *\n * Bundle-size discipline:\n * • The compressed-PLY parser (`splat-ply-compressed.ts`) is dynamic-\n * imported only when `isPlyCompressedOrSH(data)` is true so plain `.ply`\n * scenes (e.g. scene 120) skip both the parser code *and* the SH textures.\n * • The SH-aware render pipeline (`gaussian-splatting-pipeline-sh.ts`) is\n * dynamic-imported only when the parsed asset carries SH coefficients.\n *\n * `mesh.firstSortReady` resolves once the worker has produced its first\n * depth-sorted splat-index buffer — wait on that promise before flagging the\n * canvas as ready in your scene script. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { isPly, isPlyCompressedOrSH, convertPlyToSplat } from \"./splat-ply-parser.js\";\nimport { buildSplatGeometry, type ParsedSplat } from \"./splat-data.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport { createGaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport { attachGaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-pipeline.js\";\nimport type { GsShaderFragment } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport SplatSortWorker from \"./splat-sort-worker.ts?worker&inline\";\n\n/** Build the mesh + renderable from a parsed splat asset. Exported so SOG/SPZ\n * loaders can share the same plumbing (worker, pipeline attach, SH dispatch). */\nexport async function attachParsedSplat(scene: SceneContext, name: string, parsed: ParsedSplat, fragments?: readonly GsShaderFragment[]): Promise<GaussianSplattingMesh> {\n const geom = buildSplatGeometry(parsed.data);\n const worker = new SplatSortWorker({ name: \"babylon-lite-splat-sort\" });\n const eng = scene.engine as EngineContext;\n const mesh = createGaussianSplattingMesh(eng, name, geom, worker, parsed);\n\n if (parsed.sh && parsed.shDegree && parsed.shDegree > 0) {\n const { attachGaussianSplattingMeshSH } = await import(\"../mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.js\");\n attachGaussianSplattingMeshSH(scene, mesh, parsed.sh, fragments);\n } else {\n attachGaussianSplattingMesh(scene, mesh, fragments);\n }\n return mesh;\n}\n\n/** Fetch + parse a Gaussian-splat asset and attach it to `scene`. */\nexport async function loadSplat(scene: SceneContext, url: string, fragments?: readonly GsShaderFragment[]): Promise<GaussianSplattingMesh> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`loadSplat: HTTP ${response.status} for ${url}`);\n }\n const data = await response.arrayBuffer();\n\n let parsed: ParsedSplat;\n if (isPly(data)) {\n if (isPlyCompressedOrSH(data)) {\n const { convertCompressedPlyToParsedSplat } = await import(\"./splat-ply-compressed.js\");\n parsed = convertCompressedPlyToParsedSplat(data);\n } else {\n parsed = convertPlyToSplat(data);\n }\n if (parsed.data.byteLength === 0) {\n throw new Error(`loadSplat: failed to parse PLY at ${url} (unsupported property layout)`);\n }\n } else {\n // Allow pre-converted .splat files (same row layout) as a fast path.\n parsed = { data };\n }\n\n const name = url.substring(url.lastIndexOf(\"/\") + 1) || \"splat\";\n return await attachParsedSplat(scene, name, parsed, fragments);\n}\n","/** Minimal ZIP central-directory parser.\n *\n * Designed for the small ZIP archive shape produced by the BJS SOG export\n * (`meta.json` + a handful of `.webp` files). Only supports:\n * • Method 0 (stored — raw slice)\n * • Method 8 (deflate — decompressed via `DecompressionStream(\"deflate-raw\")`)\n * and rejects anything else (encrypted entries, ZIP64, multi-disk, …) with a\n * descriptive error so callers can surface a meaningful message instead of\n * silently producing wrong data.\n *\n * Reads sizes / offsets from the central directory record (not the local\n * file header) so it tolerates entries written with bit-3 of the general\n * purpose flag set (data-descriptor mode), which BJS uses on some platforms. */\n\nconst SIG_EOCD = 0x06054b50;\nconst SIG_CDIR = 0x02014b50;\nconst SIG_LFH = 0x04034b50;\n\nconst utf8 = new TextDecoder(\"utf-8\");\n\nexport interface ZipEntry {\n /** Filename as stored in the archive. */\n name: string;\n /** Decompressed bytes. */\n bytes: Uint8Array;\n}\n\n/** Locate the End-Of-Central-Directory record by scanning backwards from the\n * end of the buffer. The EOCD lives within the last 22 + 64 KB of the file.\n * Returns the byte offset of the EOCD signature, or -1 if not found. */\nfunction findEocd(view: DataView): number {\n const maxBack = Math.min(view.byteLength, 22 + 65535);\n const start = view.byteLength - maxBack;\n for (let i = view.byteLength - 22; i >= start; i--) {\n if (view.getUint32(i, true) === SIG_EOCD) {\n return i;\n }\n }\n return -1;\n}\n\n/** Parse the archive and return all decoded entries. */\nexport async function unzipBuffer(buffer: ArrayBuffer): Promise<ZipEntry[]> {\n const view = new DataView(buffer);\n const eocd = findEocd(view);\n if (eocd < 0) {\n throw new Error(\"zip: EOCD record not found\");\n }\n const totalEntries = view.getUint16(eocd + 10, true);\n const cdSize = view.getUint32(eocd + 12, true);\n const cdOffset = view.getUint32(eocd + 16, true);\n if (cdSize === 0xffffffff || cdOffset === 0xffffffff) {\n throw new Error(\"zip: ZIP64 archives are not supported\");\n }\n\n const entries: ZipEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < totalEntries; i++) {\n if (view.getUint32(p, true) !== SIG_CDIR) {\n throw new Error(`zip: bad central directory signature at offset ${p}`);\n }\n const gpFlag = view.getUint16(p + 8, true);\n const method = view.getUint16(p + 10, true);\n const compressedSize = view.getUint32(p + 20, true);\n const uncompressedSize = view.getUint32(p + 24, true);\n const nameLen = view.getUint16(p + 28, true);\n const extraLen = view.getUint16(p + 30, true);\n const commentLen = view.getUint16(p + 32, true);\n const localOffset = view.getUint32(p + 42, true);\n if (gpFlag & 0x0001) {\n throw new Error(`zip: encrypted entries are not supported`);\n }\n if (compressedSize === 0xffffffff || uncompressedSize === 0xffffffff || localOffset === 0xffffffff) {\n throw new Error(\"zip: ZIP64 archives are not supported\");\n }\n const name = utf8.decode(new Uint8Array(buffer, p + 46, nameLen));\n p += 46 + nameLen + extraLen + commentLen;\n\n // Re-read filename/extra lengths from the local file header since the\n // central-directory extra-field length doesn't have to match.\n if (view.getUint32(localOffset, true) !== SIG_LFH) {\n throw new Error(`zip: bad local file header signature at offset ${localOffset}`);\n }\n const lfhNameLen = view.getUint16(localOffset + 26, true);\n const lfhExtraLen = view.getUint16(localOffset + 28, true);\n const dataStart = localOffset + 30 + lfhNameLen + lfhExtraLen;\n\n const compressed = new Uint8Array(buffer, dataStart, compressedSize);\n\n let bytes: Uint8Array;\n if (method === 0) {\n bytes = new Uint8Array(compressed); // copy out so consumers can transfer.\n } else if (method === 8) {\n const stream = new Response(new Blob([compressed]).stream().pipeThrough(new DecompressionStream(\"deflate-raw\")));\n const ab = await stream.arrayBuffer();\n bytes = new Uint8Array(ab);\n } else {\n throw new Error(`zip: unsupported compression method ${method} for entry '${name}'`);\n }\n\n if (bytes.byteLength !== uncompressedSize) {\n throw new Error(`zip: entry '${name}' decompressed size mismatch (got ${bytes.byteLength}, expected ${uncompressedSize})`);\n }\n\n entries.push({ name, bytes });\n }\n return entries;\n}\n","/** Public Gaussian-Splatting SOG loader.\n *\n * SOG (\"SuperSplat Optimized Gaussians\") is the ZIP container produced by the\n * PlayCanvas / Babylon SOG exporter:\n * meta.json + means_l.webp + means_u.webp + scales.webp + quats.webp +\n * sh0.webp + (optional) sh_centroids.webp + sh_labels.webp\n *\n * This loader fetches a `.sog` URL, unzips it, decodes the WebPs to\n * RGBA pixels in main-thread canvases, and rebuilds the 32-byte/splat\n * row buffer + flat SH bytes — mirroring BJS `ParseSogMeta` / `ParseSogDatas`\n * byte-for-byte so parity with the reference is exact.\n *\n * All SOG-specific code lives here so non-SOG scenes don't pay the bundle\n * cost (the zip-parser, the WebP decode path, and the per-component\n * dequantisation tables). */\n\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { ParsedSplat } from \"./splat-data.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport { attachParsedSplat } from \"./load-splat.js\";\nimport { unzipBuffer } from \"./zip-parser.js\";\n\nconst SH_C0 = 0.28209479177387814;\n\n/** Subset of the BJS SOG metadata we need to consume. */\ninterface SOGDataFile {\n /** [splatCount, components] (e.g. [N, 3] or [N, 4]). */\n shape: number[];\n /** Per-component min/max for linear dequant (v1) — or single number for SH (v1). */\n mins?: number | number[];\n maxs?: number | number[];\n /** Codebook table for v2 (quantised data — each byte indexes this LUT). */\n codebook?: number[];\n /** WebP filenames inside the archive. */\n files: string[];\n /** SH band count when present. */\n bands?: number;\n}\n\ninterface SOGRootData {\n /** 1 (linear) or 2 (codebook). */\n version?: number;\n means: SOGDataFile;\n scales: SOGDataFile;\n quats: SOGDataFile;\n sh0: SOGDataFile;\n shN?: SOGDataFile;\n /** Number of splats — optional, can be inferred from means.shape[0]. */\n count?: number;\n}\n\ninterface WebPImage {\n bits: Uint8Array;\n width: number;\n height: number;\n}\n\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * t;\nconst clamp255 = (v: number): number => (v < 0 ? 0 : v > 255 ? 255 : v);\n\n/** Decode a WebP blob to RGBA pixels through an offscreen 2D canvas. The\n * underlying decoder is the browser's built-in (no WASM, no copy needed in\n * headless Chrome — `createImageBitmap` is GPU-accelerated). */\nasync function decodeWebP(bytes: Uint8Array): Promise<WebPImage> {\n const blob = new Blob([bytes as BlobPart], { type: \"image/webp\" });\n const bitmap = await createImageBitmap(blob);\n const width = bitmap.width;\n const height = bitmap.height;\n if (width === 0 || height === 0) {\n throw new Error(`loadSOG: decoded WebP has zero dimensions (input size ${bytes.byteLength})`);\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n throw new Error(\"loadSOG: failed to acquire 2D context for WebP decode\");\n }\n ctx.drawImage(bitmap, 0, 0);\n const imageData = ctx.getImageData(0, 0, width, height);\n bitmap.close?.();\n return { bits: new Uint8Array(imageData.data.buffer), width: imageData.width, height: imageData.height };\n}\n\n/** Build a 32-byte/splat row buffer + optional flat SH bytes from decoded\n * WebPs and SOG metadata. Mirrors BJS `ParseSogDatas`. */\nfunction parseSogDatas(data: SOGRootData, images: WebPImage[]): ParsedSplat {\n const splatCount = data.count ?? data.means.shape[0]!;\n const ROW = 32;\n const buffer = new ArrayBuffer(ROW * splatCount);\n const position = new Float32Array(buffer);\n const scale = new Float32Array(buffer);\n const rgba = new Uint8ClampedArray(buffer);\n const rot = new Uint8ClampedArray(buffer);\n\n // Undo the symmetric log transform used at encode time:\n const unlog = (n: number): number => Math.sign(n) * (Math.exp(Math.abs(n)) - 1);\n\n const meansLow = images[0]!.bits;\n const meansHigh = images[1]!.bits;\n if (!Array.isArray(data.means.mins) || !Array.isArray(data.means.maxs)) {\n throw new Error(\"loadSOG: means.mins/means.maxs must be arrays\");\n }\n\n // ── Positions (16-bit value reconstructed from low + high bytes) ───\n for (let i = 0; i < splatCount; i++) {\n const idx = i * 4;\n for (let j = 0; j < 3; j++) {\n const mn = data.means.mins[j]!;\n const mx = data.means.maxs[j]!;\n const q = (meansHigh[idx + j]! << 8) | meansLow[idx + j]!;\n position[i * 8 + j] = unlog(lerp(mn, mx, q / 65535));\n }\n }\n\n // ── Scales (codebook v2 / linear v1 in log-space, then expf) ───────\n const scales = images[2]!.bits;\n if (data.version === 2) {\n const cb = data.scales.codebook;\n if (!cb) {\n throw new Error(\"loadSOG: SOG v2 missing scales codebook\");\n }\n for (let i = 0; i < splatCount; i++) {\n const idx = i * 4;\n for (let j = 0; j < 3; j++) {\n scale[i * 8 + 3 + j] = Math.exp(cb[scales[idx + j]!]!);\n }\n }\n } else {\n if (!Array.isArray(data.scales.mins) || !Array.isArray(data.scales.maxs)) {\n throw new Error(\"loadSOG: scales.mins/maxs must be arrays for SOG v1\");\n }\n for (let i = 0; i < splatCount; i++) {\n const idx = i * 4;\n for (let j = 0; j < 3; j++) {\n scale[i * 8 + 3 + j] = Math.exp(lerp(data.scales.mins[j]!, data.scales.maxs[j]!, scales[idx + j]! / 255));\n }\n }\n }\n\n // ── Colours / SH0 (RGB through SH_C0 + sigmoid alpha) ──────────────\n const colors = images[4]!.bits;\n if (data.version === 2) {\n const cb = data.sh0.codebook;\n if (!cb) {\n throw new Error(\"loadSOG: SOG v2 missing sh0 codebook\");\n }\n for (let i = 0; i < splatCount; i++) {\n const idx = i * 4;\n for (let j = 0; j < 3; j++) {\n const c = 0.5 + cb[colors[idx + j]!]! * SH_C0;\n rgba[i * 32 + 24 + j] = clamp255(Math.round(255 * c));\n }\n rgba[i * 32 + 24 + 3] = colors[idx + 3]!;\n }\n } else {\n if (!Array.isArray(data.sh0.mins) || !Array.isArray(data.sh0.maxs)) {\n throw new Error(\"loadSOG: sh0.mins/maxs must be arrays for SOG v1\");\n }\n for (let i = 0; i < splatCount; i++) {\n const idx = i * 4;\n for (let j = 0; j < 4; j++) {\n const c = lerp(data.sh0.mins[j]!, data.sh0.maxs[j]!, colors[idx + j]! / 255);\n const csh = j < 3 ? 0.5 + c * SH_C0 : 1.0 / (1.0 + Math.exp(-c));\n rgba[i * 32 + 24 + j] = clamp255(Math.round(255 * csh));\n }\n }\n }\n\n // ── Rotations: dequant the 3 stored components, reconstruct the 4th ─\n const toComp = (c: number): number => ((c / 255 - 0.5) * 2.0) / Math.SQRT2;\n const quatBits = images[3]!.bits;\n for (let i = 0; i < splatCount; i++) {\n const a = toComp(quatBits[i * 4 + 0]!);\n const b = toComp(quatBits[i * 4 + 1]!);\n const c = toComp(quatBits[i * 4 + 2]!);\n const mode = quatBits[i * 4 + 3]! - 252;\n const t = a * a + b * b + c * c;\n const d = Math.sqrt(Math.max(0, 1 - t));\n let q0 = 0,\n q1 = 0,\n q2 = 0,\n q3 = 0;\n switch (mode) {\n case 0:\n q0 = d;\n q1 = a;\n q2 = b;\n q3 = c;\n break;\n case 1:\n q0 = a;\n q1 = d;\n q2 = b;\n q3 = c;\n break;\n case 2:\n q0 = a;\n q1 = b;\n q2 = d;\n q3 = c;\n break;\n case 3:\n q0 = a;\n q1 = b;\n q2 = c;\n q3 = d;\n break;\n default:\n throw new Error(`loadSOG: invalid quaternion mode ${mode}`);\n }\n rot[i * 32 + 28 + 0] = q0 * 127.5 + 127.5;\n rot[i * 32 + 28 + 1] = q1 * 127.5 + 127.5;\n rot[i * 32 + 28 + 2] = q2 * 127.5 + 127.5;\n rot[i * 32 + 28 + 3] = q3 * 127.5 + 127.5;\n }\n\n // ── SH (optional) ──────────────────────────────────────────────────\n if (data.shN) {\n const coeffs = data.shN.bands != null ? (data.shN.bands + 1) ** 2 - 1 : data.shN.shape[1]! / 3;\n const shDegree = data.shN.bands ?? Math.round(Math.sqrt(coeffs + 1) - 1);\n const shComponentCount = coeffs * 3;\n const centroids = images[5]!.bits;\n const labels = images[6]!.bits;\n const centroidsWidth = images[5]!.width;\n const shFlat = new Uint8Array(splatCount * shComponentCount);\n\n if (data.version === 2) {\n const cb = data.shN.codebook;\n if (!cb) {\n throw new Error(\"loadSOG: SOG v2 missing shN codebook\");\n }\n for (let i = 0; i < splatCount; i++) {\n const n = labels[i * 4]! + (labels[i * 4 + 1]! << 8);\n const u = (n % 64) * coeffs;\n const v = Math.floor(n / 64);\n const splatBase = i * shComponentCount;\n for (let k = 0; k < coeffs; k++) {\n for (let j = 0; j < 3; j++) {\n const shIdx = k * 3 + j;\n const val = cb[centroids[(u + k) * 4 + j + v * centroidsWidth * 4]!]! * 127.5 + 127.5;\n shFlat[splatBase + shIdx] = clamp255(val);\n }\n }\n }\n } else {\n const shMin = data.shN.mins as number;\n const shMax = data.shN.maxs as number;\n for (let i = 0; i < splatCount; i++) {\n const n = labels[i * 4]! + (labels[i * 4 + 1]! << 8);\n const u = (n % 64) * coeffs;\n const v = Math.floor(n / 64);\n const splatBase = i * shComponentCount;\n for (let j = 0; j < 3; j++) {\n for (let k = 0; k < coeffs / 3; k++) {\n const shIdx = k * 3 + j;\n const raw = centroids[(u + k) * 4 + j + v * centroidsWidth * 4]!;\n const val = lerp(shMin, shMax, raw / 255) * 127.5 + 127.5;\n shFlat[splatBase + shIdx] = clamp255(val);\n }\n }\n }\n }\n\n return { data: buffer, sh: shFlat, shDegree };\n }\n\n return { data: buffer };\n}\n\n/** Fetch + parse a `.sog` archive and attach the resulting splat cloud to `scene`.\n *\n * The returned mesh has `rotation.x = Math.PI` set on the scene node, matching\n * the BJS reference convention. SOG / PlayCanvas / SuperSplat assets are\n * authored \"Y-down\", and BJS compensates with `mesh.rotation.x = Math.PI`\n * at scene-graph time. */\nexport async function loadSOG(scene: SceneContext, url: string): Promise<GaussianSplattingMesh> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`loadSOG: HTTP ${response.status} for ${url}`);\n }\n const buffer = await response.arrayBuffer();\n const entries = await unzipBuffer(buffer);\n const filesByName = new Map<string, Uint8Array>();\n for (const e of entries) {\n filesByName.set(e.name, e.bytes);\n }\n const metaBytes = filesByName.get(\"meta.json\");\n if (!metaBytes) {\n throw new Error(\"loadSOG: meta.json not found in archive\");\n }\n const meta = JSON.parse(new TextDecoder().decode(metaBytes)) as SOGRootData;\n\n // Same load order as BJS: means → scales → quats → sh0 → (shN: centroids → labels).\n const filenames = [...meta.means.files, ...meta.scales.files, ...meta.quats.files, ...meta.sh0.files];\n if (meta.shN) {\n filenames.push(...meta.shN.files);\n }\n const images = await Promise.all(\n filenames.map(async (name) => {\n const bytes = filesByName.get(name);\n if (!bytes) {\n throw new Error(`loadSOG: missing image '${name}' inside archive`);\n }\n return await decodeWebP(bytes);\n })\n );\n\n const parsed = parseSogDatas(meta, images);\n const friendly = url.substring(url.lastIndexOf(\"/\") + 1) || \"sog\";\n const mesh = await attachParsedSplat(scene, friendly, parsed);\n mesh.rotation.x = Math.PI;\n return mesh;\n}\n","/** Public Gaussian-Splatting SPZ loader.\n *\n * SPZ (Niantic Spatial / Aardvark \"Splat Z\") is a compact binary container\n * for trained Gaussian-Splatting scenes — typically gzip-compressed and\n * ~10x smaller than an equivalent `.ply`. We parse versions 2 and 3 inline\n * (no WASM module), mirroring BJS `ParseSpz` byte-for-byte so parity with\n * the reference renderer is exact.\n *\n * Header (16 bytes):\n * [0..3] magic 'NGSP'\n * [4..7] version (u32 le, supported: 2 or 3)\n * [8..11] splat count (u32 le)\n * [12] SH degree\n * [13] fractional bits (signed 24-bit position scale = `1/(1<<frac)`)\n * [14] flags (bit 0 = trained with antialiasing)\n * [15] reserved (must be 0)\n *\n * Body laid out as parallel arrays — positions then colors+alpha then\n * scales then rotations then (optional) SH bytes. SH bytes are already\n * BJS-quantised (`v * 127.5 + 127.5` clamped) so we copy them directly into\n * our flat per-splat layout.\n *\n * All SPZ-specific code lives here so non-SPZ scenes don't pay the bundle\n * cost. */\n\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { ParsedSplat } from \"./splat-data.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport { attachParsedSplat } from \"./load-splat.js\";\n\nconst SH_C0 = 0.28209479177387814;\nconst MAGIC_NGSP = 0x5053474e; // 'NGSP' little-endian\n\n/** Decompress a gzip-wrapped buffer via the browser's DecompressionStream. */\nasync function decompressGzip(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Response(new Blob([bytes as BlobPart]).stream().pipeThrough(new DecompressionStream(\"gzip\")));\n return new Uint8Array(await stream.arrayBuffer());\n}\n\n/** Sign-extend the 3 bytes at `offset` into an i32 and scale by `positionScale`. */\nfunction read24bComponent(u8: Uint8Array, offset: number, positionScale: number, int32View: Int32Array, uint8View: Uint8Array): number {\n uint8View[0] = u8[offset + 0]!;\n uint8View[1] = u8[offset + 1]!;\n uint8View[2] = u8[offset + 2]!;\n uint8View[3] = (u8[offset + 2]! & 0x80) !== 0 ? 0xff : 0x00;\n return int32View[0]! * positionScale;\n}\n\nconst clamp255 = (v: number): number => (v < 0 ? 0 : v > 255 ? 255 : v);\n\n/** Parse a decompressed SPZ buffer into the engine's standard ParsedSplat. */\nfunction parseSpz(data: ArrayBuffer): ParsedSplat {\n const ubuf = new Uint8Array(data);\n if (ubuf.byteLength < 16) {\n throw new Error(\"loadSPZ: file too short to contain header\");\n }\n const ubuf32 = new Uint32Array(data.slice(0, 12));\n const splatCount = ubuf32[2]!;\n const shDegree = ubuf[12]!;\n const fractionalBits = ubuf[13]!;\n /* const flags = ubuf[14]; */\n const reserved = ubuf[15]!;\n const version = ubuf32[1]!;\n if (reserved !== 0 || ubuf32[0] !== MAGIC_NGSP || version < 2 || version > 3) {\n throw new Error(`loadSPZ: unsupported SPZ stream (magic=0x${ubuf32[0]!.toString(16)} version=${version})`);\n }\n\n const ROW = 32;\n const buffer = new ArrayBuffer(ROW * splatCount);\n const position = new Float32Array(buffer);\n const scale = new Float32Array(buffer);\n const rgba = new Uint8ClampedArray(buffer);\n const rot = new Uint8ClampedArray(buffer);\n\n const positionScale = 1.0 / (1 << fractionalBits);\n const int32View = new Int32Array(1);\n const uint8View = new Uint8Array(int32View.buffer);\n\n let byteOffset = 16;\n\n // ── Positions ──────────────────────────────────────────────────────\n for (let i = 0; i < splatCount; i++) {\n position[i * 8 + 0] = read24bComponent(ubuf, byteOffset + 0, positionScale, int32View, uint8View);\n position[i * 8 + 1] = read24bComponent(ubuf, byteOffset + 3, positionScale, int32View, uint8View);\n position[i * 8 + 2] = read24bComponent(ubuf, byteOffset + 6, positionScale, int32View, uint8View);\n byteOffset += 9;\n }\n\n // ── Colours + Alpha (alpha is laid out before RGB in this block) ───\n // alpha[i] at byteOffset + i\n // rgb[i][c] at byteOffset + splatCount + i*3 + c\n for (let i = 0; i < splatCount; i++) {\n for (let c = 0; c < 3; c++) {\n const byteValue = ubuf[byteOffset + splatCount + i * 3 + c]!;\n // SPZ stores DC SH as (v - 127.5) / (0.15 * 255) — the 0.15 lets\n // higher-order bands push out-of-range DC values back into [0,1].\n const value = (byteValue - 127.5) / (0.15 * 255);\n rgba[i * 32 + 24 + c] = clamp255((0.5 + SH_C0 * value) * 255);\n }\n rgba[i * 32 + 24 + 3] = ubuf[byteOffset + i]!;\n }\n byteOffset += splatCount * 4;\n\n // ── Scales (log space, single byte each) ───────────────────────────\n for (let i = 0; i < splatCount; i++) {\n scale[i * 8 + 3 + 0] = Math.exp(ubuf[byteOffset + 0]! / 16.0 - 10.0);\n scale[i * 8 + 3 + 1] = Math.exp(ubuf[byteOffset + 1]! / 16.0 - 10.0);\n scale[i * 8 + 3 + 2] = Math.exp(ubuf[byteOffset + 2]! / 16.0 - 10.0);\n byteOffset += 3;\n }\n\n // ── Rotations (v2 = 3×i8 xyz, v3 = 32-bit smallest-three encoding) ─\n if (version >= 3) {\n const sqrt12 = Math.SQRT1_2;\n for (let i = 0; i < splatCount; i++) {\n const comp = ubuf[byteOffset + 0]! + (ubuf[byteOffset + 1]! << 8) + (ubuf[byteOffset + 2]! << 16) + (ubuf[byteOffset + 3]! << 24);\n const cmask = (1 << 9) - 1;\n const rotation: [number, number, number, number] = [0, 0, 0, 0];\n const iLargest = comp >>> 30;\n let remaining = comp;\n let sumSquares = 0;\n for (let j = 3; j >= 0; --j) {\n if (j !== iLargest) {\n const mag = remaining & cmask;\n const negbit = (remaining >>> 9) & 0x1;\n remaining = remaining >>> 10;\n let v = sqrt12 * (mag / cmask);\n if (negbit === 1) {\n v = -v;\n }\n rotation[j] = v;\n sumSquares += v * v;\n }\n }\n rotation[iLargest] = Math.sqrt(Math.max(1 - sumSquares, 0));\n // SPZ rotation order is xyzw; pack into our row layout's wxyz.\n const shuffle: readonly [number, number, number, number] = [3, 0, 1, 2];\n for (let j = 0; j < 4; j++) {\n rot[i * 32 + 28 + j] = Math.round(127.5 + rotation[shuffle[j]!]! * 127.5);\n }\n byteOffset += 4;\n }\n } else {\n // Version 2: 3×u8 (x,y,z), w reconstructed from unit-length constraint.\n for (let i = 0; i < splatCount; i++) {\n const x = ubuf[byteOffset + 0]!;\n const y = ubuf[byteOffset + 1]!;\n const z = ubuf[byteOffset + 2]!;\n const nx = x / 127.5 - 1;\n const ny = y / 127.5 - 1;\n const nz = z / 127.5 - 1;\n rot[i * 32 + 28 + 1] = x;\n rot[i * 32 + 28 + 2] = y;\n rot[i * 32 + 28 + 3] = z;\n const v = 1 - (nx * nx + ny * ny + nz * nz);\n rot[i * 32 + 28 + 0] = 127.5 + Math.sqrt(v < 0 ? 0 : v) * 127.5;\n byteOffset += 3;\n }\n }\n\n // ── SH (raw BJS-quantised bytes) ───────────────────────────────────\n if (shDegree) {\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\n const shComponentCount = shVectorCount * 3;\n const shFlat = new Uint8Array(splatCount * shComponentCount);\n for (let i = 0; i < splatCount; i++) {\n for (let k = 0; k < shComponentCount; k++) {\n shFlat[i * shComponentCount + k] = ubuf[byteOffset++]!;\n }\n }\n return { data: buffer, sh: shFlat, shDegree };\n }\n\n return { data: buffer };\n}\n\n/** Fetch + parse a `.spz` asset and attach the splat cloud to `scene`.\n *\n * The returned mesh has `rotation.x = Math.PI` set on the scene node, matching\n * the BJS reference convention. SPZ assets are authored \"Y-down\", and BJS\n * compensates with `mesh.rotation.x = Math.PI` at scene-graph time. */\nexport async function loadSPZ(scene: SceneContext, url: string): Promise<GaussianSplattingMesh> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`loadSPZ: HTTP ${response.status} for ${url}`);\n }\n const raw = new Uint8Array(await response.arrayBuffer());\n // SPZ files are conventionally gzip-wrapped; auto-detect the magic.\n const isGzip = raw[0] === 0x1f && raw[1] === 0x8b;\n const data: ArrayBuffer = isGzip ? ((await decompressGzip(raw)).buffer as ArrayBuffer) : (raw.buffer as ArrayBuffer);\n const parsed = parseSpz(data);\n const friendly = url.substring(url.lastIndexOf(\"/\") + 1) || \"spz\";\n const mesh = await attachParsedSplat(scene, friendly, parsed);\n mesh.rotation.x = Math.PI;\n return mesh;\n}\n","import type { GaussianSplattingMesh } from \"./gaussian-splatting-mesh.js\";\nimport type { Mat4 } from \"../../math/types.js\";\n\nconst ROW_LENGTH = 32;\n\nfunction mat4TransformCoord(m: Float32Array, x: number, y: number, z: number): [number, number, number] {\n const w = 1.0 / (m[3]! * x + m[7]! * y + m[11]! * z + m[15]!);\n return [(m[0]! * x + m[4]! * y + m[8]! * z + m[12]!) * w, (m[1]! * x + m[5]! * y + m[9]! * z + m[13]!) * w, (m[2]! * x + m[6]! * y + m[10]! * z + m[14]!) * w];\n}\n\nfunction mat4ToRotationQuat(m: Float32Array): [number, number, number, number] {\n const sx = Math.sqrt(m[0]! * m[0]! + m[1]! * m[1]! + m[2]! * m[2]!);\n const sy = Math.sqrt(m[4]! * m[4]! + m[5]! * m[5]! + m[6]! * m[6]!);\n const sz = Math.sqrt(m[8]! * m[8]! + m[9]! * m[9]! + m[10]! * m[10]!);\n const r00 = m[0]! / sx,\n r01 = m[1]! / sx,\n r02 = m[2]! / sx;\n const r10 = m[4]! / sy,\n r11 = m[5]! / sy,\n r12 = m[6]! / sy;\n const r20 = m[8]! / sz,\n r21 = m[9]! / sz,\n r22 = m[10]! / sz;\n\n const trace = r00 + r11 + r22;\n let qw: number, qx: number, qy: number, qz: number;\n if (trace > 0) {\n const s = 0.5 / Math.sqrt(trace + 1.0);\n qw = 0.25 / s;\n qx = (r12 - r21) * s;\n qy = (r20 - r02) * s;\n qz = (r01 - r10) * s;\n } else if (r00 > r11 && r00 > r22) {\n const s = 2.0 * Math.sqrt(1.0 + r00 - r11 - r22);\n qw = (r12 - r21) / s;\n qx = 0.25 * s;\n qy = (r01 + r10) / s;\n qz = (r02 + r20) / s;\n } else if (r11 > r22) {\n const s = 2.0 * Math.sqrt(1.0 + r11 - r00 - r22);\n qw = (r20 - r02) / s;\n qx = (r01 + r10) / s;\n qy = 0.25 * s;\n qz = (r12 + r21) / s;\n } else {\n const s = 2.0 * Math.sqrt(1.0 + r22 - r00 - r11);\n qw = (r01 - r10) / s;\n qx = (r02 + r20) / s;\n qy = (r12 + r21) / s;\n qz = 0.25 * s;\n }\n const len = Math.hypot(qx, qy, qz, qw) || 1;\n return [qx / len, qy / len, qz / len, qw / len];\n}\n\nfunction quatMultiply(ax: number, ay: number, az: number, aw: number, bx: number, by: number, bz: number, bw: number): [number, number, number, number] {\n return [aw * bx + ax * bw + ay * bz - az * by, aw * by - ax * bz + ay * bw + az * bx, aw * bz + ax * by - ay * bx + az * bw, aw * bw - ax * bx - ay * by - az * bz];\n}\n\n/**\n * Bakes a transform matrix directly into a mesh's splat vertices, rewriting each splat's\n * position, scale, and orientation so the mesh renders identically with an identity transform.\n * @param mesh - Gaussian Splatting mesh to modify in place.\n * @param transform - World-space transform to bake into the splat data.\n */\nexport function bakeTransformIntoVertices(mesh: GaussianSplattingMesh, transform: Mat4): void {\n const arrayBuffer = mesh.splatsData;\n const newBuffer = arrayBuffer.slice(0);\n const u8 = new Uint8Array(newBuffer);\n const f32 = new Float32Array(newBuffer);\n const splatCount = (u8.byteLength / ROW_LENGTH) | 0;\n\n const m = new Float32Array(transform as unknown as ArrayLike<number>);\n\n const scaleX = Math.sqrt(m[0]! * m[0]! + m[1]! * m[1]! + m[2]! * m[2]!);\n\n const [tqx, tqy, tqz, tqw] = mat4ToRotationQuat(m);\n\n for (let i = 0; i < splatCount; i++) {\n const fi = i * 8;\n const bi = i * ROW_LENGTH;\n\n const rawX = f32[fi]!;\n const rawY = f32[fi + 1]!;\n const rawZ = f32[fi + 2]!;\n\n const x = rawX;\n const y = -rawY;\n const z = rawZ;\n\n const [tx, ty, tz] = mat4TransformCoord(m, x, y, z);\n f32[fi] = tx;\n f32[fi + 1] = -ty;\n f32[fi + 2] = tz;\n\n f32[fi + 3] = f32[fi + 3]! * scaleX;\n f32[fi + 4] = f32[fi + 4]! * scaleX;\n f32[fi + 5] = f32[fi + 5]! * scaleX;\n\n let qx = (u8[bi + 29]! - 127.5) / 127.5;\n let qy = (u8[bi + 30]! - 127.5) / 127.5;\n let qz = (u8[bi + 31]! - 127.5) / 127.5;\n let qw = (u8[bi + 28]! - 127.5) / 127.5;\n const qLen = Math.hypot(qx, qy, qz, qw) || 1;\n qx /= qLen;\n qy /= qLen;\n qz /= qLen;\n qw /= qLen;\n\n // Lite's buildSplatGeometry decodes quaternions with W,Y sign flips\n // (to compensate for the Y-position negate). The transform quaternion\n // must be conjugated by diag(1,-1,1) so the baked raw quaternion\n // produces the correct covariance after the decode flip is re-applied.\n const [rx, ry, rz, rw] = quatMultiply(tqx, -tqy, tqz, -tqw, qx, qy, qz, qw);\n const rLen = Math.hypot(rx, ry, rz, rw) || 1;\n\n u8[bi + 28] = Math.round((rw / rLen) * 127.5 + 127.5);\n u8[bi + 29] = Math.round((rx / rLen) * 127.5 + 127.5);\n u8[bi + 30] = Math.round((ry / rLen) * 127.5 + 127.5);\n u8[bi + 31] = Math.round((rz / rLen) * 127.5 + 127.5);\n }\n\n mesh.updateData(newBuffer);\n}\n\n/**\n * Bakes the mesh's current world matrix into its splat vertices, then resets the mesh's\n * position, rotation, and scaling to identity so the visual result is unchanged.\n * @param mesh - Gaussian Splatting mesh to modify in place.\n */\nexport function bakeCurrentTransformIntoVertices(mesh: GaussianSplattingMesh): void {\n const transform = mesh.worldMatrix;\n bakeTransformIntoVertices(mesh, transform);\n mesh.position.x = 0;\n mesh.position.y = 0;\n mesh.position.z = 0;\n mesh.rotationQuaternion.x = 0;\n mesh.rotationQuaternion.y = 0;\n mesh.rotationQuaternion.z = 0;\n mesh.rotationQuaternion.w = 1;\n mesh.scaling.x = 1;\n mesh.scaling.y = 1;\n mesh.scaling.z = 1;\n}\n","import type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene-core.js\";\nimport type { GaussianSplattingMesh, GsShaderFragment } from \"./gaussian-splatting-mesh.js\";\nimport { createGaussianSplattingMesh } from \"./gaussian-splatting-mesh.js\";\nimport { buildSplatGeometry, type ParsedSplat } from \"../../loader-splat/splat-data.js\";\nimport { attachGaussianSplattingMesh } from \"./gaussian-splatting-pipeline.js\";\nimport SplatSortWorker from \"../../loader-splat/splat-sort-worker.ts?worker&inline\";\n\n/**\n * Creates a Gaussian Splatting mesh with `splatCount` placeholder splats and attaches\n * it to the scene's render pipeline. Useful for procedurally filling splat data later.\n * @param scene - Scene that owns and renders the mesh.\n * @param name - Mesh name.\n * @param splatCount - Number of splats to allocate.\n * @param fragments - Optional custom shader fragments for the splat material.\n * @returns The created, scene-attached Gaussian Splatting mesh.\n */\nexport function createProceduralGaussianSplattingMesh(scene: SceneContext, name: string, splatCount: number, fragments?: readonly GsShaderFragment[]): GaussianSplattingMesh {\n const ROW = 32;\n const buffer = new ArrayBuffer(ROW * splatCount);\n const u8 = new Uint8Array(buffer);\n for (let i = 0; i < splatCount; i++) {\n u8[i * ROW + 24 + 3] = 255;\n u8[i * ROW + 28 + 0] = 255;\n u8[i * ROW + 28 + 1] = 128;\n u8[i * ROW + 28 + 2] = 128;\n u8[i * ROW + 28 + 3] = 128;\n }\n const parsed: ParsedSplat = { data: buffer };\n const geom = buildSplatGeometry(parsed.data);\n const worker = new SplatSortWorker({ name: \"babylon-lite-splat-sort\" });\n const eng = scene.engine as EngineContext;\n const mesh = createGaussianSplattingMesh(eng, name, geom, worker, parsed);\n attachGaussianSplattingMesh(scene, mesh, fragments);\n return mesh;\n}\n","/** GsShaderFragment plugins for linear-depth output from a Gaussian-Splatting mesh.\n *\n * Two variants matching BJS `DepthRenderer` configuration on a GS material:\n *\n * - `gsLinearDepthFragment` mirrors `depthRenderer.forceDepthWriteTransparentMeshes = true`\n * on a non-alpha-blended depth pass: each splat fragment with `alpha > 0.001`\n * writes the linear depth as `(d, d, d, 1)` and the rest discard.\n *\n * - `gsAlphaBlendedDepthFragment` mirrors `depthRenderer.alphaBlendedDepth = true`\n * on top: the fragment writes `(d, d, d, gaussianAlpha)` so the swapchain blend\n * accumulates a soft-edged depth visualisation matching BJS `V80DRL#19`.\n *\n * Both compute linear depth from `in.pos.z` (reverse-Z NDC z in [0,1] for\n * WebGPU) and the per-mesh projection matrix that's already present in the GS\n * UBO, so no extra uniforms are required.\n *\n * Apply by passing the fragment in `loadSplat(scene, url, [gsLinearDepthFragment])`. */\n\nimport type { GsShaderFragment } from \"./gaussian-splatting-mesh.js\";\n\nconst GS_LINEAR_DEPTH_HELPERS = /* wgsl */ `\nfn gsLinearDepth(ndcZ: f32) -> f32 {\n // Lite uses a reverse-Z left-handed perspective matrix:\n // projection[2][2] = -near / (far-near)\n // projection[3][2] = far*near / (far-near)\n // For a point at camera-space depth viewZ (positive in front in LH):\n // pos2d.z = projection[2][2] * viewZ + projection[3][2]\n // pos2d.w = viewZ\n // After perspective divide (what we get as in.pos.z):\n // ndcZ = pos2d.z / pos2d.w = projection[2][2] + projection[3][2] / viewZ\n // So we can recover viewZ and the camera near/far purely from the projection:\n let p22 = u.projection[2][2];\n let p32 = u.projection[3][2];\n let viewZ = p32 / (ndcZ - p22);\n let near = p32 / (1.0 - p22);\n let far = -p32 / p22;\n return clamp((viewZ - near) / (far - near), 0.0, 1.0);\n}\n`;\n\n/** Force-depth-write variant (BJS `forceDepthWriteTransparentMeshes = true`).\n * Matches BJS's `gaussianSplattingDepth.fragment.fx` default (no `ALPHA_BLENDED_DEPTH`)\n * branch exactly:\n *\n * ```\n * // base WGSL has `let A = -dot(in.vPos, in.vPos);` and `in.vColor.a = splat.color.a * material.alpha`\n * if (A < -in.vColor.a) { discard; } // ↔ if dot(vPos,vPos) > vColor.a\n * finalColor = vec4(linearDepth, linearDepth, linearDepth, 1.0);\n * ```\n *\n * Per-splat α is used as a *squared-radius* threshold in the splat-local 2D\n * quad coordinate (`vPos ∈ [-1,1]²`), so each splat clips to a disc of\n * radius √α inside its quad. No gaussian falloff in the depth pass —\n * surviving fragments all write `opacity = 1.0` (the EWA core is not\n * used here; that's the `gsAlphaBlendedDepthFragment` regime). */\nexport const gsLinearDepthFragment: GsShaderFragment = {\n id: \"gsLinearDepth\",\n helperFunctions: GS_LINEAR_DEPTH_HELPERS,\n fragmentSlots: {\n GS_FRAGMENT_BEFORE_FRAGCOLOR: /* wgsl */ `\n if (dot(in.vPos, in.vPos) > in.vColor.a) { discard; }\n let _gsDepth = gsLinearDepth(in.pos.z);\n finalColor = vec4<f32>(_gsDepth, _gsDepth, _gsDepth, 1.0);\n `,\n },\n};\n\n/** Alpha-blended depth variant (BJS `depthRenderer.alphaBlendedDepth = true`).\n * Splat fragments emit `(d, d, d, gaussianAlpha)` so the existing GS pipeline's\n * ALPHA_COMBINE blend accumulates a soft-edged grayscale depth visualisation,\n * matching BJS `V80DRL#19`. */\nexport const gsAlphaBlendedDepthFragment: GsShaderFragment = {\n id: \"gsAlphaBlendedDepth\",\n helperFunctions: GS_LINEAR_DEPTH_HELPERS,\n fragmentSlots: {\n GS_FRAGMENT_BEFORE_FRAGCOLOR: /* wgsl */ `\n let _gsDepth = gsLinearDepth(in.pos.z);\n finalColor = vec4<f32>(_gsDepth, _gsDepth, _gsDepth, finalColor.a);\n `,\n },\n};\n","/** GsShaderFragment for Gaussian-Splatting GPU picking.\n *\n * Lite equivalent of BJS `GaussianSplattingGpuPickingMaterialPlugin.pure.ts`:\n * reads a per-mesh `pickingColor: vec3f` uniform (the 24-bit pick id encoded\n * as normalised RGB) and writes it as the fragment color, discarding splat\n * fragments whose gaussian alpha is below 0.001 so picks pass cleanly through\n * transparent splats.\n *\n * This is the shader-injection half of the plugin. The CPU half — owning the\n * picking-color UBO, allocating the bind group and rendering with multi-target\n * output / no blending — lives in `gs-picking-pipeline.ts`. Splitting the\n * plugin this way mirrors how BJS's `MaterialPluginBase.getCustomCode` (shader\n * side) and `bindForSubMesh` (binding side) interact.\n *\n * Compound (multi-part) picking is **not** supported in Lite (matches the\n * minimal-port scope confirmed for scene 129). */\n\nimport type { GsShaderFragment } from \"./gaussian-splatting-mesh.js\";\n\n/** Lite port of `GaussianSplattingGpuPickingMaterialPlugin`'s non-compound path:\n * declare a `picking` UBO at `@group(2) @binding(0)` (allocated by the picking\n * pipeline) and override the fragment colour with the per-mesh pick id. */\nexport const gsGpuPickingFragment: GsShaderFragment = {\n id: \"gsGpuPicking\",\n helperFunctions: /* wgsl */ `\nstruct GsPickingU { pickingColor: vec3<f32> };\n@group(2) @binding(0) var<uniform> picking: GsPickingU;\n`,\n fragmentSlots: {\n GS_FRAGMENT_BEFORE_FRAGCOLOR: /* wgsl */ `\n if (finalColor.a < 0.001) { discard; }\n finalColor = vec4<f32>(picking.pickingColor, 1.0);\n `,\n },\n};\n\n/** CPU helper matching BJS `GaussianSplattingGpuPickingMaterialPlugin.EncodeIdToColor`. */\nexport function encodeIdToColor(id: number): [number, number, number] {\n return [((id >> 16) & 0xff) / 255, ((id >> 8) & 0xff) / 255, (id & 0xff) / 255];\n}\n","/** Linear-depth ShaderMaterial — outputs `vec4(linearDepth)` for every fragment.\n *\n * Lite equivalent of BJS `DepthRenderer` (linear-mode) + `customDepthPixelShader`\n * post-process collapsed into a single direct-to-swapchain material. The fragment\n * writes the grayscale depth visualization directly, so scenes don't need an\n * offscreen render target + post-process pass.\n *\n * `linearDepth = (viewZ - near) / (far - near)`, matching BJS's\n * `DepthRenderer.useOnlyInActiveCamera = true; isPacked = false` path. */\n\nimport type { ShaderMaterial } from \"../material/shader/shader-material.js\";\nimport { createShaderMaterial } from \"../material/shader/shader-material.js\";\n\nconst VERTEX = /* wgsl */ `\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) viewZ: f32,\n};\n@vertex\nfn mainVertex(input: VertexInput) -> VertexOutput {\n var out: VertexOutput;\n let worldPos = shaderSystem.world * vec4<f32>(input.position, 1.0);\n let viewPos = shaderSystem.view * worldPos;\n out.position = shaderSystem.projection * viewPos;\n // LH view space: positive z is in front of the camera.\n out.viewZ = viewPos.z;\n return out;\n}\n`;\n\nconst FRAGMENT = /* wgsl */ `\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) viewZ: f32,\n};\n@fragment\nfn mainFragment(input: VertexOutput) -> @location(0) vec4<f32> {\n let near = shaderUniforms.nearFar.x;\n let far = shaderUniforms.nearFar.y;\n let d = clamp((input.viewZ - near) / (far - near), 0.0, 1.0);\n return vec4<f32>(d, d, d, 1.0);\n}\n`;\n\n/** Options for `createLinearDepthMaterial()`. */\nexport interface LinearDepthMaterialOptions {\n /** Camera near plane (defaults to 0.03 to match the source playground). */\n near?: number;\n /** Camera far plane (defaults to 15 to match the source playground). */\n far?: number;\n /** Optional material name. */\n name?: string;\n}\n\n/** Create a linear-depth ShaderMaterial that writes `(d, d, d, 1)` per fragment.\n * The depth is computed from the view-space z, normalized by the supplied\n * near/far range (or 0.03/15 by default). Override per material via the\n * `nearFar` custom uniform. */\nexport function createLinearDepthMaterial(options: LinearDepthMaterialOptions = {}): ShaderMaterial {\n const near = options.near ?? 0.03;\n const far = options.far ?? 15.0;\n return createShaderMaterial({\n name: options.name ?? \"linearDepth\",\n vertexSource: VERTEX,\n fragmentSource: FRAGMENT,\n attributes: [\"position\"],\n uniforms: [\"world\", \"view\", \"projection\", { name: \"nearFar\", type: \"vec2<f32>\", defaultValue: [near, far] }],\n backFaceCulling: true,\n depthWrite: true,\n depthCompare: \"greater-equal\",\n });\n}\n","/**\n * Shared shadow helpers used by ESM and PCF shadow generators/tasks.\n */\n\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\n\n/** Write shadow generator state into a Float32Array(24) for UBO upload.\n * Layout: [lightMatrix(16), depthValues.x, depthValues.y, 0, 0, shadowsInfo(4)] */\nexport function writeShadowUboFields(out: Float32Array, sg: { _lightMatrix: Float32Array; _depthValues: Float32Array; _shadowsInfo: Float32Array }): void {\n out.set(sg._lightMatrix, 0);\n out[16] = sg._depthValues[0]!;\n out[17] = sg._depthValues[1]!;\n out[18] = 0;\n out[19] = 0;\n out[20] = sg._shadowsInfo[0]!;\n out[21] = sg._shadowsInfo[1]!;\n out[22] = sg._shadowsInfo[2]!;\n out[23] = sg._shadowsInfo[3]!;\n}\n\n/** Build a light-space view matrix (column-major 4x4) from direction + position.\n * Shared between directional and spot shadow generators. */\nexport function buildLightViewMatrix(dirX: number, dirY: number, dirZ: number, px: number, py: number, pz: number): Float32Array {\n const len = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ) || 1;\n const fx = dirX / len;\n const fy = dirY / len;\n const fz = dirZ / len;\n\n let upX = 0,\n upY = 1,\n upZ = 0;\n if (Math.abs(fy) > 0.99) {\n upX = 0;\n upY = 0;\n upZ = 1;\n }\n // right = cross(up, forward)\n let rx = upY * fz - upZ * fy;\n let ry = upZ * fx - upX * fz;\n let rz = upX * fy - upY * fx;\n const rLen = Math.sqrt(rx * rx + ry * ry + rz * rz) || 1;\n rx /= rLen;\n ry /= rLen;\n rz /= rLen;\n\n // up = cross(forward, right)\n const ux = fy * rz - fz * ry;\n const uy = fz * rx - fx * rz;\n const uz = fx * ry - fy * rx;\n\n // Column-major view matrix (stores basis as rows of rotation, plus translation column)\n return new Float32Array([rx, ux, fx, 0, ry, uy, fy, 0, rz, uz, fz, 0, -(rx * px + ry * py + rz * pz), -(ux * px + uy * py + uz * pz), -(fx * px + fy * py + fz * pz), 1]);\n}\n\n/** Multiply two column-major 4x4 matrices: out = a * b. */\nexport function multiply4x4(a: Float32Array, b: Float32Array): Float32Array {\n const out = new Float32Array(16);\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n let sum = 0;\n for (let k = 0; k < 4; k++) {\n sum += a[row + k * 4]! * b[k + col * 4]!;\n }\n out[row + col * 4] = sum;\n }\n }\n return out;\n}\n\n/** Create the shared shadow-params UBO (32 bytes) holding bias/depthScale/depth-range fields. */\nexport function createShadowParamsUBO(engine: EngineContext, bias: number, depthScale: number): GPUBuffer {\n const data = new Float32Array(8);\n data[0] = bias;\n data[2] = depthScale;\n data[4] = 0; // depthMinZ (WebGPU)\n data[5] = 1; // depthMinZ + depthMaxZ\n return createUniformBuffer(engine, data);\n}\n\n/** Create the eager shadow-map render target used by frame-graph shadow tasks. */\nexport function createShadowRenderTarget(sg: ShadowGenerator, colorTexture: GPUTexture | null = null, depthTexture: GPUTexture = sg._depthTexture): RenderTarget {\n const mapSize = sg._config._mapSize;\n return {\n _descriptor: {\n size: { width: mapSize, height: mapSize },\n colorFormat: colorTexture ? \"rgba16float\" : undefined,\n depthStencilFormat: \"depth32float\",\n _depthClearValue: 1,\n _depthCompare: \"less-equal\",\n sampleCount: 1,\n flipY: false,\n },\n _colorTexture: colorTexture,\n _colorView: colorTexture?.createView() ?? null,\n _depthTexture: depthTexture,\n _depthView: depthTexture.createView(),\n _width: mapSize,\n _height: mapSize,\n _eager: true,\n };\n}\n\n/** Create the shared receiver-side shadow UBO (96 bytes), initialised from state. */\nexport function createSharedShadowUBO(\n engine: EngineContext,\n _lightMatrix: Float32Array,\n _depthValues: Float32Array,\n _shadowsInfo: Float32Array\n): { ubo: GPUBuffer; data: Float32Array } {\n const data = new Float32Array(24);\n writeShadowUboFields(data, { _lightMatrix, _depthValues, _shadowsInfo });\n const ubo = createUniformBuffer(engine, data);\n return { ubo, data };\n}\n\n/** Sum caster world matrix versions for shadow-map dirty checks. */\nexport function casterVersionSum(casterMeshes: readonly Mesh[]): number {\n let sum = 0;\n for (const mesh of casterMeshes) {\n sum += mesh.worldMatrixVersion;\n }\n return sum;\n}\n\n/** Create the light-owned camera facade used by shadow render tasks. */\nexport function createShadowCamera(sg: Pick<ShadowGenerator, \"_light\">): Camera {\n return {\n fov: 1,\n nearPlane: 1,\n farPlane: 1,\n children: [],\n get worldMatrix() {\n return sg._light.worldMatrix;\n },\n get worldMatrixVersion() {\n const state = (this as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion;\n return state ?? sg._light.worldMatrixVersion;\n },\n } as Camera;\n}\n\n/** Update the camera facade caches shared by all shadow task variants. */\nexport function updateShadowCameraBase(camera: Camera, cameraVersion: number, near: number, far: number, view: Float32Array, viewProj: Float32Array): void {\n camera.nearPlane = near;\n camera.farPlane = far;\n camera._viewCache = view;\n camera._viewVer = cameraVersion;\n camera._vpCache = viewProj;\n camera._vpVer = cameraVersion;\n camera._vpAspect = 1;\n (camera as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion = cameraVersion;\n}\n","export default \"// Shadow Blur Vertex Shader — fullscreen quad with pre-computed sample coordinates\\n// Uses Babylon's kernel blur approach with bilinear tap offsets\\n\\nstruct BlurParams {\\n delta: vec2<f32>, // (1/texWidth, 0) for H pass, (0, 1/texHeight) for V pass\\n _pad: vec2<f32>,\\n};\\n@group(0) @binding(0) var<uniform> params: BlurParams;\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) sampleCenter: vec2<f32>,\\n};\\n\\n@vertex\\nfn main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {\\n // Fullscreen triangle (3 vertices cover the screen)\\n var pos = array<vec2<f32>, 3>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>(3.0, -1.0),\\n vec2<f32>(-1.0, 3.0),\\n );\\n\\n var out: VertexOutput;\\n let p = pos[vertexIndex];\\n out.clipPos = vec4<f32>(p, 0.0, 1.0);\\n out.sampleCenter = p * vec2<f32>(0.5, -0.5) + 0.5;\\n return out;\\n}\\n\"","/**\n * Exponential Shadow Map (ESM) generator resource setup.\n *\n * This module creates the directional shadow resources and owns the internal\n * task hooks used by frame-graph/shadow-task.ts.\n */\n\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createRenderTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport {\n buildLightViewMatrix,\n casterVersionSum,\n createSharedShadowUBO,\n createShadowCamera,\n createShadowParamsUBO,\n createShadowRenderTarget,\n multiply4x4,\n updateShadowCameraBase,\n writeShadowUboFields,\n} from \"./shadow-base.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\nimport blurVertSrc from \"../../shaders/shadow-blur.vertex.wgsl?raw\";\n\nexport interface EsmLightMatrix {\n /** @internal */\n _view: Float32Array;\n /** @internal */\n _viewProj: Float32Array;\n /** @internal */\n _near: number;\n /** @internal */\n _far: number;\n}\n\nexport interface EsmShadowTaskResources {\n /** @internal */\n _esmTexture: GPUTexture;\n /** @internal */\n _depthBuffer: GPUTexture;\n /** @internal */\n _blurTexH: GPUTexture;\n /** @internal */\n _blurPipeline: GPURenderPipeline;\n /** @internal */\n _blurHBG: GPUBindGroup;\n /** @internal */\n _blurVBG: GPUBindGroup;\n /** @internal */\n _shadowUboData: Float32Array;\n}\n\n/** Configuration for a directional-light ESM shadow generator: map size, depth scale, blur kernel, darkness, and ortho projection bounds. */\nexport interface EsmDirectionalShadowGeneratorConfig {\n mapSize?: number;\n depthScale?: number;\n bias?: number;\n /** Kernel blur sample region in pixels. Matches Babylon.js ShadowGenerator.blurKernel. Default 1. */\n blurKernel?: number;\n blurScale?: number;\n darkness?: number;\n frustumEdgeFalloff?: number;\n /** Ortho projection min Z — typically camera.nearPlane. Default 1. */\n orthoMinZ?: number;\n /** Ortho projection max Z — typically camera.farPlane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\ninterface EsmTaskState extends ShadowTaskInternalState {\n _task: RenderTask;\n _camera: Camera;\n _cameraVersion: number;\n _lastCasterVersion: number;\n _lastLightVersion: number;\n _casterMeshes: readonly Mesh[];\n}\n\ntype StandardEsmFactory = typeof import(\"../material/standard/esm-shadow-view.js\").createStandardEsmShadowMaterialView;\ntype PbrEsmFactory = typeof import(\"../material/pbr/esm-shadow-view.js\").createPbrEsmShadowMaterialView;\ntype NodeEsmFactory = typeof import(\"../material/node/esm-shadow-view.js\").createNodeEsmShadowMaterialView;\n\nlet esmShadowTaskResources: WeakMap<ShadowGenerator, EsmShadowTaskResources> | null = null;\nlet createStandardEsmShadowMaterialView: StandardEsmFactory;\nlet createPbrEsmShadowMaterialView: PbrEsmFactory;\nlet createNodeEsmShadowMaterialView: NodeEsmFactory;\n\nfunction getEsmShadowTaskResourceMap(): WeakMap<ShadowGenerator, EsmShadowTaskResources> {\n esmShadowTaskResources ??= new WeakMap<ShadowGenerator, EsmShadowTaskResources>();\n return esmShadowTaskResources;\n}\n\nfunction setEsmShadowTaskResources(sg: ShadowGenerator, resources: EsmShadowTaskResources): void {\n getEsmShadowTaskResourceMap().set(sg, resources);\n}\n\nfunction getEsmShadowTaskResources(sg: ShadowGenerator): EsmShadowTaskResources | null {\n return esmShadowTaskResources?.get(sg) ?? null;\n}\n\nasync function preloadEsmShadowTaskState(casterMeshes: readonly Mesh[]): Promise<void> {\n const loads: Promise<void>[] = [];\n let needsStandard = false;\n let needsPbr = false;\n let needsNode = false;\n for (const mesh of casterMeshes) {\n const family = mesh.material?._buildGroup._materialFamily;\n needsStandard ||= family === \"standard\";\n needsPbr ||= family === \"pbr\";\n needsNode ||= family === \"node\";\n }\n if (needsStandard && !createStandardEsmShadowMaterialView) {\n loads.push(\n import(\"../material/standard/esm-shadow-view.js\").then((module) => {\n createStandardEsmShadowMaterialView = module.createStandardEsmShadowMaterialView;\n })\n );\n }\n if (needsPbr && !createPbrEsmShadowMaterialView) {\n loads.push(\n import(\"../material/pbr/esm-shadow-view.js\").then((module) => {\n createPbrEsmShadowMaterialView = module.createPbrEsmShadowMaterialView;\n })\n );\n }\n if (needsNode && !createNodeEsmShadowMaterialView) {\n loads.push(\n import(\"../material/node/esm-shadow-view.js\").then((module) => {\n createNodeEsmShadowMaterialView = module.createNodeEsmShadowMaterialView;\n })\n );\n }\n await Promise.all(loads);\n}\n\n/** @internal Compute the ESM directional light view/projection matrix for ShadowTask. */\nfunction _computeDirectionalLightMatrix(light: DirectionalLight, casterMeshes: readonly Mesh[], orthoMinZ: number, orthoMaxZ: number): EsmLightMatrix {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x, light.position.y, light.position.z);\n let lMinX = Infinity;\n let lMaxX = -Infinity;\n let lMinY = Infinity;\n let lMaxY = -Infinity;\n for (const mesh of casterMeshes) {\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let ci = 0; ci < 8; ci++) {\n const lx = ci & 1 ? bmax[0]! : bmin[0]!;\n const ly = ci & 2 ? bmax[1]! : bmin[1]!;\n const lz = ci & 4 ? bmax[2]! : bmin[2]!;\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]!;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]!;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]!;\n const vx = view[0]! * wx + view[4]! * wy + view[8]! * wz + view[12]!;\n const vy = view[1]! * wx + view[5]! * wy + view[9]! * wz + view[13]!;\n lMinX = Math.min(lMinX, vx);\n lMaxX = Math.max(lMaxX, vx);\n lMinY = Math.min(lMinY, vy);\n lMaxY = Math.max(lMaxY, vy);\n }\n }\n if (!Number.isFinite(lMinX)) {\n lMinX = -1;\n lMaxX = 1;\n lMinY = -1;\n lMaxY = 1;\n }\n const sx = (lMaxX - lMinX) * 0.1;\n const sy = (lMaxY - lMinY) * 0.1;\n lMinX -= sx;\n lMaxX += sx;\n lMinY -= sy;\n lMaxY += sy;\n\n const near = orthoMinZ;\n const far = orthoMaxZ;\n const proj = new Float32Array(16);\n proj[0] = 2 / (lMaxX - lMinX);\n proj[5] = 2 / (lMaxY - lMinY);\n proj[10] = 1 / (far - near);\n proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);\n proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);\n proj[14] = -near / (far - near);\n proj[15] = 1;\n return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };\n}\n\nfunction nearestBestKernel(idealKernel: number): number {\n const v = Math.round(Math.max(idealKernel, 1));\n for (const k of [v, v - 1, v + 1, v - 2, v + 2]) {\n if (k % 2 !== 0 && Math.floor(k / 2) % 2 === 0 && k > 0) {\n return Math.max(k, 3);\n }\n }\n return Math.max(v, 3);\n}\n\nfunction gaussianWeight(x: number): number {\n const sigma = 1 / 3;\n return Math.exp(-((x * x) / (2 * sigma * sigma))) / (Math.sqrt(2 * Math.PI) * sigma);\n}\n\nfunction createKernelBlurSamples(idealKernel: number): { offsets: number[]; weights: number[] } {\n const n = nearestBestKernel(idealKernel);\n const centerIndex = (n - 1) / 2;\n const offsets: number[] = [];\n const weights: number[] = [];\n let totalWeight = 0;\n\n for (let i = 0; i < n; i++) {\n const u = i / (n - 1);\n const weight = gaussianWeight(u * 2.0 - 1);\n offsets[i] = i - centerIndex;\n weights[i] = weight;\n totalWeight += weight;\n }\n\n for (let i = 0; i < weights.length; i++) {\n weights[i] = weights[i]! / totalWeight;\n }\n\n const linearOffsets: number[] = [];\n const linearWeights: number[] = [];\n for (let i = 0; i <= centerIndex; i += 2) {\n const j = Math.min(i + 1, Math.floor(centerIndex));\n if (i === j) {\n linearOffsets.push(offsets[i]!);\n linearWeights.push(weights[i]!);\n continue;\n }\n\n const sharedCell = j === centerIndex;\n const weightLinear = weights[i]! + weights[j]! * (sharedCell ? 0.5 : 1);\n const offsetLinear = offsets[i]! + 1 / (1 + weights[i]! / weights[j]!);\n if (offsetLinear === 0) {\n linearOffsets.push(offsets[i]!, offsets[i + 1]!);\n linearWeights.push(weights[i]!, weights[i + 1]!);\n } else {\n linearOffsets.push(offsetLinear, -offsetLinear);\n linearWeights.push(weightLinear, weightLinear);\n }\n }\n\n return { offsets: linearOffsets, weights: linearWeights };\n}\n\nfunction wgslFloat(value: number): string {\n const n = Object.is(value, -0) ? 0 : value;\n let s = n.toPrecision(10);\n if (!/[.eE]/.test(s)) {\n s += \".0\";\n }\n return s;\n}\n\nfunction createShadowBlurFragmentWGSL(blurKernel: number): string {\n const { offsets, weights } = createKernelBlurSamples(blurKernel);\n const count = offsets.length;\n return `struct BlurParams{delta:vec2<f32>,_pad:vec2<f32>,};@group(0) @binding(0) var<uniform> params:BlurParams;@group(0) @binding(1) var srcTex:texture_2d<f32>;@group(0) @binding(2) var srcSampler:sampler;const OFFSETS=array<f32,${count}>(${offsets.map(wgslFloat).join(\",\")});const WEIGHTS=array<f32,${count}>(${weights.map(wgslFloat).join(\",\")});@fragment fn main(@location(0) sampleCenter:vec2<f32>)->@location(0) vec4<f32>{var blend=vec4<f32>(0.0);for(var i=0u;i<${count}u;i=i+1u){blend+=textureSample(srcTex,srcSampler,sampleCenter+params.delta*OFFSETS[i])*WEIGHTS[i];}return blend;}`;\n}\n\nfunction ensureEsmShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): EsmTaskState {\n const existing = existingState as EsmTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes) {\n return existing;\n }\n existing._task.dispose();\n }\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n throw new Error(\"ShadowTask: missing ESM metadata.\");\n }\n const materialViews = new Map<Material, MaterialView>();\n const camera = createShadowCamera(sg);\n const taskState: EsmTaskState = {\n _task: createRenderTask(\n {\n name: \"esm\",\n rt: createShadowRenderTarget(sg, resources._esmTexture, resources._depthBuffer),\n clr: true,\n clrColor: { r: 0, g: 0, b: 0, a: 0 },\n cam: camera,\n },\n engine,\n scene\n ),\n _camera: camera,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _casterMeshes: casterMeshes,\n };\n\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n taskState._task.addMesh(mesh, { material: getEsmShadowView(material, materialViews, sg._shadowParamsUBO) });\n }\n }\n\n return taskState;\n}\n\nfunction renderEsmShadowMap(engine: EngineContext, sg: ShadowGenerator, state: EsmTaskState): number {\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n return 0;\n }\n const casterMeshes = state._casterMeshes;\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n if (!sg._config._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion) {\n return 0;\n }\n\n const matrix = _computeDirectionalLightMatrix(sg._light as DirectionalLight, casterMeshes, sg._config._orthoMinZ!, sg._config._orthoMaxZ!);\n if (shadowMatrixChanged(sg._lightMatrix, matrix._viewProj)) {\n sg._lightMatrix.set(matrix._viewProj);\n sg._version++;\n writeShadowUboFields(resources._shadowUboData, sg);\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, resources._shadowUboData as Float32Array<ArrayBuffer>);\n }\n updateShadowCamera(state, matrix);\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n\n let draws = state._task.execute?.() ?? 0;\n const encoder = engine._currentEncoder;\n const bh = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: resources._blurTexH.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bh.setPipeline(resources._blurPipeline);\n bh.setBindGroup(0, resources._blurHBG);\n bh.draw(3);\n bh.end();\n\n const bv = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: sg._depthTexture.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bv.setPipeline(resources._blurPipeline);\n bv.setBindGroup(0, resources._blurVBG);\n bv.draw(3);\n bv.end();\n draws += 2;\n return draws;\n}\n\nfunction updateShadowCamera(state: EsmTaskState, matrix: EsmLightMatrix): void {\n state._cameraVersion++;\n updateShadowCameraBase(state._camera, state._cameraVersion, matrix._near, matrix._far, matrix._view, matrix._viewProj);\n}\n\nfunction getEsmShadowView(material: Material, cache: Map<Material, MaterialView>, shadowParamsUBO: GPUBuffer): MaterialView {\n const cached = cache.get(material);\n if (cached) {\n return cached;\n }\n const family = material._buildGroup._materialFamily;\n let view: MaterialView;\n if (family === \"standard\") {\n view = createStandardEsmShadowMaterialView(material as Parameters<StandardEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"pbr\") {\n view = createPbrEsmShadowMaterialView(material as Parameters<PbrEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"node\") {\n view = createNodeEsmShadowMaterialView(material as Parameters<NodeEsmFactory>[0], shadowParamsUBO);\n }\n cache.set(material, view!);\n return view!;\n}\n\nfunction shadowMatrixChanged(a: Float32Array, b: Float32Array): boolean {\n for (let i = 0; i < 16; i++) {\n if (a[i] !== b[i]) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Creates an exponential shadow map (ESM) shadow generator for a directional light,\n * including the depth, blur, and final ESM textures plus the per-frame render task hooks.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map, blur, and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional ESM render path.\n */\nexport function createEsmDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: EsmDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const depthScale = cfg.depthScale ?? 50;\n const bias = cfg.bias ?? 0.00005;\n const blurKernel = cfg.blurKernel ?? 1;\n const blurScale = cfg.blurScale ?? 2;\n const darkness = cfg.darkness ?? 0;\n const frustumEdgeFalloff = cfg.frustumEdgeFalloff ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n const blurSize = mapSize / blurScale;\n\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n };\n\n const _shadowParamsUBO = createShadowParamsUBO(engine, bias, depthScale);\n\n const esmTexture = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"rgba16float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n });\n const depthBuf = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT,\n });\n const blurTexH = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n });\n const blurTexV = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n });\n\n const blurVert = device.createShaderModule({ code: blurVertSrc });\n const blurFrag = device.createShaderModule({ code: createShadowBlurFragmentWGSL(blurKernel) });\n const blurBGL = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n const blurPipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [blurBGL] }),\n vertex: { module: blurVert, entryPoint: \"main\" },\n fragment: { module: blurFrag, entryPoint: \"main\", targets: [{ format: \"rgba16float\" }] },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n });\n\n const blurSampler = getBilinearSampler(engine);\n const blurHData = new Float32Array([1.0 / blurSize, 0, 0, 0]);\n const blurHUBO = createUniformBuffer(engine, blurHData);\n const blurHBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurHUBO } },\n { binding: 1, resource: esmTexture.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n const blurVData = new Float32Array([0, 1.0 / blurSize, 0, 0]);\n const blurVUBO = createUniformBuffer(engine, blurVData);\n const blurVBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurVUBO } },\n { binding: 1, resource: blurTexH.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n\n const _lightMatrix = new Float32Array(16);\n const _shadowsInfo = new Float32Array([darkness, 0, depthScale, frustumEdgeFalloff]);\n const _depthValues = new Float32Array([0, 1]);\n const { ubo: _shadowUBO, data: shadowUboData } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _depthTexture = blurTexV;\n const _depthSampler = blurSampler;\n\n const sg: ShadowGenerator = {\n _shadowType: \"esm\",\n _light,\n _depthTexture,\n _depthSampler,\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO,\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadEsmShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensureEsmShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderEsmShadowMap(engine, sg, state as EsmTaskState);\n };\n setEsmShadowTaskResources(sg, {\n _esmTexture: esmTexture,\n _depthBuffer: depthBuf,\n _blurTexH: blurTexH,\n _blurPipeline: blurPipeline,\n _blurHBG: blurHBG,\n _blurVBG: blurVBG,\n _shadowUboData: shadowUboData,\n });\n return sg;\n}\n","/** Internal PCF shadow task hooks owned by PCF shadow generators. */\n\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { SpotLight } from \"../light/spot-light.js\";\nimport { createRenderTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport { casterVersionSum, createShadowCamera, createShadowRenderTarget, updateShadowCameraBase, writeShadowUboFields } from \"./shadow-base.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\n\nexport interface PcfLightMatrix {\n /** @internal */\n _view: Float32Array;\n /** @internal */\n _viewProj: Float32Array;\n /** @internal */\n _near: number;\n /** @internal */\n _far: number;\n}\n\nexport interface PcfTaskState extends ShadowTaskInternalState {\n /** @internal */\n _task: RenderTask;\n /** @internal */\n _camera: Camera;\n /** @internal */\n _cameraVersion: number;\n /** @internal */\n _lastCasterVersion: number;\n /** @internal */\n _lastLightVersion: number;\n /** @internal */\n _shadowUboData: Float32Array;\n /** @internal */\n _casterMeshes: readonly Mesh[];\n}\n\ntype StandardNoColorFactory = typeof import(\"../material/standard/no-color-view.js\").createStandardNoColorMaterialView;\ntype PbrNoColorFactory = typeof import(\"../material/pbr/no-color-view.js\").createPbrNoColorMaterialView;\ntype NodeNoColorFactory = typeof import(\"../material/node/no-color-view.js\").createNodeNoColorMaterialView;\n\nlet createStandardNoColorMaterialView: StandardNoColorFactory;\nlet createPbrNoColorMaterialView: PbrNoColorFactory;\nlet createNodeNoColorMaterialView: NodeNoColorFactory;\n\nexport async function preloadPcfShadowTaskState(casterMeshes: readonly Mesh[]): Promise<void> {\n const loads: Promise<void>[] = [];\n let needsStandard = false;\n let needsPbr = false;\n let needsNode = false;\n for (const mesh of casterMeshes) {\n const family = mesh.material?._buildGroup._materialFamily;\n needsStandard ||= family === \"standard\";\n needsPbr ||= family === \"pbr\";\n needsNode ||= family === \"node\";\n }\n if (needsStandard && !createStandardNoColorMaterialView) {\n loads.push(\n import(\"../material/standard/no-color-view.js\").then((module) => {\n createStandardNoColorMaterialView = module.createStandardNoColorMaterialView;\n })\n );\n }\n if (needsPbr && !createPbrNoColorMaterialView) {\n loads.push(\n import(\"../material/pbr/no-color-view.js\").then((module) => {\n createPbrNoColorMaterialView = module.createPbrNoColorMaterialView;\n })\n );\n }\n if (needsNode && !createNodeNoColorMaterialView) {\n loads.push(\n import(\"../material/node/no-color-view.js\").then((module) => {\n createNodeNoColorMaterialView = module.createNodeNoColorMaterialView;\n })\n );\n }\n await Promise.all(loads);\n}\n\nexport function ensurePcfShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): PcfTaskState {\n const existing = existingState as PcfTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes) {\n return existing;\n }\n existing._task.dispose();\n }\n\n const materialViews = new Map<Material, MaterialView>();\n const camera = createShadowCamera(sg);\n const rt = createShadowRenderTarget(sg);\n const state: PcfTaskState = {\n _task: createRenderTask(\n {\n name: \"pcf\",\n rt,\n clr: true,\n cam: camera,\n },\n engine,\n scene\n ),\n _camera: camera,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _shadowUboData: new Float32Array(24),\n _casterMeshes: casterMeshes,\n };\n\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n state._task.addMesh(mesh, { material: getNoColorView(material, materialViews) });\n }\n }\n\n return state;\n}\n\nexport function renderPcfShadowMap(engine: EngineContext, sg: ShadowGenerator, state: PcfTaskState, computeLightMatrix: (casterMeshes: readonly Mesh[]) => PcfLightMatrix): number {\n const casterMeshes = state._casterMeshes;\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n if (!sg._config._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion) {\n return 0;\n }\n\n const matrix = computeLightMatrix(casterMeshes);\n const matrixChanged = sg._light.lightType === \"directional\" || lightVersion !== state._lastLightVersion;\n if (matrixChanged) {\n sg._lightMatrix.set(matrix._viewProj);\n sg._version++;\n writeShadowUboFields(state._shadowUboData, sg);\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, state._shadowUboData as Float32Array<ArrayBuffer>);\n }\n updateShadowCamera(state, sg, matrix);\n\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n return state._task.execute?.() ?? 0;\n}\n\nfunction updateShadowCamera(state: PcfTaskState, sg: ShadowGenerator, matrix: PcfLightMatrix): void {\n state._cameraVersion++;\n state._camera.fov = sg._light.lightType === \"spot\" ? (sg._light as SpotLight).angle : 1;\n updateShadowCameraBase(state._camera, state._cameraVersion, matrix._near, matrix._far, matrix._view, biasViewProjection(matrix._viewProj, sg._config._bias));\n}\n\nfunction biasViewProjection(viewProj: Float32Array, bias: number): Float32Array {\n const biased = new Float32Array(viewProj);\n const b = bias * 0.5;\n for (let col = 0; col < 4; col++) {\n const z = 2 + col * 4;\n const w = 3 + col * 4;\n biased[z] = biased[z]! + b * biased[w]!;\n }\n return biased;\n}\n\nfunction getNoColorView(material: Material, cache: Map<Material, MaterialView>): MaterialView {\n const cached = cache.get(material);\n if (cached) {\n return cached;\n }\n const family = material._buildGroup._materialFamily;\n let view: MaterialView;\n if (family === \"standard\") {\n view = createStandardNoColorMaterialView(material as Parameters<StandardNoColorFactory>[0]);\n } else if (family === \"pbr\") {\n view = createPbrNoColorMaterialView(material as Parameters<PbrNoColorFactory>[0]);\n } else if (family === \"node\") {\n view = createNodeNoColorMaterialView(material as Parameters<NodeNoColorFactory>[0]);\n }\n cache.set(material, view!);\n return view!;\n}\n","/**\n * PCF Shadow Generator — Percentage Closer Filtering for spot lights.\n *\n * Pipeline (per frame):\n * 1. Render shadow casters to depth-only texture from light's perspective\n * 2. Main-pass fragment shader samples depth with comparison sampler (PCF5 — 5×5 bilinear)\n *\n * Compared to the ESM generator:\n * - No blur passes (saves 2 draw calls + 2 GPU textures)\n * - depth32float depth-only texture (no rgba16float color)\n * - Smaller shadow maps work well (512 default)\n * - Uses hardware depth comparison + averaging for soft edges\n *\n * Matches Babylon.js ShadowGenerator with:\n * - usePercentageCloserFiltering = true (SM_PCF / shadow5 quality)\n */\n\nimport type { SpotLight } from \"../light/spot-light.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { buildLightViewMatrix, createSharedShadowUBO, createShadowParamsUBO, multiply4x4 } from \"./shadow-base.js\";\nimport { ensurePcfShadowTaskState, preloadPcfShadowTaskState, renderPcfShadowMap, type PcfLightMatrix, type PcfTaskState } from \"./pcf-shadow-task-hooks.js\";\n\n/** Configuration for a spot-light PCF shadow generator: map size, depth bias, darkness, and projection near/far planes. */\nexport interface PcfSpotlightShadowGeneratorConfig {\n mapSize?: number;\n bias?: number;\n darkness?: number;\n normalBias?: number;\n /** Near plane for the shadow projection. Default: uses camera near (1). */\n near?: number;\n /** Far plane for the shadow projection. Default: uses camera far or light range. */\n far?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\n/** @internal Compute the PCF spot-light view/projection matrix for ShadowTask. */\nexport function _computeSpotLightMatrix(light: SpotLight, near: number, far: number): PcfLightMatrix {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x, light.position.y, light.position.z);\n const f = 1.0 / Math.tan(light.angle * 0.5);\n const proj = new Float32Array(16);\n proj[0] = f;\n proj[5] = f;\n proj[10] = far / (far - near);\n proj[11] = 1;\n proj[14] = -(far * near) / (far - near);\n return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };\n}\n\n/**\n * Creates a PCF (percentage-closer filtering) shadow generator for a spot light, using a\n * perspective projection derived from the light's cone angle.\n * @param engine - The engine providing the GPU device.\n * @param _light - The spot light that casts the shadows.\n * @param cfg - Optional shadow-map and projection configuration.\n * @returns A `ShadowGenerator` wired to the spot-light PCF render path.\n */\nexport function createPcfSpotlightShadowGenerator(engine: EngineContext, _light: SpotLight, cfg: PcfSpotlightShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 512;\n const bias = cfg.bias ?? 0.00005;\n const darkness = cfg.darkness ?? 0;\n // Near/far for perspective projection — BJS uses activeCamera.minZ / maxZ\n const near = cfg.near ?? 1;\n const far = cfg.far ?? (_light.range === Number.MAX_VALUE ? 10000 : _light.range);\n\n // --- Depth-only texture ---\n const _depthTexture = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n });\n // --- Comparison sampler for PCF ---\n const _depthSampler = device.createSampler({\n compare: \"less\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n });\n\n // Shadow params UBO (depthScale slot reused as texel size for PCF offsets)\n const _shadowParamsUBO = createShadowParamsUBO(engine, bias, 1.0 / mapSize);\n\n const _lightMatrix = new Float32Array(16);\n const _shadowsInfo = new Float32Array([darkness, mapSize, 1.0 / mapSize, 0]);\n const _depthValues = new Float32Array([0, far]);\n\n // Shared shadow UBO for all receiver meshes (96 bytes)\n const { ubo: _shadowUBO } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _forceRefreshEveryFrame: cfg.forceRefreshEveryFrame ?? false,\n };\n\n const sg: ShadowGenerator = {\n _shadowType: \"pcf\",\n _light,\n _depthTexture,\n _depthSampler,\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO,\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadPcfShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensurePcfShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderPcfShadowMap(engine, sg, state as PcfTaskState, () => _computeSpotLightMatrix(_light, near, far));\n };\n return sg;\n}\n","/** PCF Shadow Generator for Directional Lights.\n *\n * Same on-shader PCF5 sampling as `pcf-spotlight-shadow-generator.ts`, but with an\n * orthographic light projection fit to the caster AABBs — matching Babylon's\n * DirectionalLight + `usePercentageCloserFiltering=true` configuration.\n *\n * Everything downstream of the projection (depth-only pipeline, comparison\n * sampler, shared UBOs, dirty tracking) is identical to the spot-light PCF\n * path. The only differences are:\n * 1. The projection matrix (ortho vs perspective).\n * 2. The projection bounds auto-fit based on casters' world AABBs.\n *\n * Exported separately so scenes that only use spot-PCF don't pull in the\n * directional AABB-fit code path, and so the API parallels the ESM split\n * (`createEsmDirectionalShadowGenerator` → directional ESM, `createPcfSpotlightShadowGenerator` → spot PCF).\n */\n\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { buildLightViewMatrix, createSharedShadowUBO, createShadowParamsUBO, multiply4x4 } from \"./shadow-base.js\";\nimport { ensurePcfShadowTaskState, preloadPcfShadowTaskState, renderPcfShadowMap, type PcfLightMatrix, type PcfTaskState } from \"./pcf-shadow-task-hooks.js\";\n\n// ─── Internal helpers ───────────────────────────────────────────────\n\n/** @internal Compute the PCF directional light view/projection matrix for ShadowTask. */\nfunction _computeDirectionalLightMatrix(light: DirectionalLight, casterMeshes: readonly Mesh[], orthoMinZ: number, orthoMaxZ: number): PcfLightMatrix {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x, light.position.y, light.position.z);\n let lMinX = Infinity,\n lMaxX = -Infinity,\n lMinY = Infinity,\n lMaxY = -Infinity;\n for (const mesh of casterMeshes) {\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let ci = 0; ci < 8; ci++) {\n const lx = ci & 1 ? bmax[0] : bmin[0];\n const ly = ci & 2 ? bmax[1] : bmin[1];\n const lz = ci & 4 ? bmax[2] : bmin[2];\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]!;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]!;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]!;\n const vx = view[0]! * wx + view[4]! * wy + view[8]! * wz + view[12]!;\n const vy = view[1]! * wx + view[5]! * wy + view[9]! * wz + view[13]!;\n lMinX = Math.min(lMinX, vx);\n lMaxX = Math.max(lMaxX, vx);\n lMinY = Math.min(lMinY, vy);\n lMaxY = Math.max(lMaxY, vy);\n }\n }\n if (!Number.isFinite(lMinX)) {\n lMinX = -1;\n lMaxX = 1;\n lMinY = -1;\n lMaxY = 1;\n }\n const sx = (lMaxX - lMinX) * 0.1;\n const sy = (lMaxY - lMinY) * 0.1;\n lMinX -= sx;\n lMaxX += sx;\n lMinY -= sy;\n lMaxY += sy;\n\n const near = orthoMinZ;\n const far = orthoMaxZ;\n const proj = new Float32Array(16);\n proj[0] = 2 / (lMaxX - lMinX);\n proj[5] = 2 / (lMaxY - lMinY);\n proj[10] = 1 / (far - near);\n proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);\n proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);\n proj[14] = -near / (far - near);\n proj[15] = 1;\n return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };\n}\n\n/** Configuration for a directional-light PCF shadow generator: map size, depth bias, darkness, and ortho projection bounds. */\nexport interface PcfDirectionalShadowGeneratorConfig {\n mapSize?: number;\n bias?: number;\n darkness?: number;\n normalBias?: number;\n /** Ortho near plane. Default 1. */\n orthoMinZ?: number;\n /** Ortho far plane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\n/**\n * Creates a PCF (percentage-closer filtering) shadow generator for a directional light,\n * using an orthographic projection auto-fit to the caster meshes' world AABBs.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional PCF render path.\n */\nexport function createPcfDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: PcfDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const bias = cfg.bias ?? 0.00005;\n const darkness = cfg.darkness ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n\n const _lightMatrix = new Float32Array(16);\n const _shadowsInfo = new Float32Array([darkness, mapSize, 1.0 / mapSize, 0]);\n const _depthValues = new Float32Array([0, 1]);\n const { ubo: _shadowUBO } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n };\n\n const sg: ShadowGenerator = {\n _shadowType: \"pcf\" as const,\n _light,\n _depthTexture: device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n }),\n _depthSampler: device.createSampler({\n compare: \"less\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n }),\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO: createShadowParamsUBO(engine, bias, 1.0 / mapSize),\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadPcfShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensurePcfShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderPcfShadowMap(engine, sg, state as PcfTaskState, (casterMeshes) => _computeDirectionalLightMatrix(_light, casterMeshes, orthoMinZ, orthoMaxZ));\n };\n return sg;\n}\n","// Animation data types — flat structs, no classes.\n// Designed for zero-allocation per-frame evaluation.\n\nimport type { Mat4 } from \"../math/types.js\";\n\n// Interpolation modes (numeric for fast comparison in hot path)\nexport const INTERP_LINEAR = 0;\nexport const INTERP_STEP = 1;\nexport const INTERP_CUBICSPLINE = 2;\n\n// Target paths (numeric)\nexport const PATH_TRANSLATION = 0;\nexport const PATH_ROTATION = 1;\nexport const PATH_SCALE = 2;\nexport const PATH_WEIGHTS = 3;\n/** KHR_animation_pointer target — value is dispatched to an arbitrary writer\n * resolved from the JSON pointer at load time. */\nexport const PATH_POINTER = 4;\n\nexport type InterpMode = 0 | 1 | 2;\nexport type TargetPath = 0 | 1 | 2 | 3 | 4;\n\n/** Parsed keyframe sampler — times + values + interpolation. */\nexport interface AnimationSampler {\n /** Keyframe timestamps in seconds (monotonically increasing). */\n readonly input: Float32Array;\n /** Keyframe output values (vec3/quat/scalar packed sequentially).\n * For CUBICSPLINE: [inTangent, value, outTangent] per keyframe. */\n readonly output: Float32Array;\n readonly interpolation: InterpMode;\n}\n\n/** Single animation channel — targets one node property, or an arbitrary\n * KHR_animation_pointer target resolved at load time to a writer function. */\nexport interface AnimationChannel {\n readonly samplerIdx: number;\n /** For standard channels: glTF node index. For `PATH_POINTER`: unused (-1). */\n readonly nodeIdx: number;\n readonly path: TargetPath;\n /** PATH_POINTER only: invoked per-frame with the interpolated sampler output.\n * The writer is responsible for applying the value to the runtime target\n * (node.visible, material factor, camera fov, light color, ...). */\n readonly pointerWriter?: (output: Float32Array, offset: number) => void;\n /** PATH_POINTER only: number of floats per keyframe (1, 3, 4, ...). */\n readonly pointerArity?: number;\n /** PATH_POINTER only: true when LINEAR interpolation should use quaternion slerp. */\n readonly pointerQuaternion?: boolean;\n}\n\n/** One animation clip (may animate many nodes). */\nexport interface AnimationClip {\n readonly name: string;\n readonly channels: readonly AnimationChannel[];\n readonly samplers: readonly AnimationSampler[];\n /** Total duration in seconds (max of all sampler input times). */\n readonly duration: number;\n /** Frame rate used by AnimationGroup goToFrame(); defaults to 60. */\n readonly frameRate?: number;\n}\n\n/** Per-node rest pose TRS + parent link for hierarchy traversal. */\nexport interface NodeRest {\n readonly parentIdx: number; // -1 for root nodes\n /** @internal */\n readonly _matrix?: Mat4;\n tx: number;\n ty: number;\n tz: number;\n rx: number;\n ry: number;\n rz: number;\n rw: number;\n sx: number;\n sy: number;\n sz: number;\n}\n\n/** Connects a skeleton to its GPU bone texture for per-frame updates. */\nexport interface SkeletonBinding {\n readonly jointNodes: readonly number[];\n readonly inverseBindMatrices: Float32Array;\n readonly invMeshWorld: Mat4;\n readonly boneTexture: GPUTexture;\n readonly boneCount: number;\n readonly boneMatrices: Float32Array;\n readonly runtimeSkeleton?: SkeletonData;\n}\n\n/** Connects a morph-target mesh to its GPU weight buffer for per-frame updates. */\nexport interface MorphBinding {\n /** Node index that owns the morph targets. */\n readonly nodeIdx: number;\n /** GPU uniform buffer written each frame with current weights. */\n readonly weightsBuffer: GPUBuffer;\n /** CPU mirror of the first four current weights, used by deformation-aware picking. */\n readonly weights: Float32Array;\n /** Number of morph targets (max 4 supported). */\n readonly targetCount: number;\n readonly runtimeMorphTargets?: MorphTargetData;\n}\n\n/** Minimal structural view of a scene node's animatable transform. Lets the\n * animation controller apply plain glTF node-TRS channels (translation/rotation/\n * scale) to scene nodes without importing the scene layer. `SceneNode` is\n * structurally compatible with this interface. */\nexport interface AnimatedNodeTarget {\n readonly position: { set(x: number, y: number, z: number): void };\n readonly rotationQuaternion: { set(x: number, y: number, z: number, w: number): void };\n readonly scaling: { set(x: number, y: number, z: number): void };\n}\n\n/** Everything the animation system needs, parsed from a glTF file. */\nexport interface GltfAnimationData {\n readonly clips: readonly AnimationClip[];\n readonly nodes: readonly NodeRest[];\n readonly skeletons: readonly SkeletonBinding[];\n readonly morphBindings: readonly MorphBinding[];\n /** Scene-node targets indexed by glTF node index. Used to write plain node-TRS\n * channels (non-skeletal node animation) back onto the live scene graph so the\n * affected meshes — and their descendants — actually move. */\n readonly nodeTargets: readonly (AnimatedNodeTarget | undefined)[];\n /** Node indices excluded from node-TRS writeback: skin joints (driven by the\n * skeleton path) plus skinned-mesh nodes and all their ancestors (their bone\n * matrices bake an `invMeshWorld` captured at load, so moving them at runtime\n * would double-transform the skinned vertices). */\n readonly excludedNodeIndices: ReadonlySet<number>;\n}\n\n// ─── GPU-side data objects attached to Mesh ─────────────────────────────────\n\n/** Skeleton GPU data — bone texture + vertex buffers for skinning.\n * Created by createSkeleton() in skeleton/create-skeleton.ts.\n * Attached to mesh.skeleton. */\nexport interface SkeletonData {\n readonly boneTexture: GPUTexture;\n readonly boneCount: number;\n readonly jointsBuffer: GPUBuffer;\n readonly weightsBuffer: GPUBuffer;\n readonly joints: Uint16Array | Uint8Array;\n readonly weights: Float32Array;\n readonly boneMatrices: Float32Array;\n /** Extra joints/weights for 8-bone skinning (JOINTS_1/WEIGHTS_1). */\n readonly joints1Buffer: GPUBuffer | null;\n readonly weights1Buffer: GPUBuffer | null;\n readonly joints1: Uint16Array | Uint8Array | null;\n readonly weights1: Float32Array | null;\n}\n\n/** Morph target GPU data — delta texture + weights UBO.\n * Created by createMorphTargets() in morph/create-morph-targets.ts.\n * Attached to mesh.morphTargets. */\nexport interface MorphTargetData {\n readonly texture: GPUTexture;\n readonly count: number;\n readonly weightsBuffer: GPUBuffer;\n readonly targets: readonly { positions: Float32Array; normals: Float32Array | null }[];\n readonly weights: Float32Array<ArrayBuffer>;\n}\n","// Keyframe interpolation engine — LINEAR, STEP, CUBICSPLINE.\n// Pure functions, zero allocation in the hot path.\n\nimport type { AnimationSampler } from \"./types.js\";\nimport { INTERP_STEP, INTERP_CUBICSPLINE } from \"./types.js\";\n\n/** Binary search: find index i such that `input[i] <= t < input[i+1]`. */\nfunction findKeyframe(input: Float32Array, t: number): number {\n let lo = 0;\n let hi = input.length - 1;\n if (t <= input[0]!) {\n return 0;\n }\n if (t >= input[hi]!) {\n return hi > 0 ? hi - 1 : 0;\n }\n while (lo < hi - 1) {\n const mid = (lo + hi) >> 1;\n if (input[mid]! <= t) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\n// Reusable scratch for quaternion slerp (avoids per-call allocation)\nconst _quat = new Float32Array([0, 0, 0, 1]);\n\n/** Normalise 4 consecutive components (quaternion) in-place. No-op on zero length. */\nfunction normalizeQuat4(buf: Float32Array, o: number): void {\n const x = buf[o]!;\n const y = buf[o + 1]!;\n const z = buf[o + 2]!;\n const w = buf[o + 3]!;\n const lenSq = x * x + y * y + z * z + w * w;\n if (lenSq > 0) {\n const inv = 1 / Math.sqrt(lenSq);\n buf[o] = x * inv;\n buf[o + 1] = y * inv;\n buf[o + 2] = z * inv;\n buf[o + 3] = w * inv;\n }\n}\n\n/** Spherical linear interpolation between two quaternions. Writes to out[].\n * Lives here (not in math/mat4.ts) so non-animated scenes don't pay for it. */\nfunction quatSlerp(out: Float32Array, ax: number, ay: number, az: number, aw: number, bx: number, by: number, bz: number, bw: number, t: number): void {\n let dot = ax * bx + ay * by + az * bz + aw * bw;\n if (dot < 0) {\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n dot = -dot;\n }\n if (dot > 0.9995) {\n // Near-parallel: linear interpolation + normalize\n out[0] = ax + t * (bx - ax);\n out[1] = ay + t * (by - ay);\n out[2] = az + t * (bz - az);\n out[3] = aw + t * (bw - aw);\n normalizeQuat4(out, 0);\n return;\n }\n const theta = Math.acos(dot);\n const sinTheta = Math.sin(theta);\n const wa = Math.sin((1 - t) * theta) / sinTheta;\n const wb = Math.sin(t * theta) / sinTheta;\n out[0] = wa * ax + wb * bx;\n out[1] = wa * ay + wb * by;\n out[2] = wa * az + wb * bz;\n out[3] = wa * aw + wb * bw;\n}\n\n/**\n * Evaluate a sampler at time `t` and write the result into `dst` at `dstOffset`.\n * @param stride - Number of components per value (3 for vec3, 4 for quat).\n * @param isQuat - True for rotation channels (uses slerp instead of lerp).\n */\nexport function evaluateSampler(sampler: AnimationSampler, t: number, stride: number, isQuat: boolean, dst: Float32Array, dstOffset: number): void {\n const { input, output, interpolation } = sampler;\n const keyCount = input.length;\n\n if (keyCount === 0) {\n return;\n }\n if (keyCount === 1 || t <= input[0]!) {\n // Clamp to first keyframe\n const srcOff = interpolation === INTERP_CUBICSPLINE ? stride : 0; // skip in-tangent\n for (let c = 0; c < stride; c++) {\n dst[dstOffset + c] = output[srcOff + c]!;\n }\n return;\n }\n const idx = findKeyframe(input, t);\n const t0 = input[idx]!;\n const t1 = input[idx + 1]!;\n\n if (interpolation === INTERP_STEP) {\n const srcOff = (t >= t1 ? idx + 1 : idx) * stride;\n for (let c = 0; c < stride; c++) {\n dst[dstOffset + c] = output[srcOff + c]!;\n }\n return;\n }\n\n const dt = t1 - t0;\n const f = t >= t1 ? 1 : dt > 0 ? (t - t0) / dt : 0; // fractional time between keyframes\n\n if (interpolation === INTERP_CUBICSPLINE) {\n // Hermite spline: p(t) = (2t³-3t²+1)p0 + (t³-2t²+t)m0 + (-2t³+3t²)p1 + (t³-t²)m1\n const f2 = f * f;\n const f3 = f2 * f;\n const h00 = 2 * f3 - 3 * f2 + 1;\n const h10 = f3 - 2 * f2 + f;\n const h01 = -2 * f3 + 3 * f2;\n const h11 = f3 - f2;\n\n const k0 = idx * stride * 3; // [inTangent0, value0, outTangent0]\n const k1 = (idx + 1) * stride * 3;\n for (let c = 0; c < stride; c++) {\n const p0 = output[k0 + stride + c]!; // value at idx\n const m0 = output[k0 + 2 * stride + c]! * dt; // outTangent at idx * deltaTime\n const p1 = output[k1 + stride + c]!; // value at idx+1\n const m1 = output[k1 + c]! * dt; // inTangent at idx+1 * deltaTime\n dst[dstOffset + c] = h00 * p0 + h10 * m0 + h01 * p1 + h11 * m1;\n }\n\n // Normalize quaternion result for cubicspline rotation\n if (isQuat) {\n normalizeQuat4(dst, dstOffset);\n }\n return;\n }\n\n // LINEAR interpolation\n const s0 = idx * stride;\n const s1 = (idx + 1) * stride;\n\n if (isQuat) {\n quatSlerp(_quat, output[s0]!, output[s0 + 1]!, output[s0 + 2]!, output[s0 + 3]!, output[s1]!, output[s1 + 1]!, output[s1 + 2]!, output[s1 + 3]!, f);\n dst[dstOffset] = _quat[0]!;\n dst[dstOffset + 1] = _quat[1]!;\n dst[dstOffset + 2] = _quat[2]!;\n dst[dstOffset + 3] = _quat[3]!;\n } else {\n for (let c = 0; c < stride; c++) {\n dst[dstOffset + c] = output[s0 + c]! + f * (output[s1 + c]! - output[s0 + c]!);\n }\n }\n}\n","// Per-frame skeleton animation — evaluates clips and uploads bone matrices.\n// Zero per-frame allocation: all scratch buffers pre-allocated at init.\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { AnimationClip, NodeRest, SkeletonBinding, AnimatedNodeTarget } from \"../animation/types.js\";\nimport type { MorphBinding } from \"../animation/types.js\";\nimport { PATH_TRANSLATION, PATH_ROTATION, PATH_SCALE, PATH_WEIGHTS, PATH_POINTER } from \"../animation/types.js\";\nimport { evaluateSampler } from \"../animation/evaluate.js\";\nimport { mat4ComposeInto } from \"../math/mat4-compose-into.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\n\n// Scratch 4x4 used during bone-matrix composition; reused across frames + bones.\nconst _boneTmp = new Float32Array(16);\n\n// RH→LH root transform (same as load-gltf.ts): diag(-1, 1, 1, 1)\n// prettier-ignore\nconst RH_TO_LH = new Float32Array([-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\n\n/** TRS layout per node in the scratch buffer: 12 floats.\n * [0..2] = translation, [3..6] = rotation (xyzw), [7..9] = scale, [10..11] = padding */\nconst TRS_STRIDE = 12;\nconst T_OFF = 0;\nconst R_OFF = 3;\nconst S_OFF = 7;\n\n/** Compute topological order so parents are processed before children. */\nfunction computeTopoOrder(nodes: readonly { readonly parentIdx: number }[]): Int32Array {\n const n = nodes.length;\n const order = new Int32Array(n);\n const visited = new Uint8Array(n);\n let cursor = 0;\n\n function visit(idx: number): void {\n if (visited[idx]!) {\n return;\n }\n visited[idx] = 1;\n const p = nodes[idx]!.parentIdx;\n if (p >= 0) {\n visit(p);\n }\n order[cursor++] = idx;\n }\n\n for (let i = 0; i < n; i++) {\n visit(i);\n }\n return order;\n}\n\n/** Drives playback of a skeletal/morph animation clip, advancing time and uploading bone matrices each tick. */\nexport interface AnimationController {\n /** Advance animation by deltaMs and update bone textures. */\n tick(deltaMs: number, engine?: EngineContext): void;\n /** Current playback time in seconds. */\n time: number;\n /** True if playing. */\n playing: boolean;\n /** Playback speed multiplier (default 1). */\n speedRatio: number;\n /** Whether animation loops (default true). */\n loop: boolean;\n /** @internal Debug: node world matrices (numNodes × 16 floats, column-major). */\n readonly _debugWorldMat?: Float32Array;\n /** @internal Debug: node names. */\n readonly _debugNodeNames?: string[];\n}\n\n/**\n * Create a skeleton animation controller from parsed glTF animation data.\n * Returns a tick function that advances the animation and uploads bone matrices.\n */\nexport function createAnimationController(\n clip: AnimationClip,\n nodes: readonly NodeRest[],\n skeletons: readonly SkeletonBinding[],\n morphBindings: readonly MorphBinding[],\n nodeTargets?: readonly (AnimatedNodeTarget | undefined)[],\n excludedNodeIndices?: ReadonlySet<number>\n): AnimationController {\n const requiresEngine = skeletons.length > 0 || morphBindings.length > 0;\n const numNodes = nodes.length;\n\n // Plain node-TRS bindings: glTF translation/rotation/scale channels that target\n // a non-excluded node with a live scene node. These move node-animated meshes\n // (and their descendants) — without this, only skeleton/morph/pointer outputs\n // would be applied and node-animated meshes would stay frozen at their rest pose.\n // Excluded nodes are skin joints + skinned-mesh nodes and their ancestors. A\n // binding list is per-clip: only nodes THIS clip animates are kept, so untouched\n // nodes never needlessly dirty the scene. mask bits: 1 = translation, 2 = rotation,\n // 4 = scale.\n const nodeTrsBindings: { target: AnimatedNodeTarget; off: number; mask: number }[] = [];\n if (nodeTargets) {\n const maskByNode = new Map<number, number>();\n for (let ci = 0; ci < clip.channels.length; ci++) {\n const ch = clip.channels[ci]!;\n const bit = ch.path === PATH_TRANSLATION ? 1 : ch.path === PATH_ROTATION ? 2 : ch.path === PATH_SCALE ? 4 : 0;\n if (bit === 0) {\n continue;\n }\n const ni = ch.nodeIdx;\n if (ni < 0 || excludedNodeIndices?.has(ni) || !nodeTargets[ni]) {\n continue;\n }\n maskByNode.set(ni, (maskByNode.get(ni) ?? 0) | bit);\n }\n for (const [ni, mask] of maskByNode) {\n nodeTrsBindings.push({ target: nodeTargets[ni]!, off: ni * TRS_STRIDE, mask });\n }\n }\n\n // Pre-allocate scratch buffers (once)\n const currentTRS = new Float32Array(numNodes * TRS_STRIDE);\n const localMat = new Float32Array(numNodes * 16);\n const worldMat = new Float32Array(numNodes * 16);\n const topoOrder = computeTopoOrder(nodes);\n\n // Per-skeleton bone scratch\n const boneScratch = skeletons.map((s) => s.boneMatrices);\n\n // Per-morph-binding scratch for weight evaluation\n const morphBindingsByNode: (MorphBinding[] | undefined)[] = [];\n for (let morphIndex = 0; morphIndex < morphBindings.length; morphIndex++) {\n const mb = morphBindings[morphIndex]!;\n let arr = morphBindingsByNode[mb.nodeIdx];\n if (!arr) {\n arr = [];\n morphBindingsByNode[mb.nodeIdx] = arr;\n }\n arr.push(mb);\n }\n // Only write first 16 bytes (weights vec4) — count/texWidth/rowsPerBand are immutable\n const morphUploadF32 = new Float32Array(4);\n // Pointer-channel scratch (sized to largest registered pointer arity).\n // Current registered writers need at most 4 (quaternion/color4). Keep 16 for headroom.\n const pointerScratch = new Float32Array(16);\n\n let cachedEngine: EngineContext | undefined;\n\n const ctrl: AnimationController = {\n time: 0,\n playing: true,\n speedRatio: 1,\n loop: true,\n _debugWorldMat: worldMat,\n\n tick:\n clip.duration <= 0\n ? noopAnimationTick\n : (deltaMs: number, engine?: EngineContext): void => {\n if (engine) {\n cachedEngine = engine;\n }\n const activeEngine = engine ?? cachedEngine;\n if (requiresEngine && !activeEngine) {\n throw new Error(\"AnimationController.tick requires an EngineContext for skeleton or morph animation\");\n }\n const device = requiresEngine ? activeEngine!._device : null;\n\n if (ctrl.playing) {\n ctrl.time += (deltaMs / 1000) * ctrl.speedRatio;\n }\n\n // Always wrap/clamp — ensures externally-set time (goToFrame) is valid\n if (ctrl.loop) {\n ctrl.time %= clip.duration;\n if (ctrl.time < 0) {\n ctrl.time += clip.duration;\n }\n } else {\n ctrl.time = Math.min(Math.max(ctrl.time, 0), clip.duration);\n }\n const t = ctrl.time;\n\n // 1. Reset to rest-pose TRS\n for (let i = 0; i < numNodes; i++) {\n const n = nodes[i]!;\n const off = i * TRS_STRIDE;\n currentTRS[off + T_OFF] = n.tx;\n currentTRS[off + T_OFF + 1] = n.ty;\n currentTRS[off + T_OFF + 2] = n.tz;\n currentTRS[off + R_OFF] = n.rx;\n currentTRS[off + R_OFF + 1] = n.ry;\n currentTRS[off + R_OFF + 2] = n.rz;\n currentTRS[off + R_OFF + 3] = n.rw;\n currentTRS[off + S_OFF] = n.sx;\n currentTRS[off + S_OFF + 1] = n.sy;\n currentTRS[off + S_OFF + 2] = n.sz;\n }\n\n // 2. Evaluate animation channels → override TRS\n for (let channelIndex = 0; channelIndex < clip.channels.length; channelIndex++) {\n const ch = clip.channels[channelIndex]!;\n const sampler = clip.samplers[ch.samplerIdx]!;\n const base = ch.nodeIdx * TRS_STRIDE;\n switch (ch.path) {\n case PATH_TRANSLATION:\n evaluateSampler(sampler, t, 3, false, currentTRS, base + T_OFF);\n break;\n case PATH_ROTATION:\n evaluateSampler(sampler, t, 4, true, currentTRS, base + R_OFF);\n break;\n case PATH_SCALE:\n evaluateSampler(sampler, t, 3, false, currentTRS, base + S_OFF);\n break;\n case PATH_WEIGHTS: {\n // Evaluate morph weights and upload to all bindings for this node\n const bindings = morphBindingsByNode[ch.nodeIdx];\n if (bindings) {\n const tc = bindings[0]!.targetCount;\n morphUploadF32.fill(0);\n evaluateSampler(sampler, t, tc, false, morphUploadF32, 0);\n for (let bindingIndex = 0; bindingIndex < bindings.length; bindingIndex++) {\n const mb = bindings[bindingIndex]!;\n mb.weights.set(morphUploadF32);\n // Write only the weights vec4 (first 16 bytes); count/texWidth/rowsPerBand are immutable\n device!.queue.writeBuffer(mb.runtimeMorphTargets?.weightsBuffer ?? mb.weightsBuffer, 0, morphUploadF32.buffer, 0, 16);\n }\n }\n break;\n }\n case PATH_POINTER: {\n if (ch.pointerArity && ch.pointerWriter) {\n evaluateSampler(sampler, t, ch.pointerArity, ch.pointerQuaternion === true, pointerScratch, 0);\n ch.pointerWriter(pointerScratch, 0);\n }\n break;\n }\n }\n }\n\n // 2b. Apply plain node-TRS channels to the live scene graph so\n // node-animated meshes (and their descendants) move. Skeleton\n // joints + skinned-mesh chains are excluded (handled by the bone\n // path below). The skeleton path is independent: it reads `nodes`\n // and uploads bone textures, never the scene hierarchy.\n for (let bi = 0; bi < nodeTrsBindings.length; bi++) {\n const b = nodeTrsBindings[bi]!;\n const o = b.off;\n if (b.mask & 1) {\n b.target.position.set(currentTRS[o + T_OFF]!, currentTRS[o + T_OFF + 1]!, currentTRS[o + T_OFF + 2]!);\n }\n if (b.mask & 2) {\n b.target.rotationQuaternion.set(currentTRS[o + R_OFF]!, currentTRS[o + R_OFF + 1]!, currentTRS[o + R_OFF + 2]!, currentTRS[o + R_OFF + 3]!);\n }\n if (b.mask & 4) {\n b.target.scaling.set(currentTRS[o + S_OFF]!, currentTRS[o + S_OFF + 1]!, currentTRS[o + S_OFF + 2]!);\n }\n }\n\n // 3. Compute local → world matrices in topological order\n for (let idx = 0; idx < numNodes; idx++) {\n const nodeIdx = topoOrder[idx]!;\n const node = nodes[nodeIdx]!;\n const off = nodeIdx * TRS_STRIDE;\n if (node._matrix) {\n localMat.set(node._matrix, nodeIdx * 16);\n } else {\n mat4ComposeInto(\n localMat,\n nodeIdx * 16,\n currentTRS[off + T_OFF]!,\n currentTRS[off + T_OFF + 1]!,\n currentTRS[off + T_OFF + 2]!,\n currentTRS[off + R_OFF]!,\n currentTRS[off + R_OFF + 1]!,\n currentTRS[off + R_OFF + 2]!,\n currentTRS[off + R_OFF + 3]!,\n currentTRS[off + S_OFF]!,\n currentTRS[off + S_OFF + 1]!,\n currentTRS[off + S_OFF + 2]!\n );\n }\n\n const parentIdx = node.parentIdx;\n if (parentIdx >= 0) {\n mat4MultiplyInto(worldMat, nodeIdx * 16, worldMat, parentIdx * 16, localMat, nodeIdx * 16);\n } else {\n // Root node: pre-multiply RH→LH\n mat4MultiplyInto(worldMat, nodeIdx * 16, RH_TO_LH, 0, localMat, nodeIdx * 16);\n }\n }\n\n // 4. Compute bone matrices and upload to GPU\n for (let si = 0; si < skeletons.length; si++) {\n const skel = skeletons[si]!;\n const boneData = boneScratch[si]!;\n\n for (let bi = 0; bi < skel.boneCount; bi++) {\n const jointIdx = skel.jointNodes[bi]!;\n const ibmOff = bi * 16;\n // boneMatrix = invMeshWorld * jointWorld * IBM\n mat4MultiplyInto(_boneTmp, 0, skel.invMeshWorld, 0, worldMat, jointIdx * 16);\n mat4MultiplyInto(boneData, bi * 16, _boneTmp, 0, skel.inverseBindMatrices, ibmOff);\n }\n\n // Upload to GPU\n const texWidth = skel.boneCount * 4;\n device!.queue.writeTexture(\n { texture: skel.runtimeSkeleton?.boneTexture ?? skel.boneTexture },\n boneData.buffer,\n { bytesPerRow: texWidth * 16 },\n { width: texWidth, height: 1 }\n );\n }\n },\n };\n\n return ctrl;\n}\n\nfunction noopAnimationTick(): void {\n // Empty controller for zero-duration clips.\n}\n","// AnimationGroup — user-facing handle for a single animation clip.\n// Stored on scene.animationGroups[]. Pure state interface.\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { AnimationClip, AnimationSampler, GltfAnimationData, NodeRest, SkeletonBinding } from \"./types.js\";\nimport { PATH_POINTER, PATH_TRANSLATION, PATH_ROTATION, PATH_SCALE } from \"./types.js\";\nimport { createAnimationController } from \"../skeleton/skeleton-updater.js\";\nimport type { AnimationController } from \"../skeleton/skeleton-updater.js\";\n\nconst DEFAULT_FRAME_RATE = 60;\n\nexport interface AnimationPropertyRuntimeTrack {\n readonly sampler: AnimationSampler;\n readonly stride: number;\n readonly quaternion: boolean;\n readonly writer: (output: Float32Array, offset: number) => void;\n readonly mixTarget: object;\n readonly mixProperty: string;\n}\nexport type AnimationPropertyMixer = readonly [readonly AnimationPropertyRuntimeTrack[], number, number, number];\nexport type AnimationGltfMixer = readonly [AnimationClip, readonly NodeRest[], readonly SkeletonBinding[]];\nexport interface AnimationAdditiveMixer {\n readonly referenceTime: number;\n}\n\n/** User-facing animation group — one per animation clip. Pure state. */\nexport interface AnimationGroup {\n /** Name of this animation. */\n readonly name: string;\n /** Duration in seconds. */\n readonly duration: number;\n /** Frame rate used by goToFrame(). */\n readonly frameRate?: number;\n /** True if currently playing. */\n isPlaying: boolean;\n /** Current playback time in seconds. */\n currentFrame: number;\n /** Playback speed multiplier (default 1). */\n speedRatio: number;\n /** Whether animation loops (default true). */\n loopAnimation: boolean;\n /** Weighted contribution used by AnimationManager mixing (default 1). */\n weight: number;\n /** @internal Debug: internal animation controller. */\n readonly _ctrl?: AnimationController;\n /** @internal Manual property animation metadata used by the optional weighted mixer. */\n _propertyMixer?: AnimationPropertyMixer;\n /** @internal glTF skeleton metadata used by the optional weighted mixer. */\n _gltfMixer?: AnimationGltfMixer;\n /** @internal Additive animation metadata used by the optional blending mixer. */\n _additive?: AnimationAdditiveMixer;\n /** @internal Whether stop() was called (suppresses tickAnimation). */\n _stopped: boolean;\n}\n\n/** Start playing an animation group. */\nexport function playAnimation(group: AnimationGroup): void {\n group.isPlaying = true;\n group._stopped = false;\n}\n\n/** Pause playback of an animation group. */\nexport function pauseAnimation(group: AnimationGroup): void {\n group.isPlaying = false;\n}\n\n/** Stop playback and reset to frame 0. */\nexport function stopAnimation(group: AnimationGroup): void {\n group.isPlaying = false;\n group.currentFrame = 0;\n group._stopped = true;\n}\n\n/** Seek to a specific frame, apply the pose, and pause. */\nexport function goToFrame(group: AnimationGroup, frame: number, engine?: EngineContext): void {\n const ctrl = group._ctrl;\n group.currentFrame = frame / (group.frameRate || DEFAULT_FRAME_RATE);\n group.isPlaying = false;\n if (ctrl) {\n syncControllerFromGroup(group, ctrl);\n if (engine || !group._stopped || !group._gltfMixer) {\n ctrl.tick(0, engine);\n group.currentFrame = ctrl.time;\n }\n }\n}\n\n/** @internal Advance animation by deltaMs. Called by the engine each frame. */\nexport function tickAnimation(group: AnimationGroup, deltaMs: number, engine?: EngineContext): void {\n if (!group._stopped && group._ctrl) {\n syncControllerFromGroup(group, group._ctrl);\n group._ctrl.tick(deltaMs, engine);\n group.currentFrame = group._ctrl.time;\n }\n}\n\nfunction syncControllerFromGroup(group: AnimationGroup, ctrl: AnimationController): void {\n ctrl.time = group.currentFrame;\n ctrl.playing = group.isPlaying;\n ctrl.speedRatio = group.speedRatio;\n ctrl.loop = group.loopAnimation;\n}\n\n/** Create AnimationGroup(s) from parsed glTF animation data.\n * Returns one group per animation clip. */\nexport function createAnimationGroups(animData: GltfAnimationData): AnimationGroup[] {\n const { clips, nodes, skeletons, morphBindings, nodeTargets, excludedNodeIndices } = animData;\n const hasPointer = clips.some((c) => c.channels.some((ch) => ch.path === PATH_POINTER));\n const hasNodeWriteback = clips.some((c) =>\n c.channels.some(\n (ch) =>\n (ch.path === PATH_TRANSLATION || ch.path === PATH_ROTATION || ch.path === PATH_SCALE) &&\n ch.nodeIdx >= 0 &&\n !excludedNodeIndices.has(ch.nodeIdx) &&\n !!nodeTargets[ch.nodeIdx]\n )\n );\n if (clips.length === 0 || (skeletons.length === 0 && morphBindings.length === 0 && !hasPointer && !hasNodeWriteback)) {\n return [];\n }\n\n return clips.map((clip, clipIndex) => {\n const ctrl: AnimationController = createAnimationController(clip, nodes, skeletons, morphBindings, nodeTargets, excludedNodeIndices);\n const group: AnimationGroup = {\n name: clip.name || `animation_${clipIndex}`,\n duration: clip.duration,\n frameRate: clip.frameRate || DEFAULT_FRAME_RATE,\n isPlaying: true,\n currentFrame: 0,\n speedRatio: 1,\n loopAnimation: true,\n weight: 1,\n _ctrl: ctrl,\n _stopped: false,\n };\n if (skeletons[0]) {\n group._gltfMixer = [clip, nodes, skeletons];\n }\n return group;\n });\n}\n","import type { AnimationGroup } from \"./animation-group.js\";\n\n/** Set the weighted contribution for an animation group. Feature-specific mixers remain explicit opt-ins. */\nexport function setAnimationWeight(group: AnimationGroup, weight: number): void {\n if (!Number.isFinite(weight) || weight < 0 || weight > 1) {\n throw new Error(`Animation weight must be a finite number between 0 and 1, got ${weight}`);\n }\n group.weight = weight;\n}\n","import type { EngineContext } from \"../engine/engine.js\";\n\n/** A unit of per-frame animation work owned by an {@link AnimationManager}. */\nexport interface AnimationTask {\n /** @internal */\n readonly _entityType: \"animation-task\";\n active: boolean;\n /** @internal */\n _update: AnimationTaskUpdate;\n /** @internal */\n _dispose?: (manager: AnimationManager) => void;\n /** @internal */\n _category?: string;\n /** @internal */\n _owner?: AnimationManager;\n}\n\n/** Callback invoked each tick to advance a single {@link AnimationTask} by `deltaMs` milliseconds. */\nexport type AnimationTaskUpdate = (manager: AnimationManager, deltaMs: number, task: AnimationTask) => void;\n/** Handler that drives all tasks of a given category in one pass; returns true if it handled that category this tick. */\nexport type AnimationTaskCategoryHandler = (manager: AnimationManager, deltaMs: number) => boolean;\n\n/** Options for {@link createAnimationTask}. */\nexport interface AnimationTaskOptions {\n readonly category?: string;\n /** Called when the task is removed from its manager, allowing it to release any owned resources. */\n readonly dispose?: (manager: AnimationManager) => void;\n}\n\n/** Options for {@link createAnimationManager}. */\nexport interface AnimationManagerOptions {\n readonly engine?: EngineContext;\n readonly fixedDeltaMs?: number;\n /** Called after each autonomous tick with the step (in ms) that was applied. */\n readonly onUpdate?: (deltaMs: number) => void;\n}\n\n/** Owns a set of {@link AnimationTask}s and ticks them, either manually or via its own requestAnimationFrame loop. */\nexport interface AnimationManager {\n animations: AnimationTask[];\n fixedDeltaMs: number;\n running: boolean;\n readonly engine?: EngineContext;\n /** Called after each autonomous tick with the step (in ms) that was applied. */\n readonly onUpdate?: (deltaMs: number) => void;\n /** @internal Optional feature updaters installed by category-specific adapters. */\n _taskCategory?: string;\n /** @internal */\n _taskCategoryHandler?: AnimationTaskCategoryHandler;\n /** @internal */\n _rafId: number;\n /** @internal */\n _lastTime: number;\n}\n\n/** Creates an animation task that invokes `update` each tick.\n * @param update - Callback that advances the task by the frame delta.\n * @param options - Optional category and dispose hook.\n * @returns The new, active animation task. */\nexport function createAnimationTask(update: AnimationTaskUpdate, options?: AnimationTaskOptions): AnimationTask {\n return {\n _entityType: \"animation-task\",\n active: true,\n _update: update,\n _category: options?.category,\n _dispose: options?.dispose,\n };\n}\n\n/** Creates an animation manager with no tasks attached.\n * @param options - Optional engine, fixed timestep, and update callback.\n * @returns The new manager. */\nexport function createAnimationManager(options?: AnimationManagerOptions): AnimationManager {\n return {\n animations: [],\n fixedDeltaMs: options?.fixedDeltaMs ?? 0,\n running: false,\n engine: options?.engine,\n onUpdate: options?.onUpdate,\n _rafId: 0,\n _lastTime: 0,\n };\n}\n\n/** Registers a single category `handler` on `manager` that drives every task tagged with `category` in one pass.\n * @throws If `category` is empty. */\nexport function setAnimationTaskCategoryHandler(manager: AnimationManager, category: string, handler: AnimationTaskCategoryHandler): void {\n if (!category) {\n throw new Error(\"Animation task category is required.\");\n }\n manager._taskCategory = category;\n manager._taskCategoryHandler = handler;\n}\n\n/** Attaches `task` to `manager` and marks it active.\n * @throws If the task is already attached to a different manager. */\nexport function addAnimationTask(manager: AnimationManager, task: AnimationTask): void {\n const owner = task._owner;\n if (owner === manager) {\n return;\n }\n if (owner) {\n throw new Error(\"AnimationTask is already attached to another AnimationManager\");\n }\n task.active = true;\n task._owner = manager;\n manager.animations.push(task);\n}\n\n/** Detaches `task` from `manager`, marking it inactive and running its dispose hook if it was attached. */\nexport function removeAnimationTask(manager: AnimationManager, task: AnimationTask): void {\n const index = manager.animations.indexOf(task);\n if (index !== -1) {\n removeAnimationTaskAt(manager, index);\n } else if (task._owner === manager) {\n task._owner = undefined;\n task.active = false;\n }\n}\n\n/** Removes and disposes every task attached to `manager`. */\nexport function clearAnimationManager(manager: AnimationManager): void {\n while (manager.animations.length > 0) {\n removeAnimationTaskAt(manager, manager.animations.length - 1);\n }\n}\n\n/** Advances every active task by `deltaMs` (or by `fixedDeltaMs` when set), running the category handler first.\n * Ignores non-finite or negative steps. */\nexport function updateAnimationManager(manager: AnimationManager, deltaMs: number): void {\n const step = manager.fixedDeltaMs > 0 ? manager.fixedDeltaMs : deltaMs;\n if (!Number.isFinite(step) || step < 0) {\n return;\n }\n const handledCategory = manager._taskCategoryHandler?.(manager, step) ? manager._taskCategory : undefined;\n // Snapshot the list so a task's _update callback can remove itself or other\n // tasks (via removeAnimationTask) without shifting unvisited tasks out of the\n // iteration. Removed tasks are marked inactive and skipped below.\n const tasks = manager.animations.slice();\n for (let index = 0; index < tasks.length; index++) {\n const task = tasks[index]!;\n if (!task.active || (task._category && task._category === handledCategory)) {\n continue;\n }\n task._update(manager, step, task);\n }\n}\n\n/** Starts the manager's autonomous requestAnimationFrame loop. No-op if already running.\n * @throws If `requestAnimationFrame` is unavailable in the host environment. */\nexport function startAnimationManager(manager: AnimationManager): void {\n if (manager.running) {\n return;\n }\n if (typeof requestAnimationFrame !== \"function\" || typeof cancelAnimationFrame !== \"function\") {\n throw new Error(\"AnimationManager autonomous mode requires requestAnimationFrame\");\n }\n manager.running = true;\n manager._lastTime = 0;\n const tick = (now: number): void => {\n if (!manager.running) {\n return;\n }\n const deltaMs = manager._lastTime > 0 ? now - manager._lastTime : 0;\n manager._lastTime = now;\n const step = manager.fixedDeltaMs > 0 ? manager.fixedDeltaMs : deltaMs;\n updateAnimationManager(manager, deltaMs);\n manager.onUpdate?.(step);\n manager._rafId = requestAnimationFrame(tick);\n };\n manager._rafId = requestAnimationFrame(tick);\n}\n\n/** Stops the manager's autonomous requestAnimationFrame loop. No-op if not running. */\nexport function stopAnimationManager(manager: AnimationManager): void {\n if (!manager.running) {\n return;\n }\n cancelAnimationFrame(manager._rafId);\n manager._rafId = 0;\n manager._lastTime = 0;\n manager.running = false;\n}\n\nfunction removeAnimationTaskAt(manager: AnimationManager, index: number): void {\n const task = manager.animations[index]!;\n manager.animations.splice(index, 1);\n if (task._owner === manager) {\n task._owner = undefined;\n }\n task.active = false;\n task._dispose?.(manager);\n}\n","import { tickAnimation } from \"./animation-group.js\";\nimport type { AnimationGroup } from \"./animation-group.js\";\nimport { addAnimationTask, createAnimationTask, removeAnimationTask } from \"./animation-manager.js\";\nimport type { AnimationManager, AnimationTask } from \"./animation-manager.js\";\n\nexport const ANIMATION_GROUP_TASK_CATEGORY = \"animation-group\";\n\ninterface AnimationGroupTaskManager extends AnimationManager {\n _animationGroups?: AnimationGroup[];\n}\n\ninterface AnimationGroupTaskGroup extends AnimationGroup {\n _animationManager?: AnimationManager;\n _animationTask?: AnimationTask;\n}\n\nfunction getMutableAnimationGroups(manager: AnimationManager): AnimationGroup[] {\n const managerInternal = manager as AnimationGroupTaskManager;\n let groups = managerInternal._animationGroups;\n if (!groups) {\n groups = [];\n managerInternal._animationGroups = groups;\n }\n return groups;\n}\n\n/** Returns the animation groups currently attached to `manager`, or an empty array if none. */\nexport function getAnimationGroups(manager: AnimationManager): readonly AnimationGroup[] {\n return (manager as AnimationGroupTaskManager)._animationGroups ?? [];\n}\n\nexport function getAnimationGroupOwner(group: AnimationGroup): AnimationManager | undefined {\n return (group as AnimationGroupTaskGroup)._animationManager;\n}\n\n/** Attaches `group` to `manager` so it is ticked each update, creating its backing animation task on first use.\n * @param manager - Animation manager that will own and drive the group.\n * @param group - Animation group to attach.\n * @throws If the group is already attached to a different manager. */\nexport function addAnimationGroup(manager: AnimationManager, group: AnimationGroup): void {\n const groupInternal = group as AnimationGroupTaskGroup;\n const owner = groupInternal._animationManager;\n if (owner && owner !== manager) {\n throw new Error(`AnimationGroup \"${group.name}\" is already attached to another AnimationManager`);\n }\n if (owner === manager) {\n return;\n }\n const task =\n groupInternal._animationTask ??\n createAnimationTask(\n (taskManager, deltaMs) => {\n tickAnimation(group, deltaMs, taskManager.engine);\n },\n {\n category: ANIMATION_GROUP_TASK_CATEGORY,\n dispose: (ownerManager) => {\n const groups = (ownerManager as AnimationGroupTaskManager)._animationGroups;\n const index = groups?.indexOf(group) ?? -1;\n if (groups && index !== -1) {\n groups.splice(index, 1);\n }\n if (groupInternal._animationManager === ownerManager) {\n groupInternal._animationManager = undefined;\n }\n },\n }\n );\n getMutableAnimationGroups(manager).push(group);\n groupInternal._animationManager = manager;\n groupInternal._animationTask = task;\n addAnimationTask(manager, task);\n}\n\n/** Attaches each group in `groups` to `manager` via {@link addAnimationGroup}. */\nexport function addAnimationGroups(manager: AnimationManager, groups: readonly AnimationGroup[]): void {\n for (const group of groups) {\n addAnimationGroup(manager, group);\n }\n}\n\n/** Detaches `group` from `manager`, removing its animation task so it is no longer ticked. */\nexport function removeAnimationGroup(manager: AnimationManager, group: AnimationGroup): void {\n const groupInternal = group as AnimationGroupTaskGroup;\n const task = groupInternal._animationTask;\n if (task && groupInternal._animationManager === manager) {\n removeAnimationTask(manager, task);\n return;\n }\n const groups = (manager as AnimationGroupTaskManager)._animationGroups;\n const index = groups?.indexOf(group) ?? -1;\n if (groups && index !== -1) {\n groups.splice(index, 1);\n }\n if (groupInternal._animationManager === manager) {\n groupInternal._animationManager = undefined;\n }\n}\n","import { tickAnimation } from \"./animation-group.js\";\nimport type { AnimationGroup, AnimationPropertyMixer, AnimationPropertyRuntimeTrack } from \"./animation-group.js\";\nimport { ANIMATION_GROUP_TASK_CATEGORY, getAnimationGroups } from \"./animation-group-task.js\";\nimport { setAnimationTaskCategoryHandler } from \"./animation-manager.js\";\nimport type { AnimationManager } from \"./animation-manager.js\";\nimport { evaluateSampler } from \"./evaluate.js\";\n\nconst MIX_TRACKS = 0;\nconst MIX_FROM = 1;\nconst MIX_TO = 2;\nconst MIX_DURATION = 3;\n\ninterface WeightedPointerBucket {\n readonly target: object;\n readonly property: string;\n readonly values: Float32Array;\n writer: (output: Float32Array, offset: number) => void;\n arity: number;\n quaternion: boolean;\n contested: boolean;\n active: boolean;\n hasReference: boolean;\n refX: number;\n refY: number;\n refZ: number;\n refW: number;\n}\n\ninterface WeightedPointerScratch {\n readonly buckets: WeightedPointerBucket[];\n readonly sample: Float32Array;\n readonly fades: AnimationWeightFade[];\n}\n\nlet scratchByManager: WeakMap<AnimationManager, WeightedPointerScratch> | undefined;\n\ninterface AnimationWeightFade {\n readonly group: AnimationGroup;\n readonly from: number;\n readonly to: number;\n readonly durationMs: number;\n elapsedMs: number;\n}\n\n/** Options for {@link fadeAnimationWeight}. */\nexport interface FadeAnimationWeightOptions {\n readonly to: number;\n readonly durationMs: number;\n readonly from?: number;\n}\n\n/** Options for {@link crossFadeAnimationGroups}. */\nexport interface CrossFadeAnimationGroupsOptions {\n readonly durationMs: number;\n readonly toWeight?: number;\n}\n\n/** Enables weighted property-animation blending on `manager` by registering its category handler. */\nexport function enablePropertyAnimationBlending(manager: AnimationManager): void {\n setAnimationTaskCategoryHandler(manager, ANIMATION_GROUP_TASK_CATEGORY, updateWeightedPointerAnimations);\n}\n\nfunction getScratch(manager: AnimationManager): WeightedPointerScratch {\n scratchByManager ??= new WeakMap();\n let scratch = scratchByManager.get(manager);\n if (!scratch) {\n scratch = {\n buckets: [],\n sample: new Float32Array(16),\n fades: [],\n };\n scratchByManager.set(manager, scratch);\n }\n return scratch;\n}\n\n/** Animates `group`'s blend weight toward `options.to` over `options.durationMs`, enabling blending on `manager`.\n * @throws If `to`/`from` are outside `[0, 1]` or the duration is not a finite positive number. */\nexport function fadeAnimationWeight(manager: AnimationManager, group: AnimationGroup, options: FadeAnimationWeightOptions): void {\n const to = validateWeight(options.to);\n const from = options.from === undefined ? group.weight : validateWeight(options.from);\n if (!(options.durationMs > 0) || !Number.isFinite(options.durationMs)) {\n throw new Error(`Animation weight fade duration must be a finite positive number, got ${options.durationMs}`);\n }\n\n enablePropertyAnimationBlending(manager);\n group.weight = from;\n const scratch = getScratch(manager);\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n if (scratch.fades[i]!.group === group) {\n scratch.fades.splice(i, 1);\n }\n }\n scratch.fades.push({ group, from, to, durationMs: options.durationMs, elapsedMs: 0 });\n}\n\n/** Cross-fades from `fromGroup` to `toGroup`, fading the first to weight 0 and the second to `options.toWeight` (default 1). */\nexport function crossFadeAnimationGroups(manager: AnimationManager, fromGroup: AnimationGroup, toGroup: AnimationGroup, options: CrossFadeAnimationGroupsOptions): void {\n const toWeight = validateWeight(options.toWeight ?? 1);\n fadeAnimationWeight(manager, fromGroup, { to: 0, durationMs: options.durationMs });\n fadeAnimationWeight(manager, toGroup, { to: toWeight, durationMs: options.durationMs });\n}\n\nfunction updateWeightedPointerAnimations(manager: AnimationManager, deltaMs: number): boolean {\n const scratch = getScratch(manager);\n updateFades(scratch, deltaMs);\n let contestedCount = 0;\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n bucket.contested = false;\n bucket.active = false;\n bucket.hasReference = false;\n bucket.values.fill(0);\n }\n\n const groups = getAnimationGroups(manager);\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n const mixer = group._propertyMixer;\n if (group._stopped || group.weight === 1 || !mixer) {\n continue;\n }\n const tracks = mixer[MIX_TRACKS];\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n bucket.contested = true;\n contestedCount++;\n }\n }\n }\n\n if (contestedCount === 0) {\n return false;\n }\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n if (group._stopped) {\n continue;\n }\n\n const mixer = group._propertyMixer;\n const tracks = mixer?.[MIX_TRACKS];\n if (!tracks) {\n tickAnimation(group, deltaMs, manager.engine);\n continue;\n }\n\n const t = advancePropertyGroupTime(group, mixer, deltaMs);\n const weight = group.weight;\n if (weight === 0) {\n continue;\n }\n\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n evaluateSampler(track.sampler, t, track.stride, track.quaternion, scratch.sample, 0);\n const bucket = getTrackBucket(scratch.buckets, track);\n if (!bucket.contested) {\n track.writer(scratch.sample, 0);\n continue;\n }\n if (weight !== 0) {\n accumulateWeightedTrack(bucket, track, scratch.sample, weight);\n }\n }\n }\n\n for (let bucketIndex = 0; bucketIndex < scratch.buckets.length; bucketIndex++) {\n const bucket = scratch.buckets[bucketIndex]!;\n if (!bucket.active) {\n continue;\n }\n if (bucket.quaternion && bucket.arity === 4) {\n normalizeQuaternion(bucket.values);\n }\n bucket.writer(bucket.values, 0);\n }\n\n return true;\n}\n\nfunction updateFades(scratch: WeightedPointerScratch, deltaMs: number): void {\n for (let i = scratch.fades.length - 1; i >= 0; i--) {\n const fade = scratch.fades[i]!;\n fade.elapsedMs = Math.min(fade.durationMs, fade.elapsedMs + Math.max(0, deltaMs));\n const t = fade.elapsedMs / fade.durationMs;\n fade.group.weight = fade.from + (fade.to - fade.from) * t;\n if (fade.elapsedMs >= fade.durationMs) {\n fade.group.weight = fade.to;\n scratch.fades.splice(i, 1);\n }\n }\n}\n\nfunction validateWeight(weight: number): number {\n if (!Number.isFinite(weight) || weight < 0 || weight > 1) {\n throw new Error(`Animation weight must be a finite number between 0 and 1, got ${weight}`);\n }\n return weight;\n}\n\nfunction advancePropertyGroupTime(group: AnimationGroup, mixer: AnimationPropertyMixer, deltaMs: number): number {\n if (group.isPlaying) {\n group.currentFrame += (deltaMs / 1000) * group.speedRatio;\n }\n\n const fromTime = Math.max(0, Math.min(mixer[MIX_FROM], mixer[MIX_DURATION]));\n const toTime = mixer[MIX_TO] > fromTime ? Math.min(mixer[MIX_TO], mixer[MIX_DURATION]) : mixer[MIX_DURATION];\n const duration = Math.max(0, toTime - fromTime);\n if (duration <= 0) {\n return fromTime;\n }\n\n if (group.loopAnimation) {\n group.currentFrame = fromTime + ((group.currentFrame - fromTime) % duration);\n if (group.currentFrame < fromTime) {\n group.currentFrame += duration;\n }\n } else {\n group.currentFrame = Math.min(Math.max(group.currentFrame, fromTime), toTime);\n }\n return group.currentFrame;\n}\n\nfunction getTrackBucket(buckets: WeightedPointerBucket[], track: AnimationPropertyRuntimeTrack): WeightedPointerBucket {\n const arity = track.stride;\n for (let bucketIndex = 0; bucketIndex < buckets.length; bucketIndex++) {\n const candidate = buckets[bucketIndex]!;\n if (candidate.target === track.mixTarget && candidate.property === track.mixProperty) {\n if (candidate.arity !== arity) {\n throw new Error(\"Weighted animation channels for the same property must use the same value size\");\n }\n candidate.writer = track.writer;\n candidate.quaternion = track.quaternion;\n return candidate;\n }\n }\n\n const bucket: WeightedPointerBucket = {\n target: track.mixTarget,\n property: track.mixProperty,\n values: new Float32Array(arity),\n writer: track.writer,\n arity,\n quaternion: track.quaternion,\n contested: false,\n active: false,\n hasReference: false,\n refX: 0,\n refY: 0,\n refZ: 0,\n refW: 1,\n };\n buckets.push(bucket);\n return bucket;\n}\n\nfunction accumulateWeightedTrack(bucket: WeightedPointerBucket, track: AnimationPropertyRuntimeTrack, sample: Float32Array, weight: number): void {\n bucket.active = true;\n\n let sign = 1;\n if (bucket.quaternion && track.stride === 4) {\n if (!bucket.hasReference) {\n bucket.refX = sample[0]!;\n bucket.refY = sample[1]!;\n bucket.refZ = sample[2]!;\n bucket.refW = sample[3]!;\n bucket.hasReference = true;\n } else {\n const dot = bucket.refX * sample[0]! + bucket.refY * sample[1]! + bucket.refZ * sample[2]! + bucket.refW * sample[3]!;\n sign = dot < 0 ? -1 : 1;\n }\n }\n\n for (let i = 0; i < track.stride; i++) {\n bucket.values[i] = bucket.values[i]! + sample[i]! * weight * sign;\n }\n}\n\nfunction normalizeQuaternion(values: Float32Array): void {\n const x = values[0]!;\n const y = values[1]!;\n const z = values[2]!;\n const w = values[3]!;\n const lenSq = x * x + y * y + z * z + w * w;\n if (lenSq > 0) {\n const inv = 1 / Math.sqrt(lenSq);\n values[0] = x * inv;\n values[1] = y * inv;\n values[2] = z * inv;\n values[3] = w * inv;\n }\n}\n","import { tickAnimation } from \"./animation-group.js\";\nimport type { AnimationGltfMixer, AnimationGroup } from \"./animation-group.js\";\nimport { ANIMATION_GROUP_TASK_CATEGORY, getAnimationGroupOwner, getAnimationGroups } from \"./animation-group-task.js\";\nimport { setAnimationTaskCategoryHandler } from \"./animation-manager.js\";\nimport type { AnimationManager } from \"./animation-manager.js\";\nimport type { NodeRest, SkeletonBinding } from \"./types.js\";\nimport { PATH_ROTATION, PATH_SCALE, PATH_TRANSLATION } from \"./types.js\";\nimport { evaluateSampler } from \"./evaluate.js\";\nimport { mat4ComposeInto } from \"../math/mat4-compose-into.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\n\nconst GLTF_CLIP = 0;\nconst GLTF_NODES = 1;\nconst GLTF_SKELETONS = 2;\nconst TRS_STRIDE = 12;\nconst T_OFF = 0;\nconst R_OFF = 3;\nconst S_OFF = 7;\n\n// RH->LH root transform (same as skeleton-updater.ts)\n// prettier-ignore\nconst RH_TO_LH = new Float32Array([-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\n\nconst _boneTmp = new Float32Array(16);\n\ninterface WeightedGltfTarget {\n readonly nodes: readonly NodeRest[];\n readonly skeletons: readonly SkeletonBinding[];\n readonly trs: Float32Array;\n readonly localMat: Float32Array;\n readonly worldMat: Float32Array;\n readonly topoOrder: Int32Array;\n readonly tWeight: Float32Array;\n readonly rWeight: Float32Array;\n readonly sWeight: Float32Array;\n active: boolean;\n}\n\ninterface WeightedGltfScratch {\n readonly keys: Set<object>;\n readonly targets: Map<object, WeightedGltfTarget>;\n readonly sample: Float32Array;\n readonly reference: Float32Array;\n readonly delta: Float32Array;\n}\n\nlet scratchByManager: WeakMap<AnimationManager, WeightedGltfScratch> | undefined;\n\n/** Options for {@link setAnimationAdditive}, selecting the reference pose subtracted from an additive animation. */\nexport interface AnimationAdditiveOptions {\n readonly referenceFrame?: number;\n readonly referenceTime?: number;\n}\n\n/** Enable advanced animation blending for a manager. Kept opt-in so manual-only weights do not pay for skeletal mixing code. */\nexport function enableAnimationBlending(manager: AnimationManager): void {\n setAnimationTaskCategoryHandler(manager, ANIMATION_GROUP_TASK_CATEGORY, updateWeightedGltfAnimations);\n}\n\n/** Mark an animation group as additive. Reference defaults to frame 0, matching Babylon.js MakeAnimationAdditive. */\nexport function setAnimationAdditive(group: AnimationGroup, options?: AnimationAdditiveOptions): void {\n if (options?.referenceFrame !== undefined && options.referenceTime !== undefined) {\n throw new Error(\"Additive animation reference must use either referenceFrame or referenceTime, not both\");\n }\n const referenceTime = options?.referenceTime ?? (options?.referenceFrame ?? 0) / (group.frameRate || 60);\n if (!Number.isFinite(referenceTime) || referenceTime < 0) {\n throw new Error(`Additive animation reference time must be a finite non-negative number, got ${referenceTime}`);\n }\n group._additive = { referenceTime };\n const owner = getAnimationGroupOwner(group);\n if (owner) {\n enableAnimationBlending(owner);\n }\n}\n\nfunction getScratch(manager: AnimationManager): WeightedGltfScratch {\n scratchByManager ??= new WeakMap();\n let scratch = scratchByManager.get(manager);\n if (!scratch) {\n scratch = {\n keys: new Set<object>(),\n targets: new Map<object, WeightedGltfTarget>(),\n sample: new Float32Array(16),\n reference: new Float32Array(16),\n delta: new Float32Array(16),\n };\n scratchByManager.set(manager, scratch);\n }\n return scratch;\n}\n\nfunction updateWeightedGltfAnimations(manager: AnimationManager, deltaMs: number): boolean {\n const scratch = getScratch(manager);\n const keys = scratch.keys;\n keys.clear();\n\n const groups = getAnimationGroups(manager);\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n const mixer = group._gltfMixer;\n if (group._stopped || !mixer || (group.weight === 1 && !group._additive)) {\n continue;\n }\n keys.add(mixer[GLTF_NODES]);\n }\n\n if (keys.size === 0) {\n return false;\n }\n\n scratch.targets.forEach(resetWeightedGltfTarget);\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n if (group._stopped) {\n continue;\n }\n\n const mixer = group._gltfMixer;\n if (mixer && keys.has(mixer[GLTF_NODES])) {\n if (group._additive) {\n getTarget(scratch, mixer).active = true;\n advanceGroupTime(group, mixer, deltaMs);\n } else {\n accumulateGroup(manager, scratch, group, mixer, deltaMs);\n }\n continue;\n }\n\n tickAnimation(group, deltaMs, manager.engine);\n }\n\n for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {\n const group = groups[groupIndex]!;\n const mixer = group._gltfMixer;\n if (!group._stopped && group._additive && mixer && keys.has(mixer[GLTF_NODES])) {\n accumulateAdditiveGroup(scratch, group, mixer);\n }\n }\n\n scratch.targets.forEach((target, key) => {\n if (target.active && keys.has(key)) {\n uploadTarget(manager, target);\n }\n });\n\n return true;\n}\n\nfunction resetWeightedGltfTarget(target: WeightedGltfTarget): void {\n target.active = false;\n target.tWeight.fill(0);\n target.rWeight.fill(0);\n target.sWeight.fill(0);\n resetTarget(target);\n}\n\nfunction getTarget(scratch: WeightedGltfScratch, mixer: AnimationGltfMixer): WeightedGltfTarget {\n const nodes = mixer[GLTF_NODES];\n let target = scratch.targets.get(nodes);\n if (!target) {\n const numNodes = nodes.length;\n target = {\n nodes,\n skeletons: mixer[GLTF_SKELETONS],\n trs: new Float32Array(numNodes * TRS_STRIDE),\n localMat: new Float32Array(numNodes * 16),\n worldMat: new Float32Array(numNodes * 16),\n topoOrder: computeTopoOrder(nodes),\n tWeight: new Float32Array(numNodes),\n rWeight: new Float32Array(numNodes),\n sWeight: new Float32Array(numNodes),\n active: false,\n };\n scratch.targets.set(nodes, target);\n }\n return target;\n}\n\nfunction resetTarget(target: WeightedGltfTarget): void {\n const { nodes, trs } = target;\n for (let i = 0; i < nodes.length; i++) {\n const n = nodes[i]!;\n const off = i * TRS_STRIDE;\n trs[off + T_OFF] = n.tx;\n trs[off + T_OFF + 1] = n.ty;\n trs[off + T_OFF + 2] = n.tz;\n trs[off + R_OFF] = n.rx;\n trs[off + R_OFF + 1] = n.ry;\n trs[off + R_OFF + 2] = n.rz;\n trs[off + R_OFF + 3] = n.rw;\n trs[off + S_OFF] = n.sx;\n trs[off + S_OFF + 1] = n.sy;\n trs[off + S_OFF + 2] = n.sz;\n }\n}\n\nfunction accumulateAdditiveGroup(scratch: WeightedGltfScratch, group: AnimationGroup, mixer: AnimationGltfMixer): void {\n const additive = group._additive;\n const weight = group.weight;\n if (!additive || weight === 0) {\n return;\n }\n\n const target = getTarget(scratch, mixer);\n const clip = mixer[GLTF_CLIP];\n const t = group.currentFrame;\n for (let channelIndex = 0; channelIndex < clip.channels.length; channelIndex++) {\n const ch = clip.channels[channelIndex]!;\n const sampler = clip.samplers[ch.samplerIdx]!;\n const nodeIdx = ch.nodeIdx;\n const base = nodeIdx * TRS_STRIDE;\n switch (ch.path) {\n case PATH_TRANSLATION:\n evaluateSampler(sampler, t, 3, false, scratch.sample, 0);\n evaluateSampler(sampler, additive.referenceTime, 3, false, scratch.reference, 0);\n target.trs[base + T_OFF] = target.trs[base + T_OFF]! + (scratch.sample[0]! - scratch.reference[0]!) * weight;\n target.trs[base + T_OFF + 1] = target.trs[base + T_OFF + 1]! + (scratch.sample[1]! - scratch.reference[1]!) * weight;\n target.trs[base + T_OFF + 2] = target.trs[base + T_OFF + 2]! + (scratch.sample[2]! - scratch.reference[2]!) * weight;\n break;\n case PATH_SCALE:\n evaluateSampler(sampler, t, 3, false, scratch.sample, 0);\n evaluateSampler(sampler, additive.referenceTime, 3, false, scratch.reference, 0);\n target.trs[base + S_OFF] = target.trs[base + S_OFF]! + (scratch.sample[0]! - scratch.reference[0]!) * weight;\n target.trs[base + S_OFF + 1] = target.trs[base + S_OFF + 1]! + (scratch.sample[1]! - scratch.reference[1]!) * weight;\n target.trs[base + S_OFF + 2] = target.trs[base + S_OFF + 2]! + (scratch.sample[2]! - scratch.reference[2]!) * weight;\n break;\n case PATH_ROTATION:\n evaluateSampler(sampler, t, 4, true, scratch.sample, 0);\n evaluateSampler(sampler, additive.referenceTime, 4, true, scratch.reference, 0);\n quatRefInverseTimesSample(scratch.delta, scratch.reference, scratch.sample);\n applyAdditiveQuaternion(target.trs, base + R_OFF, scratch.delta, weight);\n break;\n }\n }\n}\n\nfunction accumulateGroup(manager: AnimationManager, scratch: WeightedGltfScratch, group: AnimationGroup, mixer: AnimationGltfMixer, deltaMs: number): void {\n if (!manager.engine) {\n throw new Error(\"Weighted glTF animation requires an AnimationManager engine\");\n }\n\n const target = getTarget(scratch, mixer);\n const t = advanceGroupTime(group, mixer, deltaMs);\n const weight = group.weight;\n target.active = true;\n if (weight === 0) {\n return;\n }\n\n const clip = mixer[GLTF_CLIP];\n for (let channelIndex = 0; channelIndex < clip.channels.length; channelIndex++) {\n const ch = clip.channels[channelIndex]!;\n const sampler = clip.samplers[ch.samplerIdx]!;\n const nodeIdx = ch.nodeIdx;\n const base = nodeIdx * TRS_STRIDE;\n switch (ch.path) {\n case PATH_TRANSLATION:\n evaluateSampler(sampler, t, 3, false, scratch.sample, 0);\n if (target.tWeight[nodeIdx] === 0) {\n target.trs[base + T_OFF] = 0;\n target.trs[base + T_OFF + 1] = 0;\n target.trs[base + T_OFF + 2] = 0;\n }\n target.trs[base + T_OFF] = target.trs[base + T_OFF]! + scratch.sample[0]! * weight;\n target.trs[base + T_OFF + 1] = target.trs[base + T_OFF + 1]! + scratch.sample[1]! * weight;\n target.trs[base + T_OFF + 2] = target.trs[base + T_OFF + 2]! + scratch.sample[2]! * weight;\n target.tWeight[nodeIdx] = target.tWeight[nodeIdx]! + weight;\n break;\n case PATH_SCALE:\n evaluateSampler(sampler, t, 3, false, scratch.sample, 0);\n if (target.sWeight[nodeIdx] === 0) {\n target.trs[base + S_OFF] = 0;\n target.trs[base + S_OFF + 1] = 0;\n target.trs[base + S_OFF + 2] = 0;\n }\n target.trs[base + S_OFF] = target.trs[base + S_OFF]! + scratch.sample[0]! * weight;\n target.trs[base + S_OFF + 1] = target.trs[base + S_OFF + 1]! + scratch.sample[1]! * weight;\n target.trs[base + S_OFF + 2] = target.trs[base + S_OFF + 2]! + scratch.sample[2]! * weight;\n target.sWeight[nodeIdx] = target.sWeight[nodeIdx]! + weight;\n break;\n case PATH_ROTATION: {\n evaluateSampler(sampler, t, 4, true, scratch.sample, 0);\n if (target.rWeight[nodeIdx] === 0) {\n target.trs[base + R_OFF] = scratch.sample[0]!;\n target.trs[base + R_OFF + 1] = scratch.sample[1]!;\n target.trs[base + R_OFF + 2] = scratch.sample[2]!;\n target.trs[base + R_OFF + 3] = scratch.sample[3]!;\n target.rWeight[nodeIdx] = weight;\n break;\n }\n const accumulatedWeight = target.rWeight[nodeIdx]!;\n quatSlerpInto(\n target.trs,\n base + R_OFF,\n target.trs[base + R_OFF]!,\n target.trs[base + R_OFF + 1]!,\n target.trs[base + R_OFF + 2]!,\n target.trs[base + R_OFF + 3]!,\n scratch.sample[0]!,\n scratch.sample[1]!,\n scratch.sample[2]!,\n scratch.sample[3]!,\n weight / (accumulatedWeight + weight)\n );\n target.rWeight[nodeIdx] = accumulatedWeight + weight;\n break;\n }\n }\n }\n}\n\nfunction advanceGroupTime(group: AnimationGroup, mixer: AnimationGltfMixer, deltaMs: number): number {\n const clip = mixer[GLTF_CLIP];\n const isPlaying = group.isPlaying;\n if (isPlaying) {\n group.currentFrame += (deltaMs / 1000) * group.speedRatio;\n }\n\n if (clip.duration <= 0) {\n return 0;\n }\n\n if (group.loopAnimation && isPlaying) {\n group.currentFrame %= clip.duration;\n if (group.currentFrame < 0) {\n group.currentFrame += clip.duration;\n }\n } else {\n group.currentFrame = Math.min(Math.max(group.currentFrame, 0), clip.duration);\n }\n return group.currentFrame;\n}\n\nfunction uploadTarget(manager: AnimationManager, target: WeightedGltfTarget): void {\n if (!manager.engine) {\n throw new Error(\"Weighted glTF animation requires an AnimationManager engine\");\n }\n const device = manager.engine._device;\n const { nodes, trs, localMat, worldMat } = target;\n\n for (let i = 0; i < nodes.length; i++) {\n const rotationWeight = target.rWeight[i]!;\n if (rotationWeight > 0 && rotationWeight < 1) {\n const off = i * TRS_STRIDE + R_OFF;\n const node = nodes[i]!;\n quatSlerpInto(trs, off, node.rx, node.ry, node.rz, node.rw, trs[off]!, trs[off + 1]!, trs[off + 2]!, trs[off + 3]!, rotationWeight);\n } else if (rotationWeight > 0) {\n normalizeQuaternionAt(trs, i * TRS_STRIDE + R_OFF);\n }\n }\n\n for (let idx = 0; idx < nodes.length; idx++) {\n const nodeIdx = target.topoOrder[idx]!;\n const node = nodes[nodeIdx]!;\n const off = nodeIdx * TRS_STRIDE;\n if (node._matrix) {\n localMat.set(node._matrix, nodeIdx * 16);\n } else {\n mat4ComposeInto(\n localMat,\n nodeIdx * 16,\n trs[off + T_OFF]!,\n trs[off + T_OFF + 1]!,\n trs[off + T_OFF + 2]!,\n trs[off + R_OFF]!,\n trs[off + R_OFF + 1]!,\n trs[off + R_OFF + 2]!,\n trs[off + R_OFF + 3]!,\n trs[off + S_OFF]!,\n trs[off + S_OFF + 1]!,\n trs[off + S_OFF + 2]!\n );\n }\n\n const parentIdx = node.parentIdx;\n if (parentIdx >= 0) {\n mat4MultiplyInto(worldMat, nodeIdx * 16, worldMat, parentIdx * 16, localMat, nodeIdx * 16);\n } else {\n mat4MultiplyInto(worldMat, nodeIdx * 16, RH_TO_LH, 0, localMat, nodeIdx * 16);\n }\n }\n\n for (let skeletonIndex = 0; skeletonIndex < target.skeletons.length; skeletonIndex++) {\n const skel = target.skeletons[skeletonIndex]!;\n const boneData = skel.boneMatrices;\n for (let bi = 0; bi < skel.boneCount; bi++) {\n const jointIdx = skel.jointNodes[bi]!;\n const ibmOff = bi * 16;\n mat4MultiplyInto(_boneTmp, 0, skel.invMeshWorld, 0, worldMat, jointIdx * 16);\n mat4MultiplyInto(boneData, bi * 16, _boneTmp, 0, skel.inverseBindMatrices, ibmOff);\n }\n\n const texWidth = skel.boneCount * 4;\n device.queue.writeTexture({ texture: skel.boneTexture }, boneData.buffer, { bytesPerRow: texWidth * 16 }, { width: texWidth, height: 1 });\n }\n}\n\nfunction computeTopoOrder(nodes: readonly { readonly parentIdx: number }[]): Int32Array {\n const order = new Int32Array(nodes.length);\n const visited = new Uint8Array(nodes.length);\n let cursor = 0;\n\n function visit(idx: number): void {\n if (visited[idx]!) {\n return;\n }\n visited[idx] = 1;\n const p = nodes[idx]!.parentIdx;\n if (p >= 0) {\n visit(p);\n }\n order[cursor++] = idx;\n }\n\n for (let i = 0; i < nodes.length; i++) {\n visit(i);\n }\n return order;\n}\n\nfunction normalizeQuaternionAt(values: Float32Array, offset: number): void {\n const x = values[offset]!;\n const y = values[offset + 1]!;\n const z = values[offset + 2]!;\n const w = values[offset + 3]!;\n const lenSq = x * x + y * y + z * z + w * w;\n if (lenSq > 0) {\n const inv = 1 / Math.sqrt(lenSq);\n values[offset] = x * inv;\n values[offset + 1] = y * inv;\n values[offset + 2] = z * inv;\n values[offset + 3] = w * inv;\n }\n}\n\nfunction quatRefInverseTimesSample(out: Float32Array, ref: Float32Array, sample: Float32Array): void {\n const ax = -ref[0]!;\n const ay = -ref[1]!;\n const az = -ref[2]!;\n const aw = ref[3]!;\n const bx = sample[0]!;\n const by = sample[1]!;\n const bz = sample[2]!;\n const bw = sample[3]!;\n out[0] = aw * bx + ax * bw + ay * bz - az * by;\n out[1] = aw * by - ax * bz + ay * bw + az * bx;\n out[2] = aw * bz + ax * by - ay * bx + az * bw;\n out[3] = aw * bw - ax * bx - ay * by - az * bz;\n normalizeQuaternionAt(out, 0);\n}\n\nfunction applyAdditiveQuaternion(base: Float32Array, offset: number, delta: Float32Array, weight: number): void {\n const bx = base[offset]!;\n const by = base[offset + 1]!;\n const bz = base[offset + 2]!;\n const bw = base[offset + 3]!;\n const dx = delta[0]!;\n const dy = delta[1]!;\n const dz = delta[2]!;\n const dw = delta[3]!;\n quatSlerpInto(\n base,\n offset,\n bx,\n by,\n bz,\n bw,\n bw * dx + bx * dw + by * dz - bz * dy,\n bw * dy - bx * dz + by * dw + bz * dx,\n bw * dz + bx * dy - by * dx + bz * dw,\n bw * dw - bx * dx - by * dy - bz * dz,\n weight\n );\n}\n\nfunction quatSlerpInto(out: Float32Array, offset: number, ax: number, ay: number, az: number, aw: number, bx: number, by: number, bz: number, bw: number, t: number): void {\n let dot = ax * bx + ay * by + az * bz + aw * bw;\n if (dot < 0) {\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n dot = -dot;\n }\n if (dot > 0.9995) {\n out[offset] = ax + t * (bx - ax);\n out[offset + 1] = ay + t * (by - ay);\n out[offset + 2] = az + t * (bz - az);\n out[offset + 3] = aw + t * (bw - aw);\n normalizeQuaternionAt(out, offset);\n return;\n }\n const theta = Math.acos(dot);\n const sinTheta = Math.sin(theta);\n const wa = Math.sin((1 - t) * theta) / sinTheta;\n const wb = Math.sin(t * theta) / sinTheta;\n out[offset] = wa * ax + wb * bx;\n out[offset + 1] = wa * ay + wb * by;\n out[offset + 2] = wa * az + wb * bz;\n out[offset + 3] = wa * aw + wb * bw;\n}\n","import { playAnimation } from \"./animation-group.js\";\nimport type { AnimationGroup, AnimationPropertyRuntimeTrack } from \"./animation-group.js\";\nimport { addAnimationGroup } from \"./animation-group-task.js\";\nimport type { AnimationManager } from \"./animation-manager.js\";\nimport { INTERP_LINEAR, INTERP_STEP } from \"./types.js\";\nimport type { AnimationSampler } from \"./types.js\";\nimport { evaluateSampler } from \"./evaluate.js\";\nimport type { AnimationController } from \"../skeleton/skeleton-updater.js\";\n\nconst DEFAULT_FRAME_RATE = 60;\n\n/** A keyframe value: a single scalar or a fixed-length tuple of components (e.g. a vector or quaternion). */\nexport type AnimationKeyframeValue = number | readonly number[];\n\n/** A single keyframe on a property animation track. Supply exactly one of `time` (seconds) or `frame`. */\nexport interface AnimationKeyframe {\n readonly time?: number;\n readonly frame?: number;\n readonly value: AnimationKeyframeValue;\n}\n\n/** Interpolation mode between keyframes: smooth `\"linear\"` or hold-previous `\"step\"`. */\nexport type PropertyAnimationInterpolation = \"linear\" | \"step\";\n\n/** Options describing one animated property track passed to {@link createPropertyAnimationClip}. */\nexport interface PropertyAnimationTrackOptions {\n readonly path: string;\n readonly keys: readonly AnimationKeyframe[];\n readonly frameRate?: number;\n readonly interpolation?: PropertyAnimationInterpolation;\n readonly quaternion?: boolean;\n}\n\n/** Options for {@link createPropertyAnimationClip}. */\nexport interface PropertyAnimationClipOptions {\n readonly frameRate?: number;\n}\n\n/** A compiled animation track: a sampler plus the metadata needed to evaluate and write its property. */\nexport interface PropertyAnimationTrack {\n readonly path: string;\n readonly sampler: AnimationSampler;\n readonly stride: number;\n readonly quaternion: boolean;\n}\n\n/** A reusable, target-independent set of compiled property tracks with a total duration. */\nexport interface PropertyAnimationClip {\n readonly name: string;\n readonly tracks: readonly PropertyAnimationTrack[];\n readonly duration: number;\n readonly frameRate: number;\n}\n\n/** Options for {@link createPropertyAnimationGroup}, controlling looping, speed, and play range. */\nexport interface CreatePropertyAnimationGroupOptions {\n readonly loop?: boolean;\n readonly speedRatio?: number;\n readonly fromFrame?: number;\n readonly toFrame?: number;\n readonly fromTime?: number;\n readonly toTime?: number;\n}\n\ntype PropertyWriter = (output: Float32Array, offset: number) => void;\n\ninterface ResolvedPropertyBinding {\n readonly mixTarget: object;\n readonly mixProperty: string;\n readonly writer: PropertyWriter;\n}\n\ninterface PathSettable {\n set: (...values: number[]) => void;\n}\n\n/** Compiles a set of track definitions into a reusable {@link PropertyAnimationClip}.\n * @param name - Clip name.\n * @param tracks - One or more track definitions; their keyframes are sorted and baked into samplers.\n * @param options - Optional default frame rate.\n * @returns The compiled clip, with its duration set to the longest track.\n * @throws If no tracks are provided. */\nexport function createPropertyAnimationClip(name: string, tracks: readonly PropertyAnimationTrackOptions[], options?: PropertyAnimationClipOptions): PropertyAnimationClip {\n if (tracks.length === 0) {\n throw new Error(\"createPropertyAnimationClip requires at least one track\");\n }\n const frameRate = options?.frameRate ?? tracks[0]?.frameRate ?? DEFAULT_FRAME_RATE;\n let duration = 0;\n const builtTracks = tracks.map((track) => {\n const trackFrameRate = track.frameRate ?? frameRate;\n const sampler = createSampler(track, trackFrameRate);\n const trackDuration = sampler.input[sampler.input.length - 1] ?? 0;\n if (trackDuration > duration) {\n duration = trackDuration;\n }\n return {\n path: track.path,\n sampler,\n stride: getTrackStride(track),\n quaternion: track.quaternion === true || track.path === \"rotationQuaternion\" || track.path.endsWith(\".rotationQuaternion\"),\n };\n });\n return { name, tracks: builtTracks, duration, frameRate };\n}\n\n/** Binds `clip` to `target`'s properties, creates a playing animation group, and attaches it to `manager`.\n * @param manager - Animation manager that drives the resulting group.\n * @param target - Object whose properties (resolved by each track's dotted path) are animated.\n * @param clip - Compiled clip to play.\n * @param options - Optional looping, speed, and play-range overrides.\n * @returns The started animation group.\n * @throws If the resolved play range does not have `toTime` greater than `fromTime`. */\nexport function createPropertyAnimationGroup(\n manager: AnimationManager,\n target: object,\n clip: PropertyAnimationClip,\n options?: CreatePropertyAnimationGroupOptions\n): AnimationGroup {\n const runtimeTracks: AnimationPropertyRuntimeTrack[] = [];\n for (let i = 0; i < clip.tracks.length; i++) {\n const track = clip.tracks[i]!;\n const binding = resolvePropertyBinding(target, track.path, track.stride);\n runtimeTracks.push({\n sampler: track.sampler,\n stride: track.stride,\n quaternion: track.quaternion,\n writer: binding.writer,\n mixTarget: binding.mixTarget,\n mixProperty: binding.mixProperty,\n });\n }\n\n const fromTime = options?.fromTime ?? (options?.fromFrame !== undefined ? options.fromFrame / clip.frameRate : 0);\n const toTime = options?.toTime ?? (options?.toFrame !== undefined ? options.toFrame / clip.frameRate : clip.duration);\n if (!(toTime > fromTime)) {\n throw new Error(\"Animation play range must have toTime greater than fromTime\");\n }\n\n const group = createPointerAnimationGroup(clip.name, clip.duration, clip.frameRate, runtimeTracks, fromTime, toTime, options);\n group.loopAnimation = options?.loop ?? true;\n group.speedRatio = options?.speedRatio ?? 1;\n group._propertyMixer = [runtimeTracks, fromTime, toTime, clip.duration];\n playAnimation(group);\n addAnimationGroup(manager, group);\n return group;\n}\n\nfunction createPointerAnimationGroup(\n name: string,\n duration: number,\n frameRate: number,\n tracks: readonly AnimationPropertyRuntimeTrack[],\n fromTime: number,\n toTime: number,\n options?: CreatePropertyAnimationGroupOptions\n): AnimationGroup {\n const ctrl: AnimationController = {\n time: fromTime,\n playing: false,\n speedRatio: options?.speedRatio ?? 1,\n loop: options?.loop ?? true,\n tick(deltaMs: number): void {\n if (ctrl.playing) {\n ctrl.time += (deltaMs / 1000) * ctrl.speedRatio;\n }\n const duration = Math.max(0, toTime - fromTime);\n if (duration <= 0) {\n return;\n }\n if (ctrl.loop && ctrl.playing) {\n ctrl.time = fromTime + ((ctrl.time - fromTime) % duration);\n if (ctrl.time < fromTime) {\n ctrl.time += duration;\n }\n } else {\n ctrl.time = Math.min(Math.max(ctrl.time, fromTime), toTime);\n }\n for (let trackIndex = 0; trackIndex < tracks.length; trackIndex++) {\n const track = tracks[trackIndex]!;\n evaluateSampler(track.sampler, ctrl.time, track.stride, track.quaternion, _pointerScratch, 0);\n track.writer(_pointerScratch, 0);\n }\n },\n };\n return {\n name,\n duration,\n frameRate: frameRate || DEFAULT_FRAME_RATE,\n isPlaying: false,\n currentFrame: fromTime,\n speedRatio: options?.speedRatio ?? 1,\n loopAnimation: options?.loop ?? true,\n weight: 1,\n _ctrl: ctrl,\n _stopped: false,\n };\n}\n\nconst _pointerScratch = new Float32Array(16);\n\nfunction createSampler(track: PropertyAnimationTrackOptions, frameRate: number): AnimationSampler {\n if (track.keys.length === 0) {\n throw new Error(`Animation track \"${track.path}\" requires at least one key`);\n }\n if (!(frameRate > 0)) {\n throw new Error(`Animation track \"${track.path}\" requires a positive frameRate`);\n }\n\n const stride = getTrackStride(track);\n const sorted = [...track.keys].sort((a, b) => getKeyTime(a, frameRate, track.path) - getKeyTime(b, frameRate, track.path));\n const input = new Float32Array(sorted.length);\n const output = new Float32Array(sorted.length * stride);\n let lastTime = -Infinity;\n for (let i = 0; i < sorted.length; i++) {\n const key = sorted[i]!;\n const time = getKeyTime(key, frameRate, track.path);\n if (time < lastTime) {\n throw new Error(`Animation track \"${track.path}\" key times must be monotonically increasing`);\n }\n input[i] = time;\n lastTime = time;\n writeKeyValue(track.path, key.value, stride, output, i * stride);\n }\n return {\n input,\n output,\n interpolation: track.interpolation === \"step\" ? INTERP_STEP : INTERP_LINEAR,\n };\n}\n\nfunction getTrackStride(track: PropertyAnimationTrackOptions): number {\n const value = track.keys[0]?.value;\n if (value === undefined) {\n throw new Error(`Animation track \"${track.path}\" requires at least one key`);\n }\n return typeof value === \"number\" ? 1 : value.length;\n}\n\nfunction getKeyTime(key: AnimationKeyframe, frameRate: number, path: string): number {\n const hasTime = key.time !== undefined;\n const hasFrame = key.frame !== undefined;\n if (hasTime === hasFrame) {\n throw new Error(`Animation key for \"${path}\" must provide exactly one of time or frame`);\n }\n const time = hasTime ? key.time! : key.frame! / frameRate;\n if (!(time >= 0)) {\n throw new Error(`Animation key for \"${path}\" must have a non-negative time`);\n }\n return time;\n}\n\nfunction writeKeyValue(path: string, value: AnimationKeyframeValue, stride: number, output: Float32Array, offset: number): void {\n if (typeof value === \"number\") {\n if (stride !== 1) {\n throw new Error(`Animation key for \"${path}\" expected ${stride} values`);\n }\n output[offset] = value;\n return;\n }\n if (value.length !== stride) {\n throw new Error(`Animation key for \"${path}\" expected ${stride} values`);\n }\n for (let i = 0; i < stride; i++) {\n output[offset + i] = value[i]!;\n }\n}\n\nfunction resolvePropertyBinding(target: object, path: string, stride: number): ResolvedPropertyBinding {\n const parts = path.split(\".\");\n if (parts.length === 0 || parts.some((p) => p.length === 0)) {\n throw new Error(`Invalid animation property path \"${path}\"`);\n }\n\n let owner: unknown = target;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]!;\n const record = asRecord(owner, path);\n if (!(part in record)) {\n throw new Error(`Animation property path \"${path}\" could not resolve \"${part}\"`);\n }\n owner = record[part];\n }\n\n const property = parts[parts.length - 1]!;\n const record = asRecord(owner, path);\n if (!(property in record)) {\n throw new Error(`Animation property path \"${path}\" could not resolve \"${property}\"`);\n }\n\n return { mixTarget: record, mixProperty: property, writer: createPropertyWriter(record, property, stride, path) };\n}\n\nfunction asRecord(value: unknown, path: string): Record<string, unknown> {\n if ((typeof value !== \"object\" && typeof value !== \"function\") || value === null) {\n throw new Error(`Animation property path \"${path}\" reached a non-object value`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction isSettable(value: unknown): value is PathSettable {\n return (typeof value === \"object\" || typeof value === \"function\") && value !== null && typeof (value as { set?: unknown }).set === \"function\";\n}\n\nfunction createPropertyWriter(target: Record<string, unknown>, property: string, stride: number, path: string): PropertyWriter {\n if (stride === 1) {\n return (output, offset) => {\n target[property] = output[offset]!;\n };\n }\n if (stride > 4) {\n throw new Error(`Animation property path \"${path}\" has unsupported vector size ${stride}`);\n }\n\n const targetValue = target[property];\n if (isSettable(targetValue)) {\n switch (stride) {\n case 2:\n return (output, offset) => targetValue.set(output[offset]!, output[offset + 1]!);\n case 3:\n return (output, offset) => targetValue.set(output[offset]!, output[offset + 1]!, output[offset + 2]!);\n case 4:\n return (output, offset) => targetValue.set(output[offset]!, output[offset + 1]!, output[offset + 2]!, output[offset + 3]!);\n }\n }\n\n const valueRecord = asRecord(targetValue, path);\n const components = \"xyzw\";\n for (let i = 0; i < stride; i++) {\n if (!(components[i]! in valueRecord)) {\n throw new Error(`Animation property path \"${path}\" could not resolve component \"${components[i]!}\"`);\n }\n }\n return (output, offset) => {\n for (let i = 0; i < stride; i++) {\n valueRecord[components[i]!] = output[offset + i]!;\n }\n };\n}\n","/** Morph target GPU resource factory.\n *\n * Dynamically imported by load-gltf.ts when a mesh has morph targets.\n * Scenes without morph targets never import this module.\n * Morph WGSL is now provided by the morph ShaderFragment\n * (shader/fragments/morph-fragment.ts) and composed at pipeline\n * creation time — no global registration needed. */\n\nimport type { MorphTargetData } from \"../animation/types.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { createMappedBuffer } from \"../resource/gpu-buffers.js\";\n\n/** Create morph target GPU data from parsed glTF targets.\n * @param engine - Engine context (provides GPU device)\n * @param targets - Array of `{positions, normals}` deltas per target\n * @param vertexCount - Number of vertices in the base mesh\n * @param morphWeights - Initial morph weights (one per target, may be null)\n */\nexport function createMorphTargets(\n engine: EngineContext,\n targets: { positions: Float32Array; normals: Float32Array | null }[],\n vertexCount: number,\n morphWeights: number[] | null\n): MorphTargetData {\n const device = engine._device;\n const targetCount = Math.min(targets.length, 4); // max 4 (vec4 weights)\n const texWidth = Math.min(vertexCount, 2048);\n const rowsPerBand = Math.ceil(vertexCount / texWidth);\n // Each target has 2 bands: position deltas + normal deltas\n const totalRows = targetCount * 2 * rowsPerBand;\n\n // Build tiled rgba32float texture\n const texData = new Float32Array(texWidth * totalRows * 4);\n for (let t = 0; t < targetCount; t++) {\n const tgt = targets[t]!;\n const posBandRow = t * 2 * rowsPerBand;\n const normBandRow = (t * 2 + 1) * rowsPerBand;\n for (let v = 0; v < vertexCount; v++) {\n const col = v % texWidth;\n const row = Math.floor(v / texWidth);\n // Position deltas\n const posIdx = ((posBandRow + row) * texWidth + col) * 4;\n texData[posIdx] = tgt.positions[v * 3]!;\n texData[posIdx + 1] = tgt.positions[v * 3 + 1]!;\n texData[posIdx + 2] = tgt.positions[v * 3 + 2]!;\n // Normal deltas\n if (tgt.normals) {\n const normIdx = ((normBandRow + row) * texWidth + col) * 4;\n texData[normIdx] = tgt.normals[v * 3]!;\n texData[normIdx + 1] = tgt.normals[v * 3 + 1]!;\n texData[normIdx + 2] = tgt.normals[v * 3 + 2]!;\n }\n }\n }\n\n const texture = device.createTexture({\n size: [texWidth, totalRows],\n format: \"rgba32float\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture({ texture }, texData.buffer, { bytesPerRow: texWidth * 16 }, { width: texWidth, height: totalRows });\n\n // Weights UBO: vec4 weights + count + texWidth + rowsPerBand + pad = 32 bytes\n const uboData = new ArrayBuffer(32);\n const weights = new Float32Array(uboData, 0, 4);\n const u32 = new Uint32Array(uboData, 16, 4);\n for (let i = 0; i < targetCount; i++) {\n weights[i] = morphWeights?.[i] ?? 0;\n }\n u32[0] = targetCount;\n u32[1] = texWidth;\n u32[2] = rowsPerBand;\n\n const weightsBuffer = createMappedBuffer(engine, new Uint8Array(uboData), GPUBufferUsage.UNIFORM);\n\n return { texture, count: targetCount, weightsBuffer, targets: targets.slice(0, targetCount), weights };\n}\n\n/** Update morph target weights on CPU and GPU.\n * Only the first four weights are used, matching the current morph target limit.\n * @param engine - Engine context that owns the morph target GPU buffer.\n * @param morphTargets - Morph target data returned by `createMorphTargets()`.\n * @param weights - New morph weights; missing slots are reset to 0.\n */\nexport function setMorphTargetWeights(engine: EngineContext, morphTargets: MorphTargetData, weights: ArrayLike<number>): void {\n const count = Math.min(morphTargets.count, 4, weights.length);\n morphTargets.weights.fill(0);\n for (let i = 0; i < count; i++) {\n morphTargets.weights[i] = weights[i] ?? 0;\n }\n engine._device.queue.writeBuffer(morphTargets.weightsBuffer, 0, morphTargets.weights);\n}\n","/** Thin instances — CPU-side data for hardware-instanced rendering.\n * Each instance carries a world matrix (16 floats) and optionally a\n * per-instance color (4 floats). The render system creates and syncs\n * GPU buffers automatically via version tracking. */\n\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"./mesh.js\";\n\n/** CPU-side data backing a thin-instanced mesh: world matrices, optional colors, and GPU sync state. */\nexport interface ThinInstanceData {\n /** CPU-side instance world matrices (16 floats per instance). */\n matrices: Float32Array;\n /** Active instance count. */\n count: number;\n /** @internal Allocated capacity (in instances). */\n _capacity: number;\n /** @internal Version counter — bumped by helpers, checked by render system. */\n _version: number;\n /** @internal GPU buffer — created and managed by render system, not user. */\n _gpuBuffer: GPUBuffer | null;\n /** @internal Whether the current matrix GPU buffer was created with STORAGE usage. */\n _gpuBufferStorage: boolean;\n /** @internal Last version uploaded to GPU. */\n _gpuVersion: number;\n\n /** @internal Min dirty instance index (inclusive). */\n _dirtyMin: number;\n /** @internal Max dirty instance index (exclusive). */\n _dirtyMax: number;\n\n /** Optional per-instance RGBA colors (4 floats per instance). */\n colors?: Float32Array | null;\n /** @internal Color version counter — independent of matrix version. */\n _colorVersion: number;\n /** @internal GPU buffer for per-instance colors. */\n _colorGpuBuffer: GPUBuffer | null;\n /** @internal Whether the current color GPU buffer was created with STORAGE usage. */\n _colorGpuBufferStorage: boolean;\n /** @internal Last color version uploaded to GPU. */\n _colorGpuVersion: number;\n /** @internal Opt-in flag for GPU frustum culling + indirect drawing. */\n _gpuCullingEnabled: boolean;\n}\n\n/** Set all instances from a pre-built matrix array. */\nexport function setThinInstances(mesh: Mesh, matrices: Float32Array, count: number): void {\n if (!mesh.thinInstances) {\n mesh.thinInstances = {\n matrices,\n count,\n _capacity: count,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: count,\n _colorVersion: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n } else {\n mesh.thinInstances.matrices = matrices;\n mesh.thinInstances.count = count;\n mesh.thinInstances._capacity = count;\n mesh.thinInstances._version++;\n mesh.thinInstances._dirtyMin = 0;\n mesh.thinInstances._dirtyMax = count;\n }\n}\n\n/** Add one instance. Returns its index. Grows capacity as needed. */\nexport function addThinInstance(mesh: Mesh, matrix: Mat4): number {\n const ti = mesh.thinInstances;\n if (!ti) {\n const capacity = 16;\n const matrices = new Float32Array(capacity * 16);\n matrices.set(matrix, 0);\n mesh.thinInstances = {\n matrices,\n count: 1,\n _capacity: capacity,\n _version: 1,\n _gpuBuffer: null,\n _gpuBufferStorage: false,\n _gpuVersion: 0,\n _dirtyMin: 0,\n _dirtyMax: 1,\n _colorVersion: 0,\n _colorGpuBuffer: null,\n _colorGpuBufferStorage: false,\n _colorGpuVersion: 0,\n _gpuCullingEnabled: false,\n };\n return 0;\n }\n\n const index = ti.count;\n if (index >= ti._capacity) {\n const newCap = ti._capacity * 2;\n const newData = new Float32Array(newCap * 16);\n newData.set(ti.matrices);\n ti.matrices = newData;\n ti._capacity = newCap;\n }\n\n ti.matrices.set(matrix, index * 16);\n ti.count++;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n return index;\n}\n\n/** Update one instance's matrix. */\nexport function setThinInstanceMatrix(mesh: Mesh, index: number, matrix: Mat4): void {\n const ti = mesh.thinInstances!;\n ti.matrices.set(matrix, index * 16);\n ti._version++;\n ti._dirtyMin = Math.min(ti._dirtyMin, index);\n ti._dirtyMax = Math.max(ti._dirtyMax, index + 1);\n}\n\n/** Remove instance by index. Swap-removes: last instance fills the gap. */\nexport function removeThinInstance(mesh: Mesh, index: number): void {\n const ti = mesh.thinInstances!;\n const last = ti.count - 1;\n if (index !== last) {\n ti.matrices.copyWithin(index * 16, last * 16, last * 16 + 16);\n }\n ti.count--;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Mark thin instance data dirty after direct array manipulation. */\nexport function flushThinInstances(mesh: Mesh): void {\n const ti = mesh.thinInstances!;\n ti._version++;\n ti._dirtyMin = 0;\n ti._dirtyMax = ti.count;\n}\n\n/** Set per-instance RGBA colors for a thin-instanced mesh. */\nexport function setThinInstanceColors(mesh: Mesh, colors: Float32Array): void {\n const ti = mesh.thinInstances!;\n ti.colors = colors;\n ti._colorVersion++;\n}\n\n/** Enable or disable GPU frustum culling for an existing thin-instanced mesh.\n *\n * Call this after `setThinInstances()`/`addThinInstance()` and before `registerScene()`.\n * The render system keeps the feature opt-in so non-culled thin-instance scenes do not\n * fetch the compute-culling module or allocate compacted visible-instance buffers.\n */\nexport function enableThinInstanceGpuCulling(mesh: Mesh, enabled = true): void {\n const ti = mesh.thinInstances;\n if (!ti) {\n throw new Error(\"enableThinInstanceGpuCulling requires mesh.thinInstances\");\n }\n if (ti._gpuCullingEnabled === enabled) {\n return;\n }\n ti._gpuCullingEnabled = enabled;\n ti._gpuVersion = -1;\n ti._colorGpuVersion = -1;\n}\n","import type { Camera, NormalizedViewport } from \"./camera.js\";\nexport { getEffectiveAspectRatio } from \"./camera.js\";\n\n/** A viewport expressed in integer render-target pixels, with `y` measured from the top (WebGPU convention). */\nexport interface PixelViewport {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport const FULL_VIEWPORT: NormalizedViewport = { x: 0, y: 0, width: 1, height: 1 };\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\n/** Resolve a Babylon-style normalized viewport to integer render-target pixels.\n * Babylon viewport y is normalized from the bottom; WebGPU viewport/scissor y is from the top. */\nexport function resolveCameraViewport(camera: Camera | null | undefined, targetWidth: number, targetHeight: number): PixelViewport {\n const v = camera?.viewport ?? FULL_VIEWPORT;\n const x0 = clamp01(v.x);\n const y0 = clamp01(1 - v.y - v.height);\n const x1 = clamp01(v.x + v.width);\n const y1 = clamp01(1 - v.y);\n const x = Math.floor(x0 * targetWidth);\n const y = Math.floor(y0 * targetHeight);\n const width = Math.max(0, Math.ceil(x1 * targetWidth) - x);\n const height = Math.max(0, Math.ceil(y1 * targetHeight) - y);\n return { x, y, width, height };\n}\n","import type { Mesh } from \"../mesh/mesh.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport type { Ray } from \"./ray.js\";\n\n/** Result of a GPU pick operation. */\nexport interface PickingInfo {\n hit: boolean;\n distance: number;\n pickedPoint: [number, number, number] | null;\n pickedNormal: [number, number, number] | null;\n pickedNormalWorld: [number, number, number] | null;\n pickedFaceNormal: [number, number, number] | null;\n pickedFaceNormalWorld: [number, number, number] | null;\n /** The picked mesh. May be a regular Lite `Mesh` or a `GaussianSplattingMesh`\n * (when GS picking via the gs-picking-pipeline ports the BJS\n * `GaussianSplattingGpuPickingMaterialPlugin`). */\n pickedMesh: Mesh | GaussianSplattingMesh | null;\n faceId: number;\n bu: number;\n bv: number;\n subMeshId: number;\n thinInstanceIndex: number;\n ray: Ray | null;\n}\n\n/** Create an empty (miss) picking result. */\nexport function createEmptyPickingInfo(): PickingInfo {\n return {\n hit: false,\n distance: 0,\n pickedPoint: null,\n pickedNormal: null,\n pickedNormalWorld: null,\n pickedFaceNormal: null,\n pickedFaceNormalWorld: null,\n pickedMesh: null,\n faceId: -1,\n bu: 0,\n bv: 0,\n subMeshId: 0,\n thinInstanceIndex: -1,\n ray: null,\n };\n}\n","import type { Mat4 } from \"../math/types.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\n\n/** A ray defined by origin, direction, and length. */\nexport interface Ray {\n origin: [number, number, number];\n direction: [number, number, number];\n length: number;\n}\n\n/**\n * Create a picking ray from screen coordinates.\n * Uses left-handed coordinates with WebGPU reverse-Z 0-to-1 depth range.\n */\nexport function createPickingRay(x: number, y: number, vpMatrix: Mat4, width: number, height: number): Ray | null {\n const invVP = mat4Invert(vpMatrix);\n if (!invVP) {\n return null;\n }\n\n // Convert screen coords to NDC (Y flipped for WebGPU)\n const ndcX = (2 * x) / width - 1;\n const ndcY = 1 - (2 * y) / height;\n\n // Reverse-Z maps near to 1 and far to 0.\n const near = unprojectPoint(invVP, ndcX, ndcY, 1);\n const far = unprojectPoint(invVP, ndcX, ndcY, 0);\n\n const dx = far[0] - near[0];\n const dy = far[1] - near[1];\n const dz = far[2] - near[2];\n const len = Math.sqrt(dx * dx + dy * dy + dz * dz);\n\n if (len < 1e-10) {\n return null;\n }\n\n const invLen = 1 / len;\n return {\n origin: near,\n direction: [dx * invLen, dy * invLen, dz * invLen],\n length: len,\n };\n}\n\n/** Unproject a clip-space point through an inverse VP matrix. */\nfunction unprojectPoint(invVP: Mat4, ndcX: number, ndcY: number, depth: number): [number, number, number] {\n // Multiply invVP * [ndcX, ndcY, depth, 1.0]\n const x = invVP[0]! * ndcX + invVP[4]! * ndcY + invVP[8]! * depth + invVP[12]!;\n const y = invVP[1]! * ndcX + invVP[5]! * ndcY + invVP[9]! * depth + invVP[13]!;\n const z = invVP[2]! * ndcX + invVP[6]! * ndcY + invVP[10]! * depth + invVP[14]!;\n const w = invVP[3]! * ndcX + invVP[7]! * ndcY + invVP[11]! * depth + invVP[15]!;\n const invW = 1 / w;\n return [x * invW, y * invW, z * invW];\n}\n","/** WGSL shaders for GPU pick-ID rendering.\n * Outputs pick ID as rgba8unorm (location 0) and depth as r32float (location 1). */\n\n// ─── Shared structs + fragment shader ───────────────────────────────\n\nconst PICK_FS = /* wgsl */ `\nstruct VsOut { @builtin(position) position: vec4f, @location(0) @interpolate(flat) pickId: u32 };\nstruct FsOut { @location(0) color: vec4f, @location(1) depth: vec4f };\n@fragment fn fs(input: VsOut) -> FsOut {\nlet id = input.pickId;\nlet r = f32((id >> 16u) & 0xFFu) / 255.0;\nlet g = f32((id >> 8u) & 0xFFu) / 255.0;\nlet b = f32(id & 0xFFu) / 255.0;\nreturn FsOut(vec4f(r, g, b, 1.0), vec4f(input.position.z, 0.0, 0.0, 0.0));\n}\n`;\n\n// ─── Regular mesh picking shader ────────────────────────────────────\n\nexport const pickingShaderSource = /* wgsl */ `\nstruct SceneUniforms { viewProjection: mat4x4f };\nstruct MeshUniforms { world: mat4x4f, pickId: u32 };\n@group(0) @binding(0) var<uniform> scene: SceneUniforms;\n@group(1) @binding(0) var<uniform> mesh: MeshUniforms;\n${PICK_FS}\n@vertex fn vs(@location(0) position: vec3f) -> VsOut {\nvar out: VsOut;\nout.position = scene.viewProjection * mesh.world * vec4f(position, 1.0);\nout.pickId = mesh.pickId;\nreturn out;\n}\n`;\n\n// ─── Thin-instance picking shader ───────────────────────────────────\n\nexport const pickingThinInstanceShaderSource = /* wgsl */ `\nstruct SceneUniforms { viewProjection: mat4x4f };\nstruct TIMeshUniforms { baseMeshPickId: u32 };\n@group(0) @binding(0) var<uniform> scene: SceneUniforms;\n@group(1) @binding(0) var<uniform> tiMesh: TIMeshUniforms;\n@group(1) @binding(1) var<storage, read> instances: array<mat4x4f>;\n${PICK_FS}\n@vertex fn vs(@location(0) position: vec3f, @builtin(instance_index) instanceIndex: u32) -> VsOut {\nlet world = instances[instanceIndex];\nvar out: VsOut;\nout.position = scene.viewProjection * world * vec4f(position, 1.0);\nout.pickId = tiMesh.baseMeshPickId + instanceIndex;\nreturn out;\n}\n`;\n","import type { EngineContext } from \"../engine/engine.js\";\n\n/** Create a BGL with a single `uniform` buffer entry at binding 0.\n * Used for scene/mesh/skybox UBOs that only bind one uniform buffer. */\nexport function createSingleUniformBGL(engine: EngineContext, label: string, visibility: GPUShaderStageFlags): GPUBindGroupLayout {\n return engine._device.createBindGroupLayout({\n label,\n entries: [{ binding: 0, visibility, buffer: { type: \"uniform\" } }],\n });\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport { pickingShaderSource, pickingThinInstanceShaderSource } from \"./picking-shader.js\";\nimport { createSingleUniformBGL } from \"../shader/bgl-helpers.js\";\n\n// ─── Cache state (auto-invalidate on device change) ─────────────────\n\nlet _cachedDevice: GPUDevice | null = null;\nlet _pipeline: GPURenderPipeline | null = null;\nlet _tiPipeline: GPURenderPipeline | null = null;\nlet _sceneBGL: GPUBindGroupLayout | null = null;\nlet _meshBGL: GPUBindGroupLayout | null = null;\nlet _tiMeshBGL: GPUBindGroupLayout | null = null;\n\nfunction invalidateIfNeeded(engine: EngineContext): void {\n const device = engine._device;\n if (device !== _cachedDevice) {\n _pipeline = null;\n _tiPipeline = null;\n _sceneBGL = null;\n _meshBGL = null;\n _tiMeshBGL = null;\n _cachedDevice = device;\n }\n}\n\n// ─── Bind group layouts ─────────────────────────────────────────────\n\n/** Group 0: scene-level viewProjection uniform. */\nexport function getPickingSceneBGL(engine: EngineContext): GPUBindGroupLayout {\n invalidateIfNeeded(engine);\n if (!_sceneBGL) {\n _sceneBGL = createSingleUniformBGL(engine, \"picking-scene-bgl\", GPUShaderStage.VERTEX);\n }\n return _sceneBGL;\n}\n\n/** Group 1: per-mesh world matrix + pickId uniform (regular meshes). */\nexport function getPickingMeshBGL(engine: EngineContext): GPUBindGroupLayout {\n invalidateIfNeeded(engine);\n if (!_meshBGL) {\n _meshBGL = createSingleUniformBGL(engine, \"picking-mesh-bgl\", GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT);\n }\n return _meshBGL;\n}\n\n/** Group 1: per-mesh baseMeshPickId uniform + instance storage buffer (thin instances). */\nexport function getPickingTIMeshBGL(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n invalidateIfNeeded(engine);\n if (!_tiMeshBGL) {\n _tiMeshBGL = device.createBindGroupLayout({\n label: \"picking-ti-mesh-bgl\",\n entries: [\n {\n binding: 0,\n visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,\n buffer: { type: \"uniform\" },\n },\n {\n binding: 1,\n visibility: GPUShaderStage.VERTEX,\n buffer: { type: \"read-only-storage\" },\n },\n ],\n });\n }\n return _tiMeshBGL;\n}\n\n// ─── Position-only vertex layout ────────────────────────────────────\n\nconst POSITION_VERTEX_LAYOUT: GPUVertexBufferLayout = {\n arrayStride: 12,\n attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x3\" }],\n};\n\n// ─── Pipeline creation ──────────────────────────────────────────────\n\ninterface PickingPipelineOptions {\n shader: string;\n meshBGL: GPUBindGroupLayout;\n label: string;\n}\n\nfunction createPickingPipelineInternal(engine: EngineContext, opts: PickingPipelineOptions): GPURenderPipeline {\n const device = engine._device;\n const module = device.createShaderModule({ label: `${opts.label}-shader`, code: opts.shader });\n const layout = device.createPipelineLayout({\n label: `${opts.label}-pipeline-layout`,\n bindGroupLayouts: [getPickingSceneBGL(engine), opts.meshBGL],\n });\n return device.createRenderPipeline({\n label: `${opts.label}-pipeline`,\n layout,\n vertex: {\n module,\n entryPoint: \"vs\",\n buffers: [POSITION_VERTEX_LAYOUT],\n },\n fragment: {\n module,\n entryPoint: \"fs\",\n targets: [{ format: \"rgba8unorm\" }, { format: \"r32float\" }],\n },\n depthStencil: {\n format: \"depth24plus\",\n depthCompare: \"greater\",\n depthWriteEnabled: true,\n },\n primitive: {\n topology: \"triangle-list\",\n cullMode: \"back\",\n frontFace: \"ccw\",\n },\n multisample: { count: 1 },\n });\n}\n\n/** Get (or create) the picking pipeline for regular meshes. */\nexport function getPickingPipeline(engine: EngineContext): GPURenderPipeline {\n invalidateIfNeeded(engine);\n if (!_pipeline) {\n _pipeline = createPickingPipelineInternal(engine, {\n shader: pickingShaderSource,\n meshBGL: getPickingMeshBGL(engine),\n label: \"picking\",\n });\n }\n return _pipeline;\n}\n\n/** Get (or create) the picking pipeline for thin-instanced meshes. */\nexport function getPickingTIPipeline(engine: EngineContext): GPURenderPipeline {\n invalidateIfNeeded(engine);\n if (!_tiPipeline) {\n _tiPipeline = createPickingPipelineInternal(engine, {\n shader: pickingThinInstanceShaderSource,\n meshBGL: getPickingTIMeshBGL(engine),\n label: \"picking-ti\",\n });\n }\n return _tiPipeline;\n}\n","import type { SceneContext } from \"../scene/scene.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { PickingInfo } from \"./picking-info.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type * as DeformedGeometry from \"./deformed-geometry.js\";\nimport type * as GsPickingPipeline from \"./gs-picking-pipeline.js\";\nimport type { GaussianSplattingMesh } from \"../mesh/GaussianSplatting/gaussian-splatting-mesh.js\";\nimport { createEmptyPickingInfo } from \"./picking-info.js\";\nimport { createPickingRay } from \"./ray.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { getPickingPipeline, getPickingTIPipeline, getPickingSceneBGL, getPickingMeshBGL, getPickingTIMeshBGL } from \"./picking-pipeline.js\";\nimport { getViewProjectionMatrix, getCameraPosition } from \"../camera/camera.js\";\nimport { resolveCameraViewport } from \"../camera/viewport.js\";\nimport { createEmptyUniformBuffer, createMappedBuffer, createUniformBuffer } from \"../resource/gpu-buffers.js\";\n\n// ─── Scratch arrays — allocated once, reused across all picks ──────\nconst _pickVP = new Float32Array(16);\nconst _gsPickMatrix = new Float32Array(16);\nconst _uboScratch = new ArrayBuffer(80);\nconst _uboF32 = new Float32Array(_uboScratch, 0, 16);\nconst _uboU32 = new Uint32Array(_uboScratch, 64, 1);\nconst _uboView = new Uint8Array(_uboScratch);\nconst _tiUboScratch = new Uint32Array(4);\n\n/** GPU-based picker — pure state. Use pickAsync() and disposePicker() standalone functions. */\nexport interface GpuPicker {\n /** @internal Optional hook for detailed picking (Phase 2). */\n _detailedPick: ((info: PickingInfo, ray: { origin: [number, number, number]; direction: [number, number, number]; length: number }) => void | Promise<void>) | null;\n /** @internal */\n _scene: SceneContext;\n /** @internal 1×1 render targets (lazily created). */\n _rt: PickTargets1x1 | null;\n /** @internal Reusable scene UBO (64 bytes). */\n _sceneUbo: GPUBuffer | null;\n /** @internal Reusable scene bind group. */\n _sceneBG: GPUBindGroup | null;\n /** @internal Per-GS-mesh picking resources (created on demand). */\n _gsMeshResources: Map<GaussianSplattingMesh, GsPickingPipeline.GsPickMeshResources> | null;\n}\n\ninterface PickTargets1x1 {\n colorTex: GPUTexture;\n colorView: GPUTextureView;\n depthColorTex: GPUTexture;\n depthColorView: GPUTextureView;\n depthTex: GPUTexture;\n depthView: GPUTextureView;\n colorStaging: GPUBuffer;\n depthStaging: GPUBuffer;\n}\n\n/** Create a GPU picker bound to the given scene. */\nexport function createGpuPicker(scene: SceneContext): GpuPicker {\n return {\n _detailedPick: null,\n _scene: scene,\n _rt: null,\n _sceneUbo: null,\n _sceneBG: null,\n _gsMeshResources: null,\n };\n}\n\nfunction ensureTargets(engine: EngineContext, picker: GpuPicker): PickTargets1x1 {\n const device = engine._device;\n if (picker._rt) {\n return picker._rt;\n }\n const colorTex = device.createTexture({ label: \"pick-color\", size: [1, 1], format: \"rgba8unorm\", usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC });\n const depthColorTex = device.createTexture({\n label: \"pick-depth-color\",\n size: [1, 1],\n format: \"r32float\",\n usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,\n });\n const depthTex = device.createTexture({ label: \"pick-depth\", size: [1, 1], format: \"depth24plus\", usage: GPUTextureUsage.RENDER_ATTACHMENT });\n picker._rt = {\n colorTex,\n colorView: colorTex.createView(),\n depthColorTex,\n depthColorView: depthColorTex.createView(),\n depthTex,\n depthView: depthTex.createView(),\n colorStaging: device.createBuffer({ label: \"pick-color-staging\", size: 256, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }),\n depthStaging: device.createBuffer({ label: \"pick-depth-staging\", size: 256, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }),\n };\n return picker._rt;\n}\n\nfunction ensureSceneUbo(engine: EngineContext, picker: GpuPicker): GPUBuffer {\n const device = engine._device;\n if (!picker._sceneUbo) {\n picker._sceneUbo = createEmptyUniformBuffer(engine, 64, \"pick-scene-ubo\");\n const sceneBGL = getPickingSceneBGL(engine);\n picker._sceneBG = device.createBindGroup({ label: \"pick-scene-bg\", layout: sceneBGL, entries: [{ binding: 0, resource: { buffer: picker._sceneUbo } }] });\n }\n return picker._sceneUbo;\n}\n\n/** Compute a VP matrix zoomed to a single pixel at (px, py) on a W×H canvas.\n * Renders to a 1×1 target — only fragments at the picked pixel survive. */\nfunction computePickVP(out: Float32Array, vp: Float32Array, px: number, py: number, w: number, h: number): void {\n const ndcX = (2 * (px + 0.5)) / w - 1;\n const ndcY = 1 - (2 * (py + 0.5)) / h;\n // pickVP = pickMatrix * VP (sparse multiply, see derivation in comments)\n for (let c = 0; c < 4; c++) {\n const base = c * 4;\n const w3 = vp[base + 3]!;\n out[base] = w * (vp[base]! - ndcX * w3);\n out[base + 1] = h * (vp[base + 1]! - ndcY * w3);\n out[base + 2] = vp[base + 2]!;\n out[base + 3] = w3;\n }\n}\n\n/** Pick the mesh at CSS-space canvas coordinates, matching Babylon.js Scene.pick. Returns a PickingInfo. */\nexport async function pickAsync(picker: GpuPicker, x: number, y: number): Promise<PickingInfo> {\n const scene = picker._scene;\n const engine = scene.engine;\n const device = engine._device;\n const canvas = engine.canvas;\n const camera = scene.camera;\n if (!camera) {\n return createEmptyPickingInfo();\n }\n\n const backingWidth = canvas.width;\n const backingHeight = canvas.height;\n const clientWidth = (\"clientWidth\" in canvas ? canvas.clientWidth : 0) || backingWidth;\n const clientHeight = (\"clientHeight\" in canvas ? canvas.clientHeight : 0) || backingHeight;\n const scaleX = backingWidth / clientWidth;\n const scaleY = backingHeight / clientHeight;\n const pickX = x * scaleX;\n const pickY = y * scaleY;\n const viewport = resolveCameraViewport(camera, backingWidth, backingHeight);\n const w = viewport.width;\n const h = viewport.height;\n if (w === 0 || h === 0) {\n return createEmptyPickingInfo();\n }\n\n if (pickX < viewport.x || pickY < viewport.y || pickX >= viewport.x + viewport.width || pickY >= viewport.y + viewport.height) {\n return createEmptyPickingInfo();\n }\n\n const px = Math.max(0, Math.min(Math.floor(pickX - viewport.x), w - 1));\n const py = Math.max(0, Math.min(Math.floor(pickY - viewport.y), h - 1));\n const aspect = w / h;\n const vp = getViewProjectionMatrix(camera, aspect);\n\n // ── Compute pick-zoomed VP (renders single pixel to 1×1 target) ──\n computePickVP(_pickVP, vp as Float32Array, px, py, w, h);\n\n const rt = ensureTargets(engine, picker);\n const sceneUbo = ensureSceneUbo(engine, picker);\n device.queue.writeBuffer(sceneUbo, 0, _pickVP);\n\n // ── Assign pick IDs (array-based, no Map for miss case) ──────────\n const meshes = scene.meshes;\n const meshCount = meshes.length;\n let nextId = 1;\n let deformedGeometry: typeof DeformedGeometry | null = null;\n for (let mi = 0; mi < meshCount; mi++) {\n const mesh = meshes[mi]!;\n if ((mesh.morphTargets || mesh.skeleton) && mesh._cpuPositions) {\n deformedGeometry = await import(\"./deformed-geometry.js\");\n break;\n }\n }\n\n // ── Render pass (1×1 target) ─────────────────────────────────────\n const encoder = device.createCommandEncoder({ label: \"pick\" });\n const pass = encoder.beginRenderPass({\n colorAttachments: [\n { view: rt.colorView, clearValue: { r: 0, g: 0, b: 0, a: 0 }, loadOp: \"clear\", storeOp: \"store\" },\n { view: rt.depthColorView, clearValue: { r: 1, g: 0, b: 0, a: 0 }, loadOp: \"clear\", storeOp: \"store\" },\n ],\n depthStencilAttachment: { view: rt.depthView, depthClearValue: 0, depthLoadOp: \"clear\", depthStoreOp: \"discard\" },\n });\n\n const regularPipeline = getPickingPipeline(engine);\n const tiPipeline = getPickingTIPipeline(engine);\n const meshBGL = getPickingMeshBGL(engine);\n const tiMeshBGL = getPickingTIMeshBGL(engine);\n\n const tempBuffers: GPUBuffer[] = [];\n for (let mi = 0; mi < meshCount; mi++) {\n const mesh = meshes[mi]!;\n const gpu = mesh._gpu;\n const ti = mesh.thinInstances;\n\n if (ti && ti.count > 0 && ti._gpuBuffer) {\n _tiUboScratch[0] = nextId;\n const tiUbo = createUniformBuffer(engine, _tiUboScratch);\n tempBuffers.push(tiUbo);\n\n pass.setPipeline(tiPipeline);\n pass.setBindGroup(0, picker._sceneBG!);\n pass.setBindGroup(\n 1,\n device.createBindGroup({\n layout: tiMeshBGL,\n entries: [\n { binding: 0, resource: { buffer: tiUbo } },\n { binding: 1, resource: { buffer: ti._gpuBuffer } },\n ],\n })\n );\n pass.setVertexBuffer(0, gpu.positionBuffer);\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.drawIndexed(gpu.indexCount, ti.count);\n nextId += ti.count;\n } else {\n _uboF32.set(mesh.worldMatrix);\n _uboU32[0] = nextId;\n const meshUbo = createUniformBuffer(engine, _uboView);\n tempBuffers.push(meshUbo);\n let positionBuffer = gpu.positionBuffer;\n if (deformedGeometry && (mesh.morphTargets || mesh.skeleton) && mesh._cpuPositions) {\n const deformedPositions = deformedGeometry.computeDeformedPositions(mesh);\n if (deformedPositions) {\n positionBuffer = createMappedBuffer(engine, deformedPositions, GPUBufferUsage.VERTEX);\n tempBuffers.push(positionBuffer);\n }\n }\n\n pass.setPipeline(regularPipeline);\n pass.setBindGroup(0, picker._sceneBG!);\n pass.setBindGroup(1, device.createBindGroup({ layout: meshBGL, entries: [{ binding: 0, resource: { buffer: meshUbo } }] }));\n pass.setVertexBuffer(0, positionBuffer);\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.drawIndexed(gpu.indexCount);\n nextId++;\n }\n }\n\n // ── Gaussian-splatting meshes ────────────────────────────────────\n // Drawn from the same pass against the same depth target. Each GS mesh\n // gets one pick id (no thin-instance support — BJS GS picking is per-mesh\n // too). The GS picking pipeline applies an independent pickMatrix to the\n // GS clip-space output so the EWA Jacobian / `u.focal` math stays intact.\n const gsMeshes = (scene as unknown as { _gsMeshes: GaussianSplattingMesh[] })._gsMeshes;\n const gsMeshCount = gsMeshes.length;\n const gsNextIdStart = nextId;\n if (gsMeshCount > 0) {\n const gsModule = await import(\"./gs-picking-pipeline.js\");\n gsModule.computeGsPickMatrix(_gsPickMatrix, px, py, w, h);\n gsModule.gsPickWritePickMatrixAndBind(pass, engine, _gsPickMatrix);\n const resMap = picker._gsMeshResources ?? (picker._gsMeshResources = new Map());\n for (let gi = 0; gi < gsMeshCount; gi++) {\n const gsMesh = gsMeshes[gi]!;\n let res = resMap.get(gsMesh);\n if (!res) {\n res = gsModule.createGsPickMeshResources(engine, gsMesh);\n resMap.set(gsMesh, res);\n }\n gsModule.drawGsForPicking(pass, engine, scene, gsMesh, res, nextId, w, h);\n nextId++;\n }\n }\n pass.end();\n\n // ── Readback (both 1×1 — trivially small) ────────────────────────\n encoder.copyTextureToBuffer({ texture: rt.colorTex }, { buffer: rt.colorStaging, bytesPerRow: 256 }, { width: 1, height: 1 });\n encoder.copyTextureToBuffer({ texture: rt.depthColorTex }, { buffer: rt.depthStaging, bytesPerRow: 256 }, { width: 1, height: 1 });\n device.queue.submit([encoder.finish()]);\n\n await Promise.all([rt.colorStaging.mapAsync(GPUMapMode.READ), rt.depthStaging.mapAsync(GPUMapMode.READ)]);\n\n const colorData = new Uint8Array(rt.colorStaging.getMappedRange());\n const pickId = (colorData[0]! << 16) | (colorData[1]! << 8) | colorData[2]!;\n const depth = new Float32Array(rt.depthStaging.getMappedRange())[0]!;\n rt.colorStaging.unmap();\n rt.depthStaging.unmap();\n\n // Destroy temp per-mesh UBOs\n for (let i = 0; i < tempBuffers.length; i++) {\n tempBuffers[i]!.destroy();\n }\n\n // ── Resolve pick ID to mesh ──────────────────────────────────────\n if (pickId === 0) {\n return createEmptyPickingInfo();\n }\n let hitMesh: Mesh | GaussianSplattingMesh | null = null;\n let hitThinIdx = -1;\n let hitIsGs = false;\n let scanId = 1;\n for (let mi = 0; mi < meshCount; mi++) {\n const mesh = meshes[mi]!;\n const ti = mesh.thinInstances;\n if (ti && ti.count > 0 && ti._gpuBuffer) {\n if (pickId >= scanId && pickId < scanId + ti.count) {\n hitMesh = mesh;\n hitThinIdx = pickId - scanId;\n break;\n }\n scanId += ti.count;\n } else {\n if (pickId === scanId) {\n hitMesh = mesh;\n break;\n }\n scanId++;\n }\n }\n if (!hitMesh && gsMeshCount > 0 && pickId >= gsNextIdStart) {\n const gsIdx = pickId - gsNextIdStart;\n if (gsIdx < gsMeshCount) {\n hitMesh = gsMeshes[gsIdx]!;\n hitIsGs = true;\n }\n }\n if (!hitMesh) {\n return createEmptyPickingInfo();\n }\n\n const info = createEmptyPickingInfo();\n info.hit = true;\n info.pickedMesh = hitMesh;\n info.thinInstanceIndex = hitThinIdx;\n\n // Reconstruct world position from depth (using original full-res VP)\n const invVP = mat4Invert(vp);\n if (invVP) {\n const ndcX = (2 * (pickX - viewport.x)) / w - 1;\n const ndcY = 1 - (2 * (pickY - viewport.y)) / h;\n const wx = invVP[0]! * ndcX + invVP[4]! * ndcY + invVP[8]! * depth + invVP[12]!;\n const wy = invVP[1]! * ndcX + invVP[5]! * ndcY + invVP[9]! * depth + invVP[13]!;\n const wz = invVP[2]! * ndcX + invVP[6]! * ndcY + invVP[10]! * depth + invVP[14]!;\n const ww = invVP[3]! * ndcX + invVP[7]! * ndcY + invVP[11]! * depth + invVP[15]!;\n const invW = 1 / ww;\n info.pickedPoint = [wx * invW, wy * invW, wz * invW];\n\n const camPos = getCameraPosition(camera);\n const dx = info.pickedPoint[0] - camPos.x;\n const dy = info.pickedPoint[1] - camPos.y;\n const dz = info.pickedPoint[2] - camPos.z;\n info.distance = Math.sqrt(dx * dx + dy * dy + dz * dz);\n }\n\n if (picker._detailedPick && !hitIsGs) {\n const ray = createPickingRay(pickX - viewport.x, pickY - viewport.y, vp, w, h);\n if (ray) {\n info.ray = ray;\n await picker._detailedPick(info, ray);\n }\n }\n\n return info;\n}\n\n/** Dispose GPU resources owned by this picker. */\nexport function disposePicker(picker: GpuPicker): void {\n if (picker._rt) {\n picker._rt.colorTex.destroy();\n picker._rt.depthColorTex.destroy();\n picker._rt.depthTex.destroy();\n picker._rt.colorStaging.destroy();\n picker._rt.depthStaging.destroy();\n picker._rt = null;\n }\n if (picker._sceneUbo) {\n picker._sceneUbo.destroy();\n picker._sceneUbo = null;\n picker._sceneBG = null;\n }\n if (picker._gsMeshResources) {\n // Async dispose — destroy() is synchronous so we can run inline once\n // the module is loaded. If the module was never imported (no GS pick\n // ever happened) the map is empty and there's nothing to do.\n void import(\"./gs-picking-pipeline.js\").then((m) => {\n if (!picker._gsMeshResources) {\n return;\n }\n for (const res of picker._gsMeshResources.values()) {\n m.disposeGsPickMeshResources(res);\n }\n picker._gsMeshResources = null;\n });\n }\n}\n","import type { Mesh } from \"../mesh/mesh.js\";\n\nexport function hasCpuDeformation(mesh: Mesh): boolean {\n return !!mesh._cpuPositions && (!!mesh.morphTargets || !!mesh.skeleton);\n}\n\nexport function computeDeformedPositions(mesh: Mesh): Float32Array | null {\n const base = mesh._cpuPositions;\n if (!base) {\n return null;\n }\n\n const out = new Float32Array(base);\n applyMorphPositions(mesh, out);\n applySkinPositions(mesh, out);\n return out;\n}\n\nexport function computeDeformedNormals(mesh: Mesh): Float32Array | null {\n const base = mesh._cpuNormals;\n if (!base) {\n return null;\n }\n\n const out = new Float32Array(base);\n applyMorphNormals(mesh, out);\n applySkinNormals(mesh, out);\n return out;\n}\n\nfunction applyMorphPositions(mesh: Mesh, out: Float32Array): void {\n const morph = mesh.morphTargets;\n if (!morph) {\n return;\n }\n\n const vertexCount = out.length / 3;\n const targetCount = Math.min(morph.count, morph.targets.length, 4);\n for (let t = 0; t < targetCount; t++) {\n const weight = morph.weights[t] ?? 0;\n if (weight === 0) {\n continue;\n }\n const positions = morph.targets[t]!.positions;\n for (let v = 0; v < vertexCount; v++) {\n const i = v * 3;\n out[i] = out[i]! + positions[i]! * weight;\n out[i + 1] = out[i + 1]! + positions[i + 1]! * weight;\n out[i + 2] = out[i + 2]! + positions[i + 2]! * weight;\n }\n }\n}\n\nfunction applyMorphNormals(mesh: Mesh, out: Float32Array): void {\n const morph = mesh.morphTargets;\n if (!morph) {\n return;\n }\n\n const vertexCount = out.length / 3;\n const targetCount = Math.min(morph.count, morph.targets.length, 4);\n for (let t = 0; t < targetCount; t++) {\n const weight = morph.weights[t] ?? 0;\n const normals = morph.targets[t]!.normals;\n if (weight === 0 || !normals) {\n continue;\n }\n for (let v = 0; v < vertexCount; v++) {\n const i = v * 3;\n out[i] = out[i]! + normals[i]! * weight;\n out[i + 1] = out[i + 1]! + normals[i + 1]! * weight;\n out[i + 2] = out[i + 2]! + normals[i + 2]! * weight;\n }\n }\n}\n\nfunction applySkinPositions(mesh: Mesh, out: Float32Array): void {\n const skeleton = mesh.skeleton;\n if (!skeleton) {\n return;\n }\n\n const source = new Float32Array(out);\n const vertexCount = out.length / 3;\n for (let v = 0; v < vertexCount; v++) {\n const i = v * 3;\n const x = source[i]!;\n const y = source[i + 1]!;\n const z = source[i + 2]!;\n const result = skinVec3(skeleton.boneMatrices, skeleton.joints, skeleton.weights, skeleton.joints1, skeleton.weights1, v, x, y, z, 1);\n out[i] = result[0];\n out[i + 1] = result[1];\n out[i + 2] = result[2];\n }\n}\n\nfunction applySkinNormals(mesh: Mesh, out: Float32Array): void {\n const skeleton = mesh.skeleton;\n if (!skeleton) {\n return;\n }\n\n const source = new Float32Array(out);\n const vertexCount = out.length / 3;\n for (let v = 0; v < vertexCount; v++) {\n const i = v * 3;\n const x = source[i]!;\n const y = source[i + 1]!;\n const z = source[i + 2]!;\n const result = skinVec3(skeleton.boneMatrices, skeleton.joints, skeleton.weights, skeleton.joints1, skeleton.weights1, v, x, y, z, 0);\n out[i] = result[0];\n out[i + 1] = result[1];\n out[i + 2] = result[2];\n }\n}\n\nfunction skinVec3(\n boneMatrices: Float32Array,\n joints: Uint16Array | Uint8Array,\n weights: Float32Array,\n joints1: Uint16Array | Uint8Array | null,\n weights1: Float32Array | null,\n vertexIndex: number,\n x: number,\n y: number,\n z: number,\n wCoord: 0 | 1\n): [number, number, number] {\n let rx = 0;\n let ry = 0;\n let rz = 0;\n const base = vertexIndex * 4;\n\n for (let i = 0; i < 4; i++) {\n const weight = weights[base + i] ?? 0;\n if (weight !== 0) {\n const joint = joints[base + i] ?? 0;\n const transformed = transformByBone(boneMatrices, joint, x, y, z, wCoord);\n rx += transformed[0] * weight;\n ry += transformed[1] * weight;\n rz += transformed[2] * weight;\n }\n }\n\n if (joints1 && weights1) {\n for (let i = 0; i < 4; i++) {\n const weight = weights1[base + i] ?? 0;\n if (weight !== 0) {\n const joint = joints1[base + i] ?? 0;\n const transformed = transformByBone(boneMatrices, joint, x, y, z, wCoord);\n rx += transformed[0] * weight;\n ry += transformed[1] * weight;\n rz += transformed[2] * weight;\n }\n }\n }\n\n return [rx, ry, rz];\n}\n\nfunction transformByBone(boneMatrices: Float32Array, joint: number, x: number, y: number, z: number, wCoord: 0 | 1): [number, number, number] {\n const o = joint * 16;\n return [\n boneMatrices[o]! * x + boneMatrices[o + 4]! * y + boneMatrices[o + 8]! * z + boneMatrices[o + 12]! * wCoord,\n boneMatrices[o + 1]! * x + boneMatrices[o + 5]! * y + boneMatrices[o + 9]! * z + boneMatrices[o + 13]! * wCoord,\n boneMatrices[o + 2]! * x + boneMatrices[o + 6]! * y + boneMatrices[o + 10]! * z + boneMatrices[o + 14]! * wCoord,\n ];\n}\n","import type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { GpuPicker } from \"./gpu-picker.js\";\nimport type { PickingInfo } from \"./picking-info.js\";\nimport type { Ray } from \"./ray.js\";\nimport { normalizeVec3 } from \"../math/normalize-vec3.js\";\nimport { computeDeformedPositions } from \"./deformed-geometry.js\";\n\n/**\n * Enable detailed picking on a GPU picker.\n * When enabled, pickAsync() will compute faceId, bu, bv\n * by performing CPU ray-triangle intersection on the identified mesh.\n * Requires meshes to have _cpuPositions and _cpuIndices set.\n */\nexport function enableDetailedPicking(picker: GpuPicker): void {\n picker._detailedPick = detailedPick;\n}\n\nasync function detailedPick(info: PickingInfo, ray: Ray): Promise<void> {\n const mesh = info.pickedMesh;\n const mi = mesh as Mesh | null;\n if (!mi || !mi._cpuPositions || !mi._cpuIndices) {\n return;\n }\n\n const deformedPositions = hasCpuDeformationData(mi) ? computeDeformedPositions(mi) : null;\n const positions = deformedPositions ?? mi._cpuPositions;\n const normals = mi._cpuNormals;\n const indices = mi._cpuIndices;\n\n // Determine the world matrix — use thin instance matrix when applicable\n let worldMatrix: Mat4 = mi.worldMatrix;\n if (info.thinInstanceIndex >= 0 && mi.thinInstances) {\n const offset = info.thinInstanceIndex * 16;\n worldMatrix = mi.thinInstances.matrices.subarray(offset, offset + 16) as unknown as Mat4;\n }\n\n const triCount = indices.length / 3;\n let closestT = Infinity;\n let closestFace = -1;\n let closestBu = 0;\n let closestBv = 0;\n\n for (let i = 0; i < triCount; i++) {\n const i0 = indices[i * 3]!;\n const i1 = indices[i * 3 + 1]!;\n const i2 = indices[i * 3 + 2]!;\n\n // Get vertex positions\n const ax = positions[i0 * 3]!,\n ay = positions[i0 * 3 + 1]!,\n az = positions[i0 * 3 + 2]!;\n const bx = positions[i1 * 3]!,\n by = positions[i1 * 3 + 1]!,\n bz = positions[i1 * 3 + 2]!;\n const cx = positions[i2 * 3]!,\n cy = positions[i2 * 3 + 1]!,\n cz = positions[i2 * 3 + 2]!;\n\n // Transform to world space using worldMatrix (column-major 4x4)\n const wax = worldMatrix[0]! * ax + worldMatrix[4]! * ay + worldMatrix[8]! * az + worldMatrix[12]!;\n const way = worldMatrix[1]! * ax + worldMatrix[5]! * ay + worldMatrix[9]! * az + worldMatrix[13]!;\n const waz = worldMatrix[2]! * ax + worldMatrix[6]! * ay + worldMatrix[10]! * az + worldMatrix[14]!;\n\n const wbx = worldMatrix[0]! * bx + worldMatrix[4]! * by + worldMatrix[8]! * bz + worldMatrix[12]!;\n const wby = worldMatrix[1]! * bx + worldMatrix[5]! * by + worldMatrix[9]! * bz + worldMatrix[13]!;\n const wbz = worldMatrix[2]! * bx + worldMatrix[6]! * by + worldMatrix[10]! * bz + worldMatrix[14]!;\n\n const wcx = worldMatrix[0]! * cx + worldMatrix[4]! * cy + worldMatrix[8]! * cz + worldMatrix[12]!;\n const wcy = worldMatrix[1]! * cx + worldMatrix[5]! * cy + worldMatrix[9]! * cz + worldMatrix[13]!;\n const wcz = worldMatrix[2]! * cx + worldMatrix[6]! * cy + worldMatrix[10]! * cz + worldMatrix[14]!;\n\n // Möller–Trumbore ray-triangle intersection\n const result = rayTriangleIntersect(\n ray.origin[0],\n ray.origin[1],\n ray.origin[2],\n ray.direction[0],\n ray.direction[1],\n ray.direction[2],\n ray.length,\n wax,\n way,\n waz,\n wbx,\n wby,\n wbz,\n wcx,\n wcy,\n wcz\n );\n\n if (result && result.t > 0 && result.t < closestT) {\n closestT = result.t;\n closestFace = i;\n closestBu = result.u;\n closestBv = result.v;\n }\n }\n\n if (closestFace >= 0) {\n const bjsBu = clampBarycentric(1 - closestBu - closestBv);\n info.faceId = closestFace;\n info.bu = bjsBu;\n info.bv = clampBarycentric(closestBu);\n info.distance = closestT;\n info.pickedPoint = [ray.origin[0] + ray.direction[0] * closestT, ray.origin[1] + ray.direction[1] * closestT, ray.origin[2] + ray.direction[2] * closestT];\n if (normals) {\n const i0 = indices[closestFace * 3]!;\n const i1 = indices[closestFace * 3 + 1]!;\n const i2 = indices[closestFace * 3 + 2]!;\n const bw = 1 - info.bu - info.bv;\n const localNormal = normalizeVec3(\n info.bu * normals[i0 * 3]! + info.bv * normals[i1 * 3]! + bw * normals[i2 * 3]!,\n info.bu * normals[i0 * 3 + 1]! + info.bv * normals[i1 * 3 + 1]! + bw * normals[i2 * 3 + 1]!,\n info.bu * normals[i0 * 3 + 2]! + info.bv * normals[i1 * 3 + 2]! + bw * normals[i2 * 3 + 2]!\n );\n const worldNormal = normalizeVec3(\n worldMatrix[0]! * localNormal[0] + worldMatrix[4]! * localNormal[1] + worldMatrix[8]! * localNormal[2],\n worldMatrix[1]! * localNormal[0] + worldMatrix[5]! * localNormal[1] + worldMatrix[9]! * localNormal[2],\n worldMatrix[2]! * localNormal[0] + worldMatrix[6]! * localNormal[1] + worldMatrix[10]! * localNormal[2]\n );\n const flip = worldNormal[0] * ray.direction[0] + worldNormal[1] * ray.direction[1] + worldNormal[2] * ray.direction[2] > 0;\n info.pickedNormal = flip ? [-localNormal[0], -localNormal[1], -localNormal[2]] : localNormal;\n info.pickedNormalWorld = flip ? [-worldNormal[0], -worldNormal[1], -worldNormal[2]] : worldNormal;\n }\n\n const i0 = indices[closestFace * 3]!;\n const i1 = indices[closestFace * 3 + 1]!;\n const i2 = indices[closestFace * 3 + 2]!;\n const ax = positions[i0 * 3]!;\n const ay = positions[i0 * 3 + 1]!;\n const az = positions[i0 * 3 + 2]!;\n const bx = positions[i1 * 3]!;\n const by = positions[i1 * 3 + 1]!;\n const bz = positions[i1 * 3 + 2]!;\n const cx = positions[i2 * 3]!;\n const cy = positions[i2 * 3 + 1]!;\n const cz = positions[i2 * 3 + 2]!;\n const faceNormal = normalizeVec3(\n (by - ay) * (cz - az) - (bz - az) * (cy - ay),\n (bz - az) * (cx - ax) - (bx - ax) * (cz - az),\n (bx - ax) * (cy - ay) - (by - ay) * (cx - ax)\n );\n const faceWorldNormal = normalizeVec3(\n worldMatrix[0]! * faceNormal[0] + worldMatrix[4]! * faceNormal[1] + worldMatrix[8]! * faceNormal[2],\n worldMatrix[1]! * faceNormal[0] + worldMatrix[5]! * faceNormal[1] + worldMatrix[9]! * faceNormal[2],\n worldMatrix[2]! * faceNormal[0] + worldMatrix[6]! * faceNormal[1] + worldMatrix[10]! * faceNormal[2]\n );\n const flip = faceWorldNormal[0] * ray.direction[0] + faceWorldNormal[1] * ray.direction[1] + faceWorldNormal[2] * ray.direction[2] > 0;\n info.pickedFaceNormal = flip ? [-faceNormal[0], -faceNormal[1], -faceNormal[2]] : faceNormal;\n info.pickedFaceNormalWorld = flip ? [-faceWorldNormal[0], -faceWorldNormal[1], -faceWorldNormal[2]] : faceWorldNormal;\n }\n}\n\nfunction clampBarycentric(value: number): number {\n return Math.abs(value) < 1e-12 ? 0 : value;\n}\n\nfunction hasCpuDeformationData(mesh: Mesh): boolean {\n const morph = mesh.morphTargets;\n const skeleton = mesh.skeleton;\n return (!!morph?.targets && !!morph.weights) || (!!skeleton?.boneMatrices && !!skeleton.joints && !!skeleton.weights);\n}\n\n/** Möller-Trumbore ray-triangle intersection with Babylon.js Ray epsilon semantics.\n * Returns `{ t, u, v }` or null if no intersection.\n * u and v are Möller weights for vertices 1 and 2; BJS exposes (1 - u - v, u). */\nfunction rayTriangleIntersect(\n ox: number,\n oy: number,\n oz: number,\n dx: number,\n dy: number,\n dz: number,\n length: number,\n v0x: number,\n v0y: number,\n v0z: number,\n v1x: number,\n v1y: number,\n v1z: number,\n v2x: number,\n v2y: number,\n v2z: number\n): { t: number; u: number; v: number } | null {\n const EPSILON = 0.001;\n\n // edge1 = v1 - v0, edge2 = v2 - v0\n const e1x = v1x - v0x,\n e1y = v1y - v0y,\n e1z = v1z - v0z;\n const e2x = v2x - v0x,\n e2y = v2y - v0y,\n e2z = v2z - v0z;\n\n // h = cross(direction, edge2)\n const hx = dy * e2z - dz * e2y;\n const hy = dz * e2x - dx * e2z;\n const hz = dx * e2y - dy * e2x;\n\n const det = e1x * hx + e1y * hy + e1z * hz;\n if (det === 0) {\n return null; // parallel\n }\n\n const invDet = 1 / det;\n\n // s = origin - v0\n const sx = ox - v0x,\n sy = oy - v0y,\n sz = oz - v0z;\n\n const u = (sx * hx + sy * hy + sz * hz) * invDet;\n if (u < -EPSILON || u > 1 + EPSILON) {\n return null;\n }\n\n // q = cross(s, edge1)\n const qx = sy * e1z - sz * e1y;\n const qy = sz * e1x - sx * e1z;\n const qz = sx * e1y - sy * e1x;\n\n const v = (dx * qx + dy * qy + dz * qz) * invDet;\n if (v < -EPSILON || u + v > 1 + EPSILON) {\n return null;\n }\n\n const t = (e2x * qx + e2y * qy + e2z * qz) * invDet;\n if (t > length || t < 0) {\n return null; // behind ray\n }\n\n return { t, u, v };\n}\n","import type { PickingInfo } from \"./picking-info.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { normalizeVec3 } from \"../math/normalize-vec3.js\";\n\n/**\n * Get the interpolated normal at the picked point.\n * Requires detailed picking (`faceId >= 0`) and mesh._cpuNormals.\n * @param useWorldCoordinates - if true, transform normal by world matrix (default: false)\n */\nexport function getPickedNormal(info: PickingInfo, useWorldCoordinates = false): [number, number, number] | null {\n if (useWorldCoordinates && info.pickedNormalWorld) {\n return info.pickedNormalWorld;\n }\n if (!useWorldCoordinates && info.pickedNormal) {\n return info.pickedNormal;\n }\n\n const mi = info.pickedMesh as Mesh | undefined;\n if (info.faceId < 0 || !mi || !mi._cpuNormals || !mi._cpuIndices) {\n return null;\n }\n\n const normals = mi._cpuNormals;\n const indices = mi._cpuIndices;\n const face = info.faceId;\n\n const i0 = indices[face * 3]!;\n const i1 = indices[face * 3 + 1]!;\n const i2 = indices[face * 3 + 2]!;\n\n // BJS exposes bu for vertex 0 and bv for vertex 1; vertex 2 gets the remainder.\n const bw = 1 - info.bu - info.bv;\n const nx = info.bu * normals[i0 * 3]! + info.bv * normals[i1 * 3]! + bw * normals[i2 * 3]!;\n const ny = info.bu * normals[i0 * 3 + 1]! + info.bv * normals[i1 * 3 + 1]! + bw * normals[i2 * 3 + 1]!;\n const nz = info.bu * normals[i0 * 3 + 2]! + info.bv * normals[i1 * 3 + 2]! + bw * normals[i2 * 3 + 2]!;\n\n const localNormal = normalizeVec3(nx, ny, nz);\n const wm = mi.worldMatrix;\n const wnx = wm[0]! * localNormal[0] + wm[4]! * localNormal[1] + wm[8]! * localNormal[2];\n const wny = wm[1]! * localNormal[0] + wm[5]! * localNormal[1] + wm[9]! * localNormal[2];\n const wnz = wm[2]! * localNormal[0] + wm[6]! * localNormal[1] + wm[10]! * localNormal[2];\n const worldNormal = normalizeVec3(wnx, wny, wnz);\n const flip = info.ray ? worldNormal[0] * info.ray.direction[0] + worldNormal[1] * info.ray.direction[1] + worldNormal[2] * info.ray.direction[2] > 0 : false;\n\n if (!useWorldCoordinates) {\n return flip ? [-localNormal[0], -localNormal[1], -localNormal[2]] : localNormal;\n }\n\n return flip ? [-worldNormal[0], -worldNormal[1], -worldNormal[2]] : worldNormal;\n}\n\nexport function getPickedFaceNormal(info: PickingInfo, useWorldCoordinates = false): [number, number, number] | null {\n if (useWorldCoordinates) {\n return info.pickedFaceNormalWorld;\n }\n return info.pickedFaceNormal;\n}\n\n/**\n * Get the interpolated UV coordinates at the picked point.\n * Requires detailed picking (`faceId >= 0`) and mesh._cpuUvs.\n */\nexport function getPickedUV(info: PickingInfo): [number, number] | null {\n const mi = info.pickedMesh as Mesh | undefined;\n if (info.faceId < 0 || !mi || !mi._cpuUvs || !mi._cpuIndices) {\n return null;\n }\n\n const uvs = mi._cpuUvs;\n const indices = mi._cpuIndices;\n const face = info.faceId;\n\n const i0 = indices[face * 3]!;\n const i1 = indices[face * 3 + 1]!;\n const i2 = indices[face * 3 + 2]!;\n\n const bw = 1 - info.bu - info.bv;\n const u = info.bu * uvs[i0 * 2]! + info.bv * uvs[i1 * 2]! + bw * uvs[i2 * 2]!;\n const v = info.bu * uvs[i0 * 2 + 1]! + info.bv * uvs[i1 * 2 + 1]! + bw * uvs[i2 * 2 + 1]!;\n\n return [u, v];\n}\n","/**\n * Sprite atlas — shared foundation for `Sprite2DLayer` (and, in later PRs,\n * billboards). A `SpriteAtlas` is a pure data record: a `Texture2D` plus\n * an immutable list of `SpriteFrame`s. The same atlas may back multiple\n * layers / scenes; lifetime is governed by the underlying `Texture2D`.\n *\n * PR 1 ships only the grid-based atlas constructor and the loader. Frames\n * are addressed by **integer index only**; a string-keyed wrapper type\n * (analogous to a future `NamedSpriteAtlas`) will land alongside the\n * TexturePacker JSON loader in a later PR.\n *\n * NOT YET IMPLEMENTED (intentionally omitted, see\n * `docs/lite/sprites/pr1-pure-2d-sprites-scope.md`):\n * - `SpriteClip` / `clips` field on the atlas (animation playback). Will\n * land as an additive change to `SpriteAtlas` in a follow-up PR.\n */\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { Texture2D, Texture2DOptions } from \"../../texture/texture-2d.js\";\nimport { loadTexture2D } from \"../../texture/texture-2d.js\";\n\n/** Texture sampling mode for a sprite atlas. */\nexport type SpriteSampling = \"linear\" | \"nearest\";\n\n/** A single frame in an atlas. UVs in [0,1]; pivot in [0,1] of the frame. */\nexport interface SpriteFrame {\n readonly name?: string;\n readonly uvMin: readonly [number, number];\n readonly uvMax: readonly [number, number];\n readonly sourceSizePx: readonly [number, number];\n readonly pivot: readonly [number, number];\n}\n\n/** A loaded sprite atlas — pure data, no methods. Frames are addressed by integer index. */\nexport interface SpriteAtlas {\n readonly texture: Texture2D;\n readonly textureSizePx: readonly [number, number];\n readonly frames: readonly SpriteFrame[];\n readonly premultipliedAlpha: boolean;\n}\n\n/** Options for `createGridSpriteAtlas`. */\nexport interface GridAtlasOptions {\n cellWidthPx: number;\n cellHeightPx: number;\n /** Defaults to `floor(textureWidth / cellWidthPx)`. */\n columns?: number;\n /** Defaults to `floor(textureHeight / cellHeightPx)`. */\n rows?: number;\n marginPx?: number;\n spacingPx?: number;\n /** Default `[0.5, 0.5]`. */\n pivot?: readonly [number, number];\n premultipliedAlpha?: boolean;\n}\n\n/** Options for `loadSpriteAtlas`. PR 1 supports the `gridSize` path only. */\nexport interface LoadAtlasOptions {\n /** Grid cell size `[w, h]` in pixels. Required in PR 1. */\n gridSize?: readonly [number, number];\n /** Reserved for future PR — TexturePacker-style JSON. Throws if used in PR 1. */\n metadataUrl?: string;\n sampling?: SpriteSampling;\n /** Marks the atlas as carrying premultiplied RGBA so the renderer picks the\n * premultiplied blend pipeline (`srcFactor: ONE`). Default `false` — matches\n * the bits PNG decoding produces. Set together with `premultiplyOnLoad: true`\n * for mathematically correct soft edges. Setting this `true` without\n * `premultiplyOnLoad: true` is only correct if the source image is *already*\n * premultiplied on disk (e.g. produced by a build step). */\n premultipliedAlpha?: boolean;\n /** Tell the texture loader to premultiply alpha at decode time\n * (`createImageBitmap({ premultiplyAlpha: \"premultiply\" })`). Default `false`.\n * Pair with `premultipliedAlpha: true` for the premultiplied blend pipeline. */\n premultiplyOnLoad?: boolean;\n textureOptions?: Texture2DOptions;\n}\n\n/**\n * Build a `SpriteAtlas` from a uniform grid over an existing texture. All\n * cells share the supplied pivot. Frames are emitted row-major (top-left\n * first). No name lookup map is populated because grid cells have no names.\n */\nexport function createGridSpriteAtlas(texture: Texture2D, options: GridAtlasOptions): SpriteAtlas {\n const cellW = options.cellWidthPx;\n const cellH = options.cellHeightPx;\n const margin = options.marginPx ?? 0;\n const spacing = options.spacingPx ?? 0;\n const cols = options.columns ?? Math.max(1, Math.floor((texture.width - margin * 2 + spacing) / (cellW + spacing)));\n const rows = options.rows ?? Math.max(1, Math.floor((texture.height - margin * 2 + spacing) / (cellH + spacing)));\n const pivot = options.pivot ?? [0.5, 0.5];\n\n const tw = texture.width;\n const th = texture.height;\n const frames: SpriteFrame[] = [];\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const x = margin + c * (cellW + spacing);\n const y = margin + r * (cellH + spacing);\n frames.push({\n uvMin: [x / tw, y / th],\n uvMax: [(x + cellW) / tw, (y + cellH) / th],\n sourceSizePx: [cellW, cellH],\n pivot: [pivot[0], pivot[1]],\n });\n }\n }\n\n return {\n texture,\n textureSizePx: [tw, th],\n frames,\n premultipliedAlpha: options.premultipliedAlpha ?? false,\n };\n}\n\n/**\n * Load a sprite atlas from an image URL. PR 1 supports only the\n * `gridSize` path: the texture is fetched as a non-Y-flipped image\n * (so atlas UVs map top-down with `(0,0)` at the image top-left) and\n * partitioned into a grid via `createGridSpriteAtlas`.\n */\nexport async function loadSpriteAtlas(engine: EngineContext, textureUrl: string, options: LoadAtlasOptions = {}): Promise<SpriteAtlas> {\n if (options.metadataUrl !== undefined) {\n throw new Error(\"loadSpriteAtlas: metadataUrl is not implemented in PR 1.\");\n }\n if (!options.gridSize) {\n throw new Error(\"loadSpriteAtlas: options.gridSize is required in PR 1.\");\n }\n\n const texOpts: Texture2DOptions = {\n // Sprite UVs are top-down (origin at image top-left); do not flip.\n invertY: false,\n // Atlas frames typically tile cleanly; use clamp to avoid bleeding from neighbouring cells at edges.\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n // Sprites usually look best with bilinear filtering and no mip chain — sharp pixel art still works in nearest.\n mipMaps: false,\n minFilter: options.sampling === \"nearest\" ? \"nearest\" : \"linear\",\n magFilter: options.sampling === \"nearest\" ? \"nearest\" : \"linear\",\n // Premultiply at decode if requested. Pair with `premultipliedAlpha: true` for\n // a mathematically honest premultiplied pipeline.\n premultiplyAlpha: options.premultiplyOnLoad ?? false,\n ...options.textureOptions,\n };\n\n const texture = await loadTexture2D(engine, textureUrl, texOpts);\n return createGridSpriteAtlas(texture, {\n cellWidthPx: options.gridSize[0],\n cellHeightPx: options.gridSize[1],\n // Default `false` — matches the straight RGBA bits the PNG decoder produces.\n // Callers wanting premultiplied blending should pass `premultiplyOnLoad: true`\n // *and* `premultipliedAlpha: true` together so storage and blend factors agree.\n premultipliedAlpha: options.premultipliedAlpha ?? false,\n });\n}\n\n/** @internal Resolve a frame index (just bounds-checks). Throws if out of range. */\nexport function resolveSpriteFrame(atlas: SpriteAtlas, frame: number): number {\n if (frame < 0 || frame >= atlas.frames.length) {\n throw new Error(`resolveSpriteFrame: index ${frame} out of range [0, ${atlas.frames.length})`);\n }\n return frame;\n}\n","/**\n * Runtime atlas packer — builds a `SpriteAtlas` from a set of in-memory RGBA\n * frames (decoded asset lumps, procedurally generated art, packed glyphs …).\n *\n * This is the runtime-frames analog to `createGridSpriteAtlas` (which slices an\n * existing grid texture): here the caller supplies each frame's pixels and the\n * packer shelf-packs them into one texture, uploads it, and emits the matching\n * `SpriteFrame` list. Frames are emitted in **input order** — `result.frames[i]`\n * corresponds to `sources[i]` — so callers can map their own per-frame metadata\n * by index. Each `SpriteFrame.name` carries the source `name` when supplied.\n *\n * Tree-shaken: importing this drags in nothing a plain sprite scene pays for.\n */\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport { createTexture2DFromPixels } from \"../../texture/pixels-texture.js\";\nimport type { SpriteAtlas, SpriteFrame, SpriteSampling } from \"./sprite-atlas.js\";\n\n/** One source frame for `createSpriteAtlasFromFrames`. */\nexport interface SpriteAtlasFrameSource {\n /** Tightly packed RGBA8 bytes — `width * height * 4`, row-major, top-to-bottom, straight alpha. */\n readonly pixels: Uint8Array;\n readonly width: number;\n readonly height: number;\n /** Pivot in [0,1] of the frame. Default `[0.5, 0.5]`. */\n readonly pivot?: readonly [number, number];\n /** Recorded on the emitted `SpriteFrame.name`. */\n readonly name?: string;\n}\n\n/** Options for `createSpriteAtlasFromFrames`. */\nexport interface SpriteAtlasPackOptions {\n /** Transparent gap (px) between packed frames; guards against bilinear bleed. Default `1`. */\n paddingPx?: number;\n /** Shelf width (px) before wrapping to a new row. Default `1024`. */\n maxWidthPx?: number;\n /** Min/mag filter for the packed texture. Default `\"nearest\"`. */\n sampling?: SpriteSampling;\n premultipliedAlpha?: boolean;\n}\n\n/**\n * Pack `sources` into a single `SpriteAtlas`. Shelf-packs in input order: each\n * frame is placed left-to-right on the current shelf, wrapping to a new shelf\n * (row) when it would overflow `maxWidthPx`. The texture is sized exactly to the\n * packed content.\n */\nexport function createSpriteAtlasFromFrames(engine: EngineContext, sources: readonly SpriteAtlasFrameSource[], options: SpriteAtlasPackOptions = {}): SpriteAtlas {\n if (sources.length === 0) {\n throw new Error(\"createSpriteAtlasFromFrames: at least one frame is required.\");\n }\n const padding = options.paddingPx ?? 1;\n const maxWidth = options.maxWidthPx ?? 1024;\n\n // Shelf-pack in input order; record each frame's top-left into xs/ys.\n const xs = new Array<number>(sources.length);\n const ys = new Array<number>(sources.length);\n let penX = 0;\n let penY = 0;\n let shelfHeight = 0;\n let atlasWidth = 1;\n for (let i = 0; i < sources.length; i++) {\n const s = sources[i]!;\n if (s.width < 1 || s.height < 1) {\n throw new Error(`createSpriteAtlasFromFrames: frame ${i} has non-positive size ${s.width}x${s.height}.`);\n }\n if (s.pixels.length < s.width * s.height * 4) {\n throw new Error(`createSpriteAtlasFromFrames: frame ${i} pixel buffer too short — need ${s.width * s.height * 4} bytes, got ${s.pixels.length}.`);\n }\n if (penX > 0 && penX + s.width > maxWidth) {\n penY += shelfHeight + padding;\n penX = 0;\n shelfHeight = 0;\n }\n xs[i] = penX;\n ys[i] = penY;\n const rightEdge = penX + s.width;\n if (rightEdge > atlasWidth) {\n atlasWidth = rightEdge;\n }\n penX = rightEdge + padding;\n if (s.height > shelfHeight) {\n shelfHeight = s.height;\n }\n }\n const atlasHeight = penY + shelfHeight;\n\n // Composite every frame into one transparent RGBA8 buffer.\n const data = new Uint8Array(atlasWidth * atlasHeight * 4);\n for (let i = 0; i < sources.length; i++) {\n const s = sources[i]!;\n const rowBytes = s.width * 4;\n for (let row = 0; row < s.height; row++) {\n const srcOffset = row * rowBytes;\n const dstOffset = ((ys[i]! + row) * atlasWidth + xs[i]!) * 4;\n data.set(s.pixels.subarray(srcOffset, srcOffset + rowBytes), dstOffset);\n }\n }\n\n const sampling: SpriteSampling = options.sampling ?? \"nearest\";\n const texture = createTexture2DFromPixels(engine, data, atlasWidth, atlasHeight, {\n minFilter: sampling,\n magFilter: sampling,\n });\n\n const frames = new Array<SpriteFrame>(sources.length);\n for (let i = 0; i < sources.length; i++) {\n const s = sources[i]!;\n frames[i] = {\n name: s.name,\n uvMin: [xs[i]! / atlasWidth, ys[i]! / atlasHeight],\n uvMax: [(xs[i]! + s.width) / atlasWidth, (ys[i]! + s.height) / atlasHeight],\n sourceSizePx: [s.width, s.height],\n pivot: s.pivot ?? [0.5, 0.5],\n };\n }\n\n return {\n texture,\n textureSizePx: [atlasWidth, atlasHeight],\n frames,\n premultipliedAlpha: options.premultipliedAlpha ?? false,\n };\n}\n","/**\n * @internal Shared `GPUBlendState` literals reused by the sprite and billboard blend\n * descriptors. Kept as separate top-level `const` bindings (pure object literals, zero\n * side effects) so a surface that only imports one descriptor pays for only the blend\n * state(s) it actually references — and the alpha/premultiplied states are defined once\n * instead of being duplicated between the sprite and billboard modules.\n */\n\n/** Straight-alpha over: color `{src-alpha, one-minus-src-alpha}`, alpha `{one, one-minus-src-alpha}`. */\nexport const _ALPHA_BLEND_STATE: GPUBlendState = {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n};\n\n/** Premultiplied over: color `{one, one-minus-src-alpha}`, alpha `{one, one-minus-src-alpha}`. */\nexport const _PREMULTIPLIED_BLEND_STATE: GPUBlendState = {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n};\n","/**\n * Sprite blend modes as importable, pure-data descriptor values.\n *\n * Each blend mode is its own top-level `const` binding, so a scene ships only the\n * descriptor(s) it imports — a default (alpha) scene references `spriteBlendAlpha` and\n * nothing else; importing `spriteBlendAdditive` does NOT drag in `spriteBlendPremultiplied`.\n * The sprite pipeline reads `_descriptor` / `_key` / `_premultipliedOpacity` directly off\n * the value, so there is no runtime string lookup table for the bundler to retain.\n */\nimport { _ALPHA_BLEND_STATE, _PREMULTIPLIED_BLEND_STATE } from \"./blend-descriptors.js\";\n\n/**\n * A sprite-layer blend descriptor. Pass one of the exported `spriteBlend*` values to\n * `createSprite2DLayer({ blendMode })`. The fields are internal plumbing; treat the value\n * as opaque.\n */\nexport interface SpriteBlendDescriptor {\n /** @internal Pipeline-cache discriminator (distinguishes blend variants of one pipeline). */\n readonly _key: string;\n /** @internal Color-target blend state; `undefined` means no color blend (opaque). */\n readonly _descriptor?: GPUBlendState;\n /** @internal When true, per-layer opacity scales RGB *and* A (premultiplied fade). */\n readonly _premultipliedOpacity?: boolean;\n}\n\n/**\n * Straight-alpha \"over\" blending (the default). RGB is composited by source alpha; this is\n * the standard transparency mode for HUDs, UI, and soft-edged sprites.\n */\nexport const spriteBlendAlpha: SpriteBlendDescriptor = {\n _key: \"alpha\",\n _descriptor: _ALPHA_BLEND_STATE,\n};\n\n/**\n * Premultiplied-alpha \"over\" blending. The sprite's RGB is assumed already multiplied by its\n * alpha; per-layer opacity scales RGB and A together for a correct fade.\n */\nexport const spriteBlendPremultiplied: SpriteBlendDescriptor = {\n _key: \"premultiplied\",\n _descriptor: _PREMULTIPLIED_BLEND_STATE,\n _premultipliedOpacity: true,\n};\n\n/**\n * Additive blending. The sprite's RGB, scaled by its own alpha, is added to the framebuffer,\n * so glows / light shafts / sparks stack and brighten (stars, embers, fireflies, sun shafts).\n */\nexport const spriteBlendAdditive: SpriteBlendDescriptor = {\n _key: \"additive\",\n _descriptor: {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n },\n};\n\n/**\n * Multiply blending. The framebuffer is multiplied by the sprite's RGB (`result = src * dst`),\n * so the sprite darkens / tints what is behind it — ideal for soft shadow blobs, dirt / grime\n * decals, ambient-occlusion stamps, and coloured \"gel\" overlays that modulate the scene colour.\n * Sprites should be opaque (or white where they must leave the background unchanged) since a pure\n * multiply ignores source alpha for RGB.\n */\nexport const spriteBlendMultiply: SpriteBlendDescriptor = {\n _key: \"multiply\",\n _descriptor: {\n color: { srcFactor: \"dst\", dstFactor: \"zero\", operation: \"add\" },\n alpha: { srcFactor: \"dst-alpha\", dstFactor: \"zero\", operation: \"add\" },\n },\n};\n","/**\n * Lazy, null-by-default registry hooks for the sprite-family custom-shader feature.\n *\n * The always-loaded sprite/billboard factory, pipeline, and renderer/renderable modules must\n * stay free of every custom-shader-specific symbol AND of the public `customShader` /\n * `shaderParams` field-name strings (both ship bytes into plain scenes). They reach the feature\n * exclusively through these hooks, which are `null` until a caller builds a custom shader —\n * `createSprite2DCustomShader` / `createBillboardCustomShader` register the impl. A plain scene\n * never imports the impl module, so the hook stays `null` and the always-loaded callers carry\n * zero custom-shader bytes — mirroring the PBR extension registry (`pbr-flags.ts`).\n *\n * The hook methods take the layer / system **opaquely** and perform all `customShader` /\n * `shaderParams` property access INSIDE the (tree-shaken) impl, so even the public field-name\n * strings stay out of the always-loaded path. No module-level side effects: the two hook slots\n * are plain nullable `let`s, registration is explicit.\n */\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Sprite2DLayer, Sprite2DLayerOptions } from \"./sprite-2d.js\";\nimport type { BillboardSpriteSystem, BillboardSpriteSystemOptions } from \"./billboard-sprite.js\";\nimport type { SpriteLayerFx } from \"./custom-shader-core.js\";\n\n/** @internal Generic 2D-sprite custom-shader hook. The impl reads `layer.customShader` / `layer.shaderParams`. */\nexport interface SpriteFxHook {\n /** Copy `opts.customShader` (+ a zeroed `shaderParams`) onto a freshly built layer, if present. */\n initLayer(layer: Sprite2DLayer, opts: Sprite2DLayerOptions): void;\n /** Extra pipeline-cache key part for `layer` (`\"\"` when it has no custom shader). */\n pipelineKeyPart(layer: Sprite2DLayer): string;\n /** Custom shader module for `layer`, or `null` to fall back to the default sprite shader. */\n shaderModule(engine: EngineContext, hasDepth: boolean, layer: Sprite2DLayer): GPUShaderModule | null;\n /** Extra bind-group-layout entries for `layer`, or `null` when it has no custom shader. */\n layoutEntries(layer: Sprite2DLayer, startBinding: number): GPUBindGroupLayoutEntry[] | null;\n /** Build the opaque fx attachment for `layer`, or `null` when it has no custom shader. */\n createLayerFx(engine: EngineContext, label: string, layer: Sprite2DLayer): SpriteLayerFx | null;\n /** Per-frame fx update (reads `layer.shaderParams`). */\n updateFx(fx: SpriteLayerFx, layer: Sprite2DLayer, deltaMs: number): void;\n /** Append the fx bind-group entries, starting at `startBinding` (always 3). */\n bindEntries(fx: SpriteLayerFx, startBinding: number): GPUBindGroupEntry[];\n /** Destroy the fx attachment. */\n disposeFx(fx: SpriteLayerFx): void;\n}\n\n/** @internal Generic billboard custom-shader hook. The impl reads `system._customShader` / `system.shaderParams`. */\nexport interface BillboardFxHook {\n /** Copy `opts.customShader` (+ a zeroed `shaderParams`) onto a freshly built system, if present. */\n initSystem(system: BillboardSpriteSystem, opts: BillboardSpriteSystemOptions): void;\n /** Extra pipeline-cache key part for `system` (`\"\"` when it has no custom shader). */\n pipelineKeyPart(system: BillboardSpriteSystem): string;\n /** Custom shader module for `system`, or `null` to fall back to the default billboard shader. */\n shaderModule(engine: EngineContext, system: BillboardSpriteSystem): GPUShaderModule | null;\n /** Extra bind-group-layout entries for `system`, or `null` when it has no custom shader. */\n layoutEntries(system: BillboardSpriteSystem, startBinding: number): GPUBindGroupLayoutEntry[] | null;\n /** Build the opaque fx attachment for `system`, or `null` when it has no custom shader. */\n createLayerFx(engine: EngineContext, label: string, system: BillboardSpriteSystem): SpriteLayerFx | null;\n /** Per-frame fx update (reads `system.shaderParams`). */\n updateFx(fx: SpriteLayerFx, system: BillboardSpriteSystem, deltaMs: number): void;\n /** Append the fx bind-group entries, starting at `startBinding` (always 3). */\n bindEntries(fx: SpriteLayerFx, startBinding: number): GPUBindGroupEntry[];\n /** Destroy the fx attachment. */\n disposeFx(fx: SpriteLayerFx): void;\n}\n\nlet _spriteFxHook: SpriteFxHook | null = null;\nlet _billboardFxHook: BillboardFxHook | null = null;\n\n/** @internal Register the 2D-sprite custom-shader hook. Idempotent; called by `createSprite2DCustomShader`. */\nexport function _registerSpriteFxHook(hook: SpriteFxHook): void {\n _spriteFxHook = hook;\n}\n/** @internal The registered 2D-sprite custom-shader hook, or `null` when no custom shader exists. */\nexport function _getSpriteFxHook(): SpriteFxHook | null {\n return _spriteFxHook;\n}\n/** @internal Register the billboard custom-shader hook. Idempotent; called by `createBillboardCustomShader`. */\nexport function _registerBillboardFxHook(hook: BillboardFxHook): void {\n _billboardFxHook = hook;\n}\n/** @internal The registered billboard custom-shader hook, or `null` when no custom shader exists. */\nexport function _getBillboardFxHook(): BillboardFxHook | null {\n return _billboardFxHook;\n}\n","/**\n * `Sprite2DLayer` — pixel-coordinate sprite layer. Pure-data interface +\n * standalone Index API for add / update / remove / setFrame. The layer is\n * owned by a `SpriteRenderer` (pure-2D / HUD `depth: \"none\"` path) or by a\n * scene renderable added through `addDepthHostedSpriteLayer`\n * (`depth: \"test\" | \"test-write\"`).\n *\n * The Index API stays the storage foundation. The optional Handle API lives in\n * `sprite-2d-handle.ts` and lazily installs hooks only when handles are used.\n */\nimport type { SpriteAtlas } from \"./shared/sprite-atlas.js\";\nimport { resolveSpriteFrame } from \"./shared/sprite-atlas.js\";\nimport type { Sprite2DCustomShader } from \"./sprite-custom-shader.js\";\nimport { _getSpriteFxHook } from \"./sprite-fx-hook.js\";\nimport type { SpriteBlendDescriptor } from \"./sprite-blend.js\";\nimport { spriteBlendAlpha } from \"./sprite-blend.js\";\n\n/**\n * Output blend mode for a sprite layer — a pure-data descriptor value. Import one of\n * `spriteBlendAlpha` (default), `spriteBlendPremultiplied`, or `spriteBlendAdditive` and pass\n * it as `Sprite2DLayerOptions.blendMode`. (Type alias of {@link SpriteBlendDescriptor}.)\n */\nexport type SpriteBlendMode = SpriteBlendDescriptor;\n\n/** Depth participation. `\"none\"` uses `SpriteRenderer`; depth-enabled modes use `addToScene`. */\nexport type Sprite2DDepthMode = \"none\" | \"test\" | \"test-write\";\n\n/** Per-layer 2D camera (pan / zoom / rotation). Identity = pixel-perfect HUD. */\nexport interface Sprite2DView {\n positionPx: [number, number];\n zoom: number;\n rotation: number;\n}\n\n/** Options accepted by `createSprite2DLayer`. */\nexport interface Sprite2DLayerOptions {\n capacity?: number;\n blendMode?: SpriteBlendMode;\n opacity?: number;\n visible?: boolean;\n order?: number;\n view?: Partial<Sprite2DView>;\n depth?: Sprite2DDepthMode;\n /**\n * Layer-wide rotation / scaling pivot in normalised sprite-local space\n * (`[0,0]` = top-left, `[0.5, 0.5]` = center, `[1,1]` = bottom-right).\n * The pivot point of every sprite in the layer lands at its `positionPx`\n * and is the center of `rotation`. Defaults to `[0.5, 0.5]` (center) to\n * match Babylon.js sprite behavior. Per-sprite / per-frame pivot is a\n * future PR — most 2D HUD layers want one uniform pivot anyway.\n */\n pivot?: [number, number];\n /**\n * Opt-in per-layer custom fragment shader (see `createSprite2DCustomShader`). Works on both\n * pure-2D (`depth: \"none\"`) layers drawn by a `SpriteRenderer` and depth-hosted\n * (`depth: \"test\" | \"test-write\"`) layers. Drives procedural effects (animated sky, clouds,\n * water / heat shimmer, twinkle, vignette) from a built-in `fx.time` clock plus an optional\n * `fx.params` vec4 set via `setSprite2DShaderParams`.\n */\n customShader?: Sprite2DCustomShader;\n /**\n * Default NDC depth (`0` = near, `1` = far) for sprites added to this layer when their\n * `Sprite2DProps.z` is omitted. Only meaningful for `depth: \"test\" | \"test-write\"` layers\n * (depth-hosted sprites added to a `SceneContext` via `addDepthHostedSpriteLayer`).\n *\n * Depth-hosted layers store one Z per sprite (slot [13] of their 14-float instance buffer),\n * so a single layer can mix sprites at different depths — e.g. one in front of a box, one\n * behind it. Pure-2D layers (`depth: \"none\"`) use the 13-float HUD layout and carry no Z slot.\n * Defaults to `0.5`. Mutating `layer.layerZ` after sprites have been added does **not**\n * retroactively change them; it only affects sprites added afterwards. To move an existing\n * depth-hosted sprite, call `updateSprite2DIndex(layer, idx, { z: … })`.\n */\n layerZ?: number;\n /**\n * Opt-in per-sprite UV scroll offset. When `true`, every sprite gains two extra instance\n * floats (`uvOffset.xy`) added to its sampled UV in the vertex stage — enabling parallax /\n * infinite-scroll backgrounds without re-uploading texture coordinates. Set the offset per\n * sprite via `Sprite2DProps.uvOffset` (on add) or `setSprite2DUvOffset` (live).\n *\n * **Zero cross-scene cost:** layers created without `uvScroll` keep the narrow 13/14-float\n * layout, the base vertex attributes, and the base WGSL — they ship none of the uvScroll\n * widening. The wider stride, the extra `@location(7)` attribute, and the `+ iUvOffset` WGSL\n * are gated directly on this per-layer flag. Defaults to `false`.\n *\n * Pairs naturally with a tileable atlas texture sampled in `repeat` wrap mode\n * (`loadSpriteAtlas(..., { textureOptions: { addressModeU: \"repeat\", addressModeV: \"repeat\" } })`).\n */\n uvScroll?: boolean;\n}\n\n/** A `Sprite2DLayer` — pure data, no methods. */\nexport interface Sprite2DLayer {\n /** @internal */\n readonly _entityType: \"sprite-2d-layer\";\n readonly atlas: SpriteAtlas;\n readonly depth: Sprite2DDepthMode;\n readonly blendMode: SpriteBlendMode;\n opacity: number;\n visible: boolean;\n order: number;\n view: Sprite2DView;\n /** Layer-wide pivot in normalised sprite-local space; see `Sprite2DLayerOptions.pivot`. */\n pivot: [number, number];\n /**\n * Opt-in custom fragment shader for this layer; see `Sprite2DLayerOptions.customShader`.\n * **Absent** (not `null`) on plain layers — never default-initialized, so the always-loaded\n * path carries zero custom-shader bytes (see `sprite-fx-hook.ts`). Present only when the\n * layer was created with a `customShader`.\n */\n readonly customShader?: Sprite2DCustomShader;\n /**\n * User `fx.params` vec4 fed to a custom shader each frame; mutate via `setSprite2DShaderParams`.\n * **Absent** on plain layers (only allocated for custom-shader layers, or lazily by the setter).\n */\n shaderParams?: [number, number, number, number];\n /**\n * @internal Opt-in per-sprite UV-scroll flag; see `Sprite2DLayerOptions.uvScroll`. **Absent** (not `false`)\n * on plain layers — never default-initialized, so the always-loaded path and every non-scroll\n * sprite scene keep the narrow layout and base shader. Present (`true`) only when the layer was\n * created with `uvScroll: true`, which widens the instance stride by two floats (`uvOffset.xy`).\n */\n readonly _uvScroll?: boolean;\n /** Default NDC depth for newly added sprites; see `Sprite2DLayerOptions.layerZ`. */\n layerZ: number;\n readonly count: number;\n\n /** @internal Capacity of the per-instance buffer (in sprites). */\n _capacity: number;\n /** @internal Per-instance stride in floats; 13 for pure-2D, 14 for depth-hosted. */\n readonly _instanceFloatsPerSprite: number;\n /** @internal Per-instance stride in bytes; 52 for pure-2D, 56 for depth-hosted. */\n readonly _instanceStrideBytes: number;\n /** @internal Per-instance CPU staging buffer; layout = `_instanceFloatsPerSprite` per sprite. */\n _instanceData: Float32Array;\n /**\n * @internal CPU-only side buffer holding the **true** (un-hidden) size of every sprite,\n * laid out as `[w0, h0, w1, h1, …]` (`SAVED_SIZE_FLOATS_PER_SPRITE` = 2 floats per sprite).\n *\n * **Invariant:** this buffer always holds the sprite's real size, regardless of visibility.\n * It exists because `visible: false` is implemented by zeroing the GPU-side size slots\n * (degenerate quad → free rasterizer cull) — a free hide on the GPU at the cost of 8 B per\n * sprite on the CPU. Without this shadow, a `visible: true` patch that omits `sizePx`\n * would have no way to recover the original size. Grown in lockstep with `_instanceData`.\n */\n _savedSize: Float32Array;\n /** @internal Bumped on any structural / per-instance edit; renderer compares. */\n _version: number;\n /** @internal Min dirty index inclusive (for partial uploads). */\n _dirtyMin: number;\n /** @internal Max dirty index exclusive. */\n _dirtyMax: number;\n /** @internal Optional hooks installed by the opt-in handle module. */\n _handleHooks?: Sprite2DIndexHandleHooks;\n}\n\n/** @internal Lazy hooks used by the opt-in Handle API to track swap-removes. */\nexport interface Sprite2DIndexHandleHooks {\n readonly removeIndex: (index: number, last: number) => void;\n readonly clear: () => void;\n}\n\n/** Per-sprite init record passed to `addSprite2DIndex` / `updateSprite2DIndex`. */\nexport interface Sprite2DProps {\n positionPx: [number, number];\n sizePx?: [number, number];\n frame?: number;\n rotation?: number;\n color?: [number, number, number, number];\n flipX?: boolean;\n flipY?: boolean;\n visible?: boolean;\n /** Reserved for picking. Accepted but unused today. */\n pickable?: boolean;\n /** Reserved for clip animation. Accepted but unused today. */\n clip?: unknown;\n /**\n * Per-sprite NDC depth (`0` = near, `1` = far). Only stored and consumed by depth-hosted\n * layers (`depth: \"test\" | \"test-write\"`); pure-2D HUD layers use a 13-float layout and\n * do not allocate a Z slot. When omitted on add for a depth-hosted layer, defaults to the\n * **owning layer's** `layerZ` at the moment of insertion. When omitted on update, the\n * sprite's existing Z is preserved. Mutate freely — the next binding update will re-upload\n * only the dirty range.\n */\n z?: number;\n /**\n * Per-sprite UV scroll offset added to the sampled UV in the vertex stage. Only stored and\n * consumed by `uvScroll` layers (created with `Sprite2DLayerOptions.uvScroll: true`); non-scroll\n * layers use the narrow 13/14-float layout and do not allocate a uvOffset slot. When omitted on\n * add for a uvScroll layer, defaults to `[0, 0]`. When omitted on update, the sprite's existing\n * offset is preserved. Live updates: `setSprite2DUvOffset`.\n */\n uvOffset?: [number, number];\n}\n\n/**\n * Pure-2D per-instance vertex layout (13 floats = 52 bytes, `depth: \"none\"`):\n * ```\n * [0..1] positionPx.xy (float32x2 @ offset 0)\n * [2..3] sizePx.xy (float32x2 @ offset 8)\n * [4..5] uvMin.xy (float32x2 @ offset 16)\n * [6..7] uvMax.xy (float32x2 @ offset 24)\n * [8] rotation (float32 @ offset 32)\n * [9..12] colorRGBA (float32x4 @ offset 36)\n * ```\n *\n * Depth-hosted layers (`depth: \"test\" | \"test-write\"`) extend this to 14 floats = 56 bytes:\n * ```\n * [13] z (NDC depth) (float32 @ offset 52, consumed only by depth-hosted pipelines)\n * ```\n *\n * `uvScroll` layers (created with `Sprite2DLayerOptions.uvScroll: true`) append two more floats\n * (`uvOffset.xy`) *after* the base layout, orthogonally to depth:\n * ```\n * pure-2D + uvScroll (15 floats = 60 bytes): [13..14] uvOffset.xy (float32x2 @ offset 52)\n * depth + uvScroll (16 floats = 64 bytes): [14..15] uvOffset.xy (float32x2 @ offset 56)\n * ```\n * The depth Z stays at slot [13]; uvOffset is appended after it. Non-scroll layers carry no\n * uvOffset slot and ship none of the widening (see `Sprite2DLayerOptions.uvScroll`).\n *\n * Visibility (`visible: false`) is implemented by zeroing slots [2..3]; the sprite's true\n * size lives in `layer._savedSize` so a later `visible: true` (without re-supplying\n * `sizePx`) can restore it. See `_savedSize` for the invariant.\n */\nexport const PURE_2D_INSTANCE_FLOATS_PER_SPRITE = 13;\nexport const DEPTH_INSTANCE_FLOATS_PER_SPRITE = 14;\n/** @internal Pure-2D per-sprite stride in bytes. */\nexport const PURE_2D_INSTANCE_STRIDE_BYTES = PURE_2D_INSTANCE_FLOATS_PER_SPRITE * 4;\n/** @internal Depth-hosted per-sprite stride in bytes. */\nexport const DEPTH_INSTANCE_STRIDE_BYTES = DEPTH_INSTANCE_FLOATS_PER_SPRITE * 4;\n/** @internal Extra floats appended per sprite when `uvScroll` is enabled: `uvOffset.xy`. */\nexport const UVSCROLL_EXTRA_FLOATS_PER_SPRITE = 2;\n/** @internal Pure-2D + uvScroll per-sprite stride in floats (13 + 2). */\nexport const PURE_2D_UVSCROLL_FLOATS_PER_SPRITE = PURE_2D_INSTANCE_FLOATS_PER_SPRITE + UVSCROLL_EXTRA_FLOATS_PER_SPRITE;\n/** @internal Depth-hosted + uvScroll per-sprite stride in floats (14 + 2). */\nexport const DEPTH_UVSCROLL_FLOATS_PER_SPRITE = DEPTH_INSTANCE_FLOATS_PER_SPRITE + UVSCROLL_EXTRA_FLOATS_PER_SPRITE;\n/** @internal Pure-2D + uvScroll per-sprite stride in bytes (60). */\nexport const PURE_2D_UVSCROLL_STRIDE_BYTES = PURE_2D_UVSCROLL_FLOATS_PER_SPRITE * 4;\n/** @internal Depth-hosted + uvScroll per-sprite stride in bytes (64). */\nexport const DEPTH_UVSCROLL_STRIDE_BYTES = DEPTH_UVSCROLL_FLOATS_PER_SPRITE * 4;\n/** @internal Per-sprite stride (in floats) of the `_savedSize` shadow buffer: `[w, h]`. */\nexport const SAVED_SIZE_FLOATS_PER_SPRITE = 2;\n\nconst DEFAULT_CAPACITY = 16;\n\n/** Create a new (empty) `Sprite2DLayer` backed by `atlas`. */\nexport function createSprite2DLayer(atlas: SpriteAtlas, opts: Sprite2DLayerOptions = {}): Sprite2DLayer {\n const depth = opts.depth ?? \"none\";\n const blendMode = opts.blendMode ?? spriteBlendAlpha;\n\n const capacity = Math.max(1, opts.capacity ?? DEFAULT_CAPACITY);\n const view: Sprite2DView = {\n positionPx: [opts.view?.positionPx?.[0] ?? 0, opts.view?.positionPx?.[1] ?? 0],\n zoom: opts.view?.zoom ?? 1,\n rotation: opts.view?.rotation ?? 0,\n };\n\n const uvScroll = opts.uvScroll === true;\n const baseFloatsPerSprite = depth === \"none\" ? PURE_2D_INSTANCE_FLOATS_PER_SPRITE : DEPTH_INSTANCE_FLOATS_PER_SPRITE;\n const instanceFloatsPerSprite = uvScroll ? baseFloatsPerSprite + UVSCROLL_EXTRA_FLOATS_PER_SPRITE : baseFloatsPerSprite;\n const instanceStrideBytes = instanceFloatsPerSprite * 4;\n const instanceData = new Float32Array(capacity * instanceFloatsPerSprite);\n const layer: Sprite2DLayer = {\n _entityType: \"sprite-2d-layer\",\n atlas,\n depth,\n blendMode,\n opacity: opts.opacity ?? 1,\n visible: opts.visible ?? true,\n order: opts.order ?? 0,\n view,\n pivot: [opts.pivot?.[0] ?? 0.5, opts.pivot?.[1] ?? 0.5],\n layerZ: opts.layerZ ?? 0.5,\n count: 0,\n _capacity: capacity,\n _instanceFloatsPerSprite: instanceFloatsPerSprite,\n _instanceStrideBytes: instanceStrideBytes,\n _instanceData: instanceData,\n _savedSize: new Float32Array(capacity * SAVED_SIZE_FLOATS_PER_SPRITE),\n _version: 0,\n _dirtyMin: 0,\n _dirtyMax: 0,\n };\n // Zero-default-init discipline: the base layer never names `_uvScroll`. Set it only when the\n // caller opted in, so plain layers keep the field off the always-loaded path and read as narrow.\n if (uvScroll) {\n (layer as { _uvScroll?: boolean })._uvScroll = true;\n }\n // Zero-default-init discipline: the base layer never names `customShader` / `shaderParams`.\n // When (and only when) a custom shader was supplied, the registered hook copies it on — the\n // impl lives in the tree-shaken `sprite-custom-shader` module, so plain scenes ship none of it.\n _getSpriteFxHook()?.initLayer(layer, opts);\n return layer;\n}\n\n/**\n * Set the user `fx.params` vec4 fed to this layer's custom shader (`createSprite2DCustomShader`)\n * each frame. No visual effect unless the layer was created with a `customShader`. Read in WGSL\n * as `fx.params`. Mutates in place; the renderer re-uploads the small FX UBO next frame.\n */\nexport function setSprite2DShaderParams(layer: Sprite2DLayer, params: readonly [number, number, number, number]): void {\n // Lazy-allocate: the base layer never names `shaderParams` (the custom-shader hook sets it only\n // when `opts.customShader` is present), so a plain layer keeps the field off the always-loaded path.\n const target = (layer.shaderParams ??= [0, 0, 0, 0]);\n target[0] = params[0];\n target[1] = params[1];\n target[2] = params[2];\n target[3] = params[3];\n}\n\n/**\n * Set the per-sprite UV scroll offset for one sprite of a `uvScroll` layer (live). The two floats\n * are added to the sprite's sampled UV in the vertex stage — driving parallax / infinite-scroll\n * backgrounds without re-uploading texture coordinates. Marks only this sprite's range dirty.\n *\n * Throws if the layer was not created with `Sprite2DLayerOptions.uvScroll: true` (non-scroll layers\n * carry no uvOffset slot) or if `index` is out of range.\n */\nexport function setSprite2DUvOffset(layer: Sprite2DLayer, index: number, uvOffset: readonly [number, number]): void {\n if (!layer._uvScroll) {\n throw new Error(\"setSprite2DUvOffset: layer was not created with uvScroll: true.\");\n }\n if (index < 0 || index >= layer.count) {\n throw new Error(`setSprite2DUvOffset: index ${index} out of range [0, ${layer.count})`);\n }\n const base = index * layer._instanceFloatsPerSprite;\n const uvSlot = base + (layer.depth !== \"none\" ? 14 : 13);\n layer._instanceData[uvSlot] = uvOffset[0];\n layer._instanceData[uvSlot + 1] = uvOffset[1];\n markDirty(layer, index, index + 1);\n}\n\nfunction growCapacity(layer: Sprite2DLayer, minCapacity: number): void {\n let cap = layer._capacity;\n while (cap < minCapacity) {\n cap *= 2;\n }\n const next = new Float32Array(cap * layer._instanceFloatsPerSprite);\n next.set(layer._instanceData);\n layer._instanceData = next;\n const nextSaved = new Float32Array(cap * SAVED_SIZE_FLOATS_PER_SPRITE);\n nextSaved.set(layer._savedSize);\n layer._savedSize = nextSaved;\n layer._capacity = cap;\n}\n\nfunction setSprite2DCount(layer: Sprite2DLayer, count: number): void {\n (layer as { count: number }).count = count;\n}\n\n/**\n * Write one sprite's instance data into `layer._instanceData[base..base+layer._instanceFloatsPerSprite]`.\n *\n * Two call sites with different shapes:\n * - **add**: `prev === null`. `props` is a full `Sprite2DProps` (positionPx required).\n * Unspecified fields take their documented defaults (size=frame.sourceSizePx or 0,\n * UVs=[0,0,1,1], rotation=0, color=opaque white, visible=true).\n * - **update**: `prev` is the existing per-layer instance slice. Unspecified fields are preserved.\n *\n * Resolution rules (per field): `props` value if given, else (on add) the default, else `prev`.\n * `frame` is a higher-level intent: when supplied it stomps the four UV slots from the atlas\n * (then `flipX`/`flipY` swap them). It does **not** by itself imply a size change — `sizePx`\n * remains independent — but on add, a missing `sizePx` falls back to `frame.sourceSizePx`.\n *\n * **Visibility model (the part that needs explaining):**\n * - `_savedSize[slot]` always stores the sprite's *true* size (unaffected by visibility).\n * - `data[base+2..+3]` (the GPU-visible size) is `_savedSize` when visible, else `(0, 0)`.\n * - We detect previous visibility by checking `prev[2]==0 && prev[3]==0` (only hidden sprites\n * have zeroed GPU size). The CPU shadow gives us back the true size for free.\n */\nfunction writeInstance(layer: Sprite2DLayer, slotIndex: number, props: Partial<Sprite2DProps>, prev: Float32Array | null): void {\n const data = layer._instanceData;\n const base = slotIndex * layer._instanceFloatsPerSprite;\n const savedBase = slotIndex * SAVED_SIZE_FLOATS_PER_SPRITE; // [w, h] per sprite\n const isAdd = prev === null;\n\n // Optional frame lookup (used for UV stomp + size default on add).\n const frame = props.frame !== undefined ? layer.atlas.frames[resolveSpriteFrame(layer.atlas, props.frame)]! : null;\n\n // ── Position (required on add; preserved on update if omitted) ──────────────────────\n const posX = props.positionPx ? props.positionPx[0] : prev![0]!;\n const posY = props.positionPx ? props.positionPx[1] : prev![1]!;\n\n // ── True size (props.sizePx → frame default → previous true size) ───────────────────\n // The shadow buffer makes \"previous true size\" cheap and unambiguous regardless of visibility.\n let trueW: number;\n let trueH: number;\n if (props.sizePx) {\n trueW = props.sizePx[0];\n trueH = props.sizePx[1];\n } else if (frame) {\n trueW = frame.sourceSizePx[0];\n trueH = frame.sourceSizePx[1];\n } else if (isAdd) {\n trueW = 0;\n trueH = 0;\n } else {\n trueW = layer._savedSize[savedBase]!;\n trueH = layer._savedSize[savedBase + 1]!;\n }\n layer._savedSize[savedBase] = trueW;\n layer._savedSize[savedBase + 1] = trueH;\n\n // ── Visibility (props.visible → preserved → default true on add) ────────────────────\n let visible: boolean;\n if (props.visible !== undefined) {\n visible = props.visible;\n } else if (isAdd) {\n visible = true;\n } else {\n // Previous sprite was hidden iff its GPU size was zeroed.\n visible = prev![2]! !== 0 || prev![3]! !== 0;\n }\n\n // ── UVs (frame stomps; else preserved; else default [0,0,1,1] on add) ───────────────\n // flipX/flipY apply on top, by swapping the U/V endpoints.\n let uMin: number;\n let vMin: number;\n let uMax: number;\n let vMax: number;\n if (frame) {\n uMin = frame.uvMin[0];\n vMin = frame.uvMin[1];\n uMax = frame.uvMax[0];\n vMax = frame.uvMax[1];\n } else if (isAdd) {\n uMin = 0;\n vMin = 0;\n uMax = 1;\n vMax = 1;\n } else {\n uMin = prev![4]!;\n vMin = prev![5]!;\n uMax = prev![6]!;\n vMax = prev![7]!;\n }\n if (props.flipX === true) {\n const t = uMin;\n uMin = uMax;\n uMax = t;\n }\n if (props.flipY === true) {\n const t = vMin;\n vMin = vMax;\n vMax = t;\n }\n\n // ── Rotation ────────────────────────────────────────────────────────────────────────\n const rotation = props.rotation ?? (prev ? prev[8]! : 0);\n\n // ── Per-instance Z (depth-hosted only) ──────────────────────────────────────────────\n // Pure-2D layers intentionally have no slot [13]; `z` is accepted by the public API but\n // not allocated, uploaded, declared, or fetched by HUD pipelines.\n const hasDepthSlot = layer.depth !== \"none\";\n const z = hasDepthSlot ? (props.z ?? (prev ? prev[13]! : layer.layerZ)) : 0;\n\n // ── Write the float slots ──────────────────────────────────────────────────────────\n data[base + 0] = posX;\n data[base + 1] = posY;\n data[base + 2] = visible ? trueW : 0;\n data[base + 3] = visible ? trueH : 0;\n data[base + 4] = uMin;\n data[base + 5] = vMin;\n data[base + 6] = uMax;\n data[base + 7] = vMax;\n data[base + 8] = rotation;\n\n // ── Color (float32x4 to match Babylon.js SpriteRenderer's color precision) ─────────\n if (props.color) {\n data[base + 9] = props.color[0];\n data[base + 10] = props.color[1];\n data[base + 11] = props.color[2];\n data[base + 12] = props.color[3];\n } else if (isAdd) {\n data[base + 9] = 1;\n data[base + 10] = 1;\n data[base + 11] = 1;\n data[base + 12] = 1;\n }\n // else: previous color floats are already in place — nothing to write.\n\n // ── Per-instance Z (slot [13], depth-hosted layout only) ───────────────────────────\n if (hasDepthSlot) {\n data[base + 13] = z;\n }\n\n // ── Per-sprite uvOffset (uvScroll layout only) ─────────────────────────────────────\n // Appended after the base layout: slot [13] for pure-2D, slot [14] for depth-hosted\n // (the depth Z keeps slot [13]). props → preserved → default [0,0] on add.\n if (layer._uvScroll) {\n const uvSlot = base + (hasDepthSlot ? 14 : 13);\n if (props.uvOffset) {\n data[uvSlot] = props.uvOffset[0];\n data[uvSlot + 1] = props.uvOffset[1];\n } else if (isAdd) {\n data[uvSlot] = 0;\n data[uvSlot + 1] = 0;\n }\n // else: previous uvOffset floats are already in place — nothing to write.\n }\n}\n\nfunction markDirty(layer: Sprite2DLayer, lo: number, hi: number): void {\n if (layer._dirtyMin >= layer._dirtyMax) {\n layer._dirtyMin = lo;\n layer._dirtyMax = hi;\n } else {\n if (lo < layer._dirtyMin) {\n layer._dirtyMin = lo;\n }\n if (hi > layer._dirtyMax) {\n layer._dirtyMax = hi;\n }\n }\n layer._version = (layer._version + 1) | 0;\n}\n\n/** Add one sprite. Returns its index. Grows capacity as needed. */\nexport function addSprite2DIndex(layer: Sprite2DLayer, props: Sprite2DProps): number {\n if (props.positionPx === undefined) {\n throw new Error(\"addSprite2DIndex: props.positionPx is required.\");\n }\n const idx = layer.count;\n if (idx >= layer._capacity) {\n growCapacity(layer, idx + 1);\n }\n writeInstance(layer, idx, props, null);\n setSprite2DCount(layer, layer.count + 1);\n markDirty(layer, idx, idx + 1);\n return idx;\n}\n\n/** Patch one sprite. Unspecified fields are preserved. */\nexport function updateSprite2DIndex(layer: Sprite2DLayer, index: number, patch: Partial<Sprite2DProps>): void {\n if (index < 0 || index >= layer.count) {\n throw new Error(`updateSprite2DIndex: index ${index} out of range [0, ${layer.count})`);\n }\n const base = index * layer._instanceFloatsPerSprite;\n const prev = layer._instanceData.subarray(base, base + layer._instanceFloatsPerSprite);\n writeInstance(layer, index, patch, prev);\n markDirty(layer, index, index + 1);\n}\n\n/** Swap-remove a sprite. The last sprite (if any) takes its slot. */\nexport function removeSprite2DIndex(layer: Sprite2DLayer, index: number): void {\n if (index < 0 || index >= layer.count) {\n throw new Error(`removeSprite2DIndex: index ${index} out of range [0, ${layer.count})`);\n }\n const last = layer.count - 1;\n layer._handleHooks?.removeIndex(index, last);\n if (index !== last) {\n layer._instanceData.copyWithin(index * layer._instanceFloatsPerSprite, last * layer._instanceFloatsPerSprite, (last + 1) * layer._instanceFloatsPerSprite);\n // Carry the swapped sprite's saved-size shadow with it (`[w, h]` per sprite).\n layer._savedSize.copyWithin(index * SAVED_SIZE_FLOATS_PER_SPRITE, last * SAVED_SIZE_FLOATS_PER_SPRITE, (last + 1) * SAVED_SIZE_FLOATS_PER_SPRITE);\n }\n // Clear the now-unused tail saved-size slot so a future re-add starts clean.\n layer._savedSize[last * SAVED_SIZE_FLOATS_PER_SPRITE] = 0;\n layer._savedSize[last * SAVED_SIZE_FLOATS_PER_SPRITE + 1] = 0;\n setSprite2DCount(layer, last);\n markDirty(layer, index, index + 1);\n}\n\n/** Clear all sprites from a layer while preserving allocated capacity. */\nexport function clearSprite2DLayer(layer: Sprite2DLayer): void {\n const count = layer.count;\n layer._dirtyMin = 0;\n layer._dirtyMax = 0;\n layer._handleHooks?.clear();\n if (count === 0) {\n return;\n }\n layer._savedSize.fill(0, 0, count * SAVED_SIZE_FLOATS_PER_SPRITE);\n setSprite2DCount(layer, 0);\n layer._version = (layer._version + 1) | 0;\n}\n\n/**\n * Update only the frame UVs for one sprite.\n *\n * The sprite keeps its explicit `sizePx`/saved size. For atlas-driven size\n * changes, call `updateSprite2DIndex(layer, index, { frame, sizePx })`.\n * Existing flip state is preserved for non-degenerate UV ranges.\n */\nexport function setSprite2DFrameIndex(layer: Sprite2DLayer, index: number, frame: number): void {\n if (index < 0 || index >= layer.count) {\n throw new Error(`setSprite2DFrameIndex: index ${index} out of range [0, ${layer.count})`);\n }\n const frameIdx = resolveSpriteFrame(layer.atlas, frame);\n const f = layer.atlas.frames[frameIdx]!;\n const base = index * layer._instanceFloatsPerSprite;\n const flipX = layer._instanceData[base + 4]! > layer._instanceData[base + 6]!;\n const flipY = layer._instanceData[base + 5]! > layer._instanceData[base + 7]!;\n layer._instanceData[base + 4] = flipX ? f.uvMax[0] : f.uvMin[0];\n layer._instanceData[base + 5] = flipY ? f.uvMax[1] : f.uvMin[1];\n layer._instanceData[base + 6] = flipX ? f.uvMin[0] : f.uvMax[0];\n layer._instanceData[base + 7] = flipY ? f.uvMin[1] : f.uvMax[1];\n markDirty(layer, index, index + 1);\n}\n","/**\n * Shared mechanics for the sprite-family custom-shader hooks (the engine owns the pipeline,\n * instancing, sorting, and vertex stage; the caller supplies only a WGSL **fragment body**\n * plus optional extra textures).\n *\n * This module holds **only** the parts that are identical across every sprite-family\n * custom-shader: extra-texture binding emission, WGSL-name validation, the always-present\n * `SpriteFx` UBO declaration, and cache-key allocation. Each system keeps its own composer\n * that owns its fixed vertex stage and varying contract — those genuinely differ (world-space\n * billboard facing vs. pixel-space 2D layer transform) and are not shared.\n *\n * Tree-shaking: a scene that never builds a custom shader never imports this module, so it\n * pays zero bytes for any of it. The GPU plumbing the custom-shader feature needs — the\n * `SpriteFx` UBO writer, the extra-texture / fx bind-group **layout** and **bind** entry\n * builders, and the per-device shader-module cache — also lives here (and is reached only\n * through a descriptor), so the always-loaded sprite/billboard pipeline + renderable modules\n * stay free of it.\n */\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { createEmptyUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\n\n/** One extra texture bound after the atlas. In WGSL it becomes `<name>Tex` + `<name>Samp`. */\nexport interface CustomShaderTexture {\n /** Identifier used in WGSL: becomes `<name>Tex` (texture) and `<name>Samp` (sampler). */\n readonly name: string;\n readonly texture: Texture2D;\n}\n\n/**\n * Opaque, per-layer / per-system **fx attachment**. Every piece of custom-shader runtime\n * state — the `SpriteFx` UBO buffer, its CPU scratch, and the accumulated elapsed time — lives\n * INSIDE this object, which is created (via a descriptor's `_createLayerFx` hook) only when a\n * layer/system actually has a custom shader.\n *\n * The always-loaded sprite/billboard renderer + renderable modules store a single nullable\n * `SpriteLayerFx | null` and reach the entire fx lifecycle (bind, per-frame update, dispose)\n * through it. A plain layer (no custom shader) allocates no fx fields, runs no fx branch, and\n * accumulates no time — the descriptor module that builds this object is never imported, so the\n * plain path pays zero bytes for the feature.\n */\nexport interface SpriteLayerFx {\n /** Append the extra-texture + fx UBO bind-group entries, starting at `startBinding` (always 3). */\n bindEntries(startBinding: number): GPUBindGroupEntry[];\n /** Accumulate `deltaMs` internally, then write the `SpriteFx` UBO (time + `params`). */\n update(params: readonly number[], deltaMs: number): void;\n /** Destroy the `SpriteFx` UBO buffer. */\n destroy(): void;\n}\n\n/** Valid WGSL identifier (used to validate extra-texture names before splicing them in). */\nconst WGSL_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** Shared all-zero `fx.params` fallback used when a layer/system has a custom shader but no params set. */\nexport const EMPTY_PARAMS: readonly number[] = [0, 0, 0, 0];\n\n/** Throw if any extra-texture name is not a legal WGSL identifier. `fnName` names the caller for the message. */\nexport function validateExtraTextureNames(fnName: string, extras: readonly CustomShaderTexture[]): void {\n for (const extra of extras) {\n if (!WGSL_NAME.test(extra.name)) {\n throw new Error(`${fnName}: extra texture name \"${extra.name}\" is not a valid WGSL identifier.`);\n }\n }\n}\n\n/**\n * Emit the `@group(group) @binding(n) var <name>Tex/<name>Samp` pairs for the extra textures,\n * starting at `startBinding` and stepping by 2 (texture, then sampler). The atlas occupies\n * bindings 1/2, so callers pass `startBinding = 3`.\n */\nexport function makeExtraBindingsWgsl(group: number, startBinding: number, extras: readonly CustomShaderTexture[]): string {\n let out = \"\";\n for (let i = 0; i < extras.length; i++) {\n const binding = startBinding + i * 2;\n const name = extras[i]!.name;\n out += `@group(${group}) @binding(${binding}) var ${name}Tex: texture_2d<f32>;\\n@group(${group}) @binding(${binding + 1}) var ${name}Samp: sampler;\\n`;\n }\n return out;\n}\n\n/**\n * Emit the always-present `SpriteFx` UBO declaration. The struct layout (32 bytes) matches the\n * CPU writer {@link writeSpriteFxUbo}:\n * [0] time (seconds since the renderable's first frame)\n * [1..3] padding (vec4 alignment)\n * [4..7] params.xyzw (user-set via `setSprite2DShaderParams` / `setBillboardShaderParams`)\n * `binding` is `3 + 2 * extraTextures.length` so the UBO always lands after the extra textures.\n */\nexport function makeFxStructWgsl(group: number, binding: number): string {\n return `struct SpriteFx {\ntime: f32,\n_p0: f32,\n_p1: f32,\n_p2: f32,\nparams: vec4<f32>,\n};\n@group(${group}) @binding(${binding}) var<uniform> fx: SpriteFx;`;\n}\n\nlet _nextKey = 0;\n\n/** Allocate a process-unique pipeline/shader-module cache key with the given prefix. */\nexport function nextCustomShaderKey(prefix: string): string {\n return `${prefix}${_nextKey++}`;\n}\n\n/**\n * Per-custom-shader `SpriteFx` UBO size in bytes. Bound at `@binding(3 + 2 * extraTextures.length)`.\n * Layout matches the WGSL `SpriteFx` struct emitted by {@link makeFxStructWgsl}:\n * [0] time (seconds since the renderable's first frame)\n * [1..3] padding (vec4 alignment)\n * [4..7] params.xyzw (user-set via `setSprite2DShaderParams` / `setBillboardShaderParams`)\n */\nexport const SPRITE_FX_UBO_BYTES = 32;\n/** Number of floats in the `SpriteFx` UBO scratch array. */\nexport const SPRITE_FX_UBO_FLOATS = SPRITE_FX_UBO_BYTES / 4;\n\n/** Write the `SpriteFx` UBO (time + user params) for a custom-shader layer/system. */\nexport function writeSpriteFxUbo(device: GPUDevice, fxBuffer: GPUBuffer, timeSeconds: number, params: readonly number[], scratch: Float32Array): void {\n scratch[0] = timeSeconds;\n scratch[1] = 0;\n scratch[2] = 0;\n scratch[3] = 0;\n scratch[4] = params[0] ?? 0;\n scratch[5] = params[1] ?? 0;\n scratch[6] = params[2] ?? 0;\n scratch[7] = params[3] ?? 0;\n device.queue.writeBuffer(fxBuffer, 0, scratch.buffer, scratch.byteOffset, SPRITE_FX_UBO_BYTES);\n}\n\n/**\n * Build the extra-texture + `SpriteFx` bind-group **layout** entries for a custom shader,\n * starting at `startBinding` (always 3 — the atlas occupies 0/1/2). Each extra texture\n * contributes a `texture` + `sampler` entry (stepping by 2); the fx UBO lands last at\n * `startBinding + 2 * extras.length`. Returned to the always-loaded pipeline builder, which\n * only appends them — keeping the custom-shader loop out of the plain path.\n */\nexport function makeCustomShaderLayoutEntries(extras: readonly CustomShaderTexture[], startBinding: number): GPUBindGroupLayoutEntry[] {\n const entries: GPUBindGroupLayoutEntry[] = [];\n let binding = startBinding;\n for (let i = 0; i < extras.length; i++) {\n entries.push({ binding, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } });\n entries.push({ binding: binding + 1, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } });\n binding += 2;\n }\n entries.push({ binding, visibility: GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } });\n return entries;\n}\n\n/**\n * Build the extra-texture + `SpriteFx` bind-group entries for a custom shader, mirroring the\n * layout produced by {@link makeCustomShaderLayoutEntries}. The fx UBO entry is emitted only\n * when `fxBuffer` is present.\n */\nexport function makeCustomShaderBindEntries(extras: readonly CustomShaderTexture[], startBinding: number, fxBuffer: GPUBuffer | null | undefined): GPUBindGroupEntry[] {\n const entries: GPUBindGroupEntry[] = [];\n let binding = startBinding;\n for (let i = 0; i < extras.length; i++) {\n const texture = extras[i]!.texture;\n entries.push({ binding, resource: texture.view });\n entries.push({ binding: binding + 1, resource: texture.sampler });\n binding += 2;\n }\n if (fxBuffer) {\n entries.push({ binding, resource: { buffer: fxBuffer } });\n }\n return entries;\n}\n\n/**\n * Build a per-layer / per-system fx attachment for a custom-shader descriptor. Allocates the\n * `SpriteFx` UBO + scratch, captures the descriptor's extra textures, and owns the elapsed-time\n * accumulator — all inside the returned closure. Exposed only through the descriptor's\n * `_createLayerFx` hook, so the always-loaded renderer/renderable modules never see the fx\n * machinery and the plain path pays nothing.\n */\nexport function createSpriteLayerFx(engine: EngineContext, label: string, extras: readonly CustomShaderTexture[]): SpriteLayerFx {\n const device = engine._device;\n const buffer = createEmptyUniformBuffer(engine, SPRITE_FX_UBO_BYTES, label);\n const scratch = new Float32Array(SPRITE_FX_UBO_FLOATS);\n let elapsedMs = 0;\n return {\n bindEntries(startBinding) {\n return makeCustomShaderBindEntries(extras, startBinding, buffer);\n },\n update(params, deltaMs) {\n elapsedMs += deltaMs;\n writeSpriteFxUbo(device, buffer, elapsedMs / 1000, params, scratch);\n },\n destroy() {\n buffer.destroy();\n },\n };\n}\n\n/**\n * Build a per-device shader-module cache for a single custom-shader descriptor. The returned\n * function compiles + caches one `GPUShaderModule` per `(device, key)` pair, auto-invalidating\n * when the engine's device changes (a new `WeakMap` entry). Lives on the descriptor so the\n * always-loaded pipeline cache no longer needs a custom-module `Map`.\n */\nexport function makeShaderModuleCache(): (engine: EngineContext, key: string, makeCode: () => string) => GPUShaderModule {\n let devices: WeakMap<GPUDevice, Map<string, GPUShaderModule>> | null = null;\n return (engine, key, makeCode) => {\n devices ??= new WeakMap();\n let byKey = devices.get(engine._device);\n if (!byKey) {\n byKey = new Map();\n devices.set(engine._device, byKey);\n }\n let module = byKey.get(key);\n if (!module) {\n module = engine._device.createShaderModule({ code: makeCode() });\n byKey.set(key, module);\n }\n return module;\n };\n}\n","/** Internal sprite pipeline helpers: owns WGSL, bind-group schema, pipeline construction, and bind-group creation. */\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Sprite2DLayer, SpriteBlendMode } from \"./sprite-2d.js\";\nimport type { SpriteLayerFx } from \"./custom-shader-core.js\";\nimport { _getSpriteFxHook } from \"./sprite-fx-hook.js\";\nimport { DEPTH_INSTANCE_STRIDE_BYTES, DEPTH_UVSCROLL_STRIDE_BYTES, PURE_2D_INSTANCE_STRIDE_BYTES, PURE_2D_UVSCROLL_STRIDE_BYTES } from \"./sprite-2d.js\";\n\n/** @internal */\nexport interface SpritePipelineDeviceCache {\n /** @internal */\n _shaderModule: GPUShaderModule | null;\n /** @internal */\n _sceneShaderModule: GPUShaderModule | null;\n /** @internal */\n _shaderModuleUv: GPUShaderModule | null;\n /** @internal */\n _sceneShaderModuleUv: GPUShaderModule | null;\n /** @internal */\n _pipelines: Map<string, GPURenderPipeline>;\n}\n\n/** @internal */\nexport interface SpritePipelineCache {\n /** @internal */\n _devices: WeakMap<GPUDevice, SpritePipelineDeviceCache>;\n}\n\nconst SPRITE_POSITION_OFFSET_BYTES = 0;\nconst SPRITE_SIZE_OFFSET_BYTES = 8;\nconst SPRITE_UV_MIN_OFFSET_BYTES = 16;\nconst SPRITE_UV_MAX_OFFSET_BYTES = 24;\nconst SPRITE_ROTATION_OFFSET_BYTES = 32;\nconst SPRITE_COLOR_OFFSET_BYTES = 36;\nconst SPRITE_DEPTH_OFFSET_BYTES = 52;\n/** uvOffset.xy byte offset: appended after the base layout (52 pure-2D, 56 depth-hosted). */\nconst SPRITE_UVOFFSET_OFFSET_PURE_2D_BYTES = 52;\nconst SPRITE_UVOFFSET_OFFSET_DEPTH_BYTES = 56;\n\nfunction makeSpriteWgsl(hasDepth: boolean, spriteGroupIndex: 0 | 1, uvScroll: boolean): string {\n return `${makeSpritePrologueWgsl(hasDepth, spriteGroupIndex, uvScroll)}\n@fragment\nfn fs(in: VOut) -> @location(0) vec4<f32> {\nlet s = textureSample(atlasTex, atlasSamp, in.uv);\nreturn s * in.tint * L.opacityMul;\n}`;\n}\n\n/**\n * Shared WGSL prologue for the sprite shader: the `Layer` UBO, atlas texture + sampler\n * bindings, instance-attribute `VIn` / interpolant `VOut` structs, and the `vs` vertex stage.\n * The default sprite shader appends a trivial textured fragment; the opt-in custom-shader\n * module (`createSprite2DCustomShader`) appends any extra-texture bindings, a `SpriteFx` UBO at\n * `@binding(3 + 2 * extraTextures.length)`, and the user's raw fragment body. Exposed so both\n * paths share one source of truth.\n */\nexport function makeSpritePrologueWgsl(hasDepth: boolean, spriteGroupIndex: 0 | 1, uvScroll = false): string {\n const group = `@group(${spriteGroupIndex})`;\n const zAttribute = hasDepth ? `,\\n@location(6) iZ: f32` : \"\";\n const uvOffsetAttribute = uvScroll ? `,\\n@location(7) iUvOffset: vec2<f32>` : \"\";\n const zPosition = hasDepth ? \"1.0 - in.iZ\" : \"0.0\";\n return `struct Layer {\nviewPos: vec2<f32>,\nviewScale: f32,\nviewRot: f32,\nscreenSize: vec2<f32>,\npivot: vec2<f32>,\n// Per-layer opacity, pre-shaped for the layer's blend mode (CPU-side):\n// straight-alpha: (1, 1, 1, opacity) — only alpha is scaled\n// premultiplied: (opacity, opacity, opacity, opacity) — RGB and A scale together\n// One uniform, no shader branch.\nopacityMul: vec4<f32>,\n};\n${group} @binding(0) var<uniform> L: Layer;\n${group} @binding(1) var atlasTex: texture_2d<f32>;\n${group} @binding(2) var atlasSamp: sampler;\nstruct VIn {\n@builtin(vertex_index) vid: u32,\n@location(0) iPos: vec2<f32>,\n@location(1) iSize: vec2<f32>,\n@location(2) iUvMin: vec2<f32>,\n@location(3) iUvMax: vec2<f32>,\n@location(4) iRot: f32,\n@location(5) iColor: vec4<f32>${zAttribute}${uvOffsetAttribute}\n};\nstruct VOut {\n@builtin(position) pos: vec4<f32>,\n@location(0) uv: vec2<f32>,\n@location(1) tint: vec4<f32>,\n};\n@vertex\nfn vs(in: VIn) -> VOut {\nvar corners = array<vec2<f32>, 4>(vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(1.0, 1.0), vec2<f32>(0.0, 1.0));\nlet c = corners[in.vid];\nlet local = (c - L.pivot) * in.iSize;\nlet cr = cos(in.iRot);\nlet sr = sin(in.iRot);\nlet rotated = vec2<f32>(local.x * cr - local.y * sr, local.x * sr + local.y * cr);\nlet layerPx = in.iPos + rotated;\nlet centered = layerPx - L.viewPos;\nlet lc = cos(L.viewRot);\nlet ls = sin(L.viewRot);\nlet viewRot = vec2<f32>(centered.x * lc - centered.y * ls, centered.x * ls + centered.y * lc);\nlet screenPx = viewRot * L.viewScale;\nlet ndc = vec2<f32>(screenPx.x / L.screenSize.x * 2.0 - 1.0, 1.0 - screenPx.y / L.screenSize.y * 2.0);\nlet uv = mix(in.iUvMin, in.iUvMax, c)${uvScroll ? \" + in.iUvOffset\" : \"\"};\nvar out: VOut;\nout.pos = vec4<f32>(ndc, ${zPosition}, 1.0);\nout.uv = uv;\nout.tint = in.iColor;\nreturn out;\n}`;\n}\n\nexport function createSpritePipelineCache(): SpritePipelineCache {\n return {\n _devices: new WeakMap(),\n };\n}\n\nexport function resetSpritePipelineCache(cache: SpritePipelineCache): void {\n cache._devices = new WeakMap();\n}\n\nexport function getSpritePipelineCacheSize(cache: SpritePipelineCache, device: GPUDevice): number {\n return cache._devices.get(device)?._pipelines.size ?? 0;\n}\n\nexport function getOrCreateSpritePipeline(\n engine: EngineContext,\n cache: SpritePipelineCache,\n format: GPUTextureFormat,\n sampleCount: 1 | 4,\n blendMode: SpriteBlendMode,\n hasDepth: boolean,\n depthWrite = false,\n depthStencilFormat?: GPUTextureFormat,\n sceneBindGroupLayout?: GPUBindGroupLayout,\n layer?: Sprite2DLayer\n): GPURenderPipeline {\n const deviceCache = getSpritePipelineDeviceCache(engine, cache);\n const resolvedDepthStencilFormat = normalizeDepthStencilFormat(hasDepth, depthStencilFormat);\n const key = spritePipelineKey(format, sampleCount, blendMode, hasDepth, depthWrite, resolvedDepthStencilFormat, layer);\n const cached = deviceCache._pipelines.get(key);\n if (cached) {\n return cached;\n }\n\n const pipeline = buildSpritePipeline(engine, deviceCache, format, sampleCount, blendMode, hasDepth, depthWrite, resolvedDepthStencilFormat, sceneBindGroupLayout, layer);\n deviceCache._pipelines.set(key, pipeline);\n return pipeline;\n}\n\nexport function createSpriteLayerBindGroup(\n engine: EngineContext,\n pipeline: GPURenderPipeline,\n spriteBindGroupIndex: 0 | 1,\n layer: Sprite2DLayer,\n uniformBuffer: GPUBuffer,\n fx?: SpriteLayerFx | null\n): GPUBindGroup {\n const tex = layer.atlas.texture;\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: uniformBuffer } },\n { binding: 1, resource: tex.view },\n { binding: 2, resource: tex.sampler },\n ];\n if (fx) {\n for (const entry of _getSpriteFxHook()!.bindEntries(fx, 3)) {\n entries.push(entry);\n }\n }\n return engine._device.createBindGroup({\n layout: pipeline.getBindGroupLayout(spriteBindGroupIndex),\n entries,\n });\n}\n\nfunction getSpritePipelineDeviceCache(engine: EngineContext, cache: SpritePipelineCache): SpritePipelineDeviceCache {\n let deviceCache = cache._devices.get(engine._device);\n if (!deviceCache) {\n deviceCache = {\n _shaderModule: null,\n _sceneShaderModule: null,\n _shaderModuleUv: null,\n _sceneShaderModuleUv: null,\n _pipelines: new Map(),\n };\n cache._devices.set(engine._device, deviceCache);\n }\n return deviceCache;\n}\n\nfunction normalizeDepthStencilFormat(hasDepth: boolean, depthStencilFormat?: GPUTextureFormat): GPUTextureFormat | null {\n if (!hasDepth) {\n return null;\n }\n if (!depthStencilFormat) {\n throw new Error(\"Sprite pipeline: depth-enabled pipelines require a depth-stencil format.\");\n }\n return depthStencilFormat;\n}\n\nfunction spritePipelineKey(\n format: GPUTextureFormat,\n sampleCount: number,\n blendMode: SpriteBlendMode,\n hasDepth: boolean,\n depthWrite: boolean,\n depthStencilFormat: GPUTextureFormat | null,\n layer?: Sprite2DLayer\n): string {\n const customKey = layer ? (_getSpriteFxHook()?.pipelineKeyPart(layer) ?? \"\") : \"\";\n const uvKey = layer?._uvScroll ? \"1\" : \"0\";\n return `${format}:${sampleCount}:${blendMode._key}:${hasDepth ? 1 : 0}:${depthWrite ? 1 : 0}:${depthStencilFormat ?? \"-\"}:cs${customKey}:uv${uvKey}`;\n}\n\nfunction getShaderModule(engine: EngineContext, cache: SpritePipelineDeviceCache, hasDepth: boolean, layer?: Sprite2DLayer): GPUShaderModule {\n const customModule = layer ? _getSpriteFxHook()?.shaderModule(engine, hasDepth, layer) : null;\n if (customModule) {\n return customModule;\n }\n const uvScroll = layer?._uvScroll === true;\n if (hasDepth) {\n if (uvScroll) {\n cache._sceneShaderModuleUv ??= engine._device.createShaderModule({ code: makeSpriteWgsl(true, 1, true) });\n return cache._sceneShaderModuleUv;\n }\n cache._sceneShaderModule ??= engine._device.createShaderModule({ code: makeSpriteWgsl(true, 1, false) });\n return cache._sceneShaderModule;\n }\n if (uvScroll) {\n cache._shaderModuleUv ??= engine._device.createShaderModule({ code: makeSpriteWgsl(false, 0, true) });\n return cache._shaderModuleUv;\n }\n cache._shaderModule ??= engine._device.createShaderModule({ code: makeSpriteWgsl(false, 0, false) });\n return cache._shaderModule;\n}\n\nfunction buildSpritePipeline(\n engine: EngineContext,\n cache: SpritePipelineDeviceCache,\n format: GPUTextureFormat,\n sampleCount: 1 | 4,\n blendMode: SpriteBlendMode,\n hasDepth: boolean,\n depthWrite: boolean,\n depthStencilFormat: GPUTextureFormat | null,\n sceneBindGroupLayout?: GPUBindGroupLayout,\n layer?: Sprite2DLayer\n): GPURenderPipeline {\n const device = engine._device;\n const layoutEntries: GPUBindGroupLayoutEntry[] = [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n ];\n const extraLayoutEntries = layer ? _getSpriteFxHook()?.layoutEntries(layer, 3) : null;\n if (extraLayoutEntries) {\n for (const entry of extraLayoutEntries) {\n layoutEntries.push(entry);\n }\n }\n const bindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });\n const module = getShaderModule(engine, cache, hasDepth, layer);\n if (hasDepth && !sceneBindGroupLayout) {\n throw new Error(\"Sprite pipeline: depth-enabled pipelines require a scene bind-group layout.\");\n }\n const bindGroupLayouts = hasDepth ? [sceneBindGroupLayout!, bindGroupLayout] : [bindGroupLayout];\n const instanceAttributes: GPUVertexAttribute[] = [\n { shaderLocation: 0, offset: SPRITE_POSITION_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 1, offset: SPRITE_SIZE_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 2, offset: SPRITE_UV_MIN_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 3, offset: SPRITE_UV_MAX_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 4, offset: SPRITE_ROTATION_OFFSET_BYTES, format: \"float32\" },\n { shaderLocation: 5, offset: SPRITE_COLOR_OFFSET_BYTES, format: \"float32x4\" },\n ];\n if (hasDepth) {\n instanceAttributes.push({ shaderLocation: 6, offset: SPRITE_DEPTH_OFFSET_BYTES, format: \"float32\" });\n }\n const uvScroll = layer?._uvScroll === true;\n if (uvScroll) {\n instanceAttributes.push({\n shaderLocation: 7,\n offset: hasDepth ? SPRITE_UVOFFSET_OFFSET_DEPTH_BYTES : SPRITE_UVOFFSET_OFFSET_PURE_2D_BYTES,\n format: \"float32x2\",\n });\n }\n const arrayStride = uvScroll\n ? hasDepth\n ? DEPTH_UVSCROLL_STRIDE_BYTES\n : PURE_2D_UVSCROLL_STRIDE_BYTES\n : hasDepth\n ? DEPTH_INSTANCE_STRIDE_BYTES\n : PURE_2D_INSTANCE_STRIDE_BYTES;\n const descriptor: GPURenderPipelineDescriptor = {\n layout: device.createPipelineLayout({ bindGroupLayouts }),\n vertex: {\n module,\n entryPoint: \"vs\",\n buffers: [\n {\n arrayStride: arrayStride,\n stepMode: \"instance\",\n attributes: instanceAttributes,\n },\n ],\n },\n fragment: {\n module,\n entryPoint: \"fs\",\n targets: [{ format, blend: blendMode._descriptor, writeMask: GPUColorWrite.ALL }],\n },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n multisample: { count: sampleCount },\n };\n if (hasDepth) {\n descriptor.depthStencil = {\n format: depthStencilFormat!,\n depthCompare: \"greater-equal\",\n depthWriteEnabled: depthWrite,\n };\n }\n return device.createRenderPipeline(descriptor);\n}\n\n// ─── Per-layer GPU sync helpers ────────────────────────────────────────────\n// Shared by `sprite-renderer.ts` (multi-layer pure-2D pass) and\n// `sprite-renderable.ts` (single-layer depth-hosted scene `Renderable`).\n// The two consumers have different lifecycles (renderer caches a `LayerGpu`\n// per layer; renderable owns one `Sprite2DLayer`) but the per-frame work —\n// \"grow instance buffer if needed\", \"upload dirty instance range\",\n// \"build the 12-float UBO\", \"writeBuffer only if changed\" — is identical.\n\n/** Per-layer UBO size in bytes. 12 floats; struct alignment forced to 16 by `vec4<f32>` fields. */\nexport const LAYER_UBO_BYTES = 48;\n/** Number of floats in the per-layer UBO scratch / lastUbo arrays. */\nexport const LAYER_UBO_FLOATS = LAYER_UBO_BYTES / 4;\n\n/** Shared two-triangle quad index buffer source (4 corners → 6 indices). */\nexport const SHARED_SPRITE_INDEX_DATA: Readonly<Uint16Array> = new Uint16Array([0, 1, 2, 0, 2, 3]);\n\n/** Allocate a per-layer instance vertex buffer sized for `capacity` sprites. */\nexport function createSpriteInstanceBuffer(device: GPUDevice, layer: Sprite2DLayer, label?: string): GPUBuffer {\n return device.createBuffer({\n size: layer._capacity * layer._instanceStrideBytes,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n label,\n });\n}\n\n/**\n * Reallocate the instance buffer if `layer._capacity` outgrew the current GPU buffer.\n * Returns the (possibly new) buffer + the new capacity, plus a `reallocated` flag the\n * caller uses to invalidate per-buffer caches (render bundles, `uploadedVersion`, etc).\n */\nexport function ensureSpriteInstanceBuffer(\n device: GPUDevice,\n layer: Sprite2DLayer,\n currentBuffer: GPUBuffer,\n currentCapacity: number,\n label?: string\n): { buffer: GPUBuffer; capacity: number; reallocated: boolean } {\n if (currentCapacity >= layer._capacity) {\n return { buffer: currentBuffer, capacity: currentCapacity, reallocated: false };\n }\n currentBuffer.destroy();\n return {\n buffer: createSpriteInstanceBuffer(device, layer, label),\n capacity: layer._capacity,\n reallocated: true,\n };\n}\n\n/**\n * Sync per-instance vertex data to `instanceBuffer`. Returns the new `uploadedVersion`\n * the caller should store. No-op if `layer._version` hasn't advanced or the layer is\n * empty. On first sight (`uploadedVersion === -1`) uploads `[0, count)`; on subsequent\n * edits uploads only `[_dirtyMin, min(_dirtyMax, count))`. Resets the dirty range.\n */\nexport function uploadSpriteInstances(device: GPUDevice, layer: Sprite2DLayer, instanceBuffer: GPUBuffer, uploadedVersion: number): number {\n if (uploadedVersion === layer._version) {\n return uploadedVersion;\n }\n if (layer.count === 0) {\n layer._dirtyMin = 0;\n layer._dirtyMax = 0;\n return layer._version;\n }\n let lo: number;\n let hi: number;\n if (uploadedVersion === -1) {\n lo = 0;\n hi = layer.count;\n } else {\n lo = layer._dirtyMin;\n hi = Math.min(layer._dirtyMax, layer.count);\n }\n if (hi > lo) {\n const offsetBytes = lo * layer._instanceStrideBytes;\n const bytes = (hi - lo) * layer._instanceStrideBytes;\n device.queue.writeBuffer(instanceBuffer, offsetBytes, layer._instanceData.buffer, layer._instanceData.byteOffset + offsetBytes, bytes);\n }\n layer._dirtyMin = 0;\n layer._dirtyMax = 0;\n return layer._version;\n}\n\n/**\n * Fill `ubo` (12 floats) with the per-layer UBO contents from `layer` at the given\n * render-target dims. Layout matches the WGSL `Layer` struct (48 bytes total):\n * [0..1] viewPos.xy [2] viewScale [3] viewRot\n * [4..5] screenSize.xy [6..7] pivot.xy\n * [8..11] opacityMul.rgba (pre-shaped per blend mode)\n *\n * Depth-hosted layers keep per-sprite NDC depth on the per-instance vertex buffer\n * (slot [13] of `Sprite2DLayer._instanceData`), not in this UBO — a single\n * depth-hosted layer can mix sprites at different depths. Pure-2D layers have no\n * Z slot.\n *\n * Premultiplied sources need RGB *and* A scaled by opacity for a correct fade;\n * straight-alpha needs only A scaled (the blend stage already uses src.a as factor).\n */\nexport function buildSpriteLayerUbo(layer: Sprite2DLayer, screenWidth: number, screenHeight: number, ubo: Float32Array): void {\n ubo[0] = layer.view.positionPx[0];\n ubo[1] = layer.view.positionPx[1];\n ubo[2] = layer.view.zoom;\n ubo[3] = layer.view.rotation;\n ubo[4] = screenWidth;\n ubo[5] = screenHeight;\n ubo[6] = layer.pivot[0];\n ubo[7] = layer.pivot[1];\n const op = layer.opacity;\n if (layer.blendMode._premultipliedOpacity) {\n ubo[8] = op;\n ubo[9] = op;\n ubo[10] = op;\n ubo[11] = op;\n } else {\n ubo[8] = 1;\n ubo[9] = 1;\n ubo[10] = 1;\n ubo[11] = op;\n }\n}\n\n/**\n * Compare `scratchUbo` to `lastUbo` (LAYER_UBO_FLOATS each) and `writeBuffer` only if they\n * differ. On first call (`alreadyUploaded === false`) forces an unconditional write\n * so `lastUbo` becomes real. Returns the new `alreadyUploaded` value (always `true`\n * after the first call regardless of whether bytes changed).\n */\nexport function writeSpriteLayerUboIfDirty(device: GPUDevice, uniformBuffer: GPUBuffer, scratchUbo: Float32Array, lastUbo: Float32Array, alreadyUploaded: boolean): boolean {\n let dirty = !alreadyUploaded;\n if (!dirty) {\n for (let i = 0; i < LAYER_UBO_FLOATS; i++) {\n if (lastUbo[i] !== scratchUbo[i]) {\n dirty = true;\n break;\n }\n }\n }\n if (dirty) {\n device.queue.writeBuffer(uniformBuffer, 0, scratchUbo.buffer, scratchUbo.byteOffset, LAYER_UBO_BYTES);\n lastUbo.set(scratchUbo);\n }\n return true;\n}\n","/**\n * Optional, tree-shakable custom-shader hook for `Sprite2DLayer` (the engine owns the layer\n * transform, instancing, sorting, and depth; the caller supplies only a WGSL **fragment body**\n * plus optional extra textures).\n *\n * Works on both pure-2D HUD layers (`depth: \"none\"`, drawn by a `SpriteRenderer`) and\n * depth-hosted 2.5D layers (`depth: \"test\"` / `\"test-write\"`, drawn as scene `Renderable`s).\n * The 2D and billboard composers share their *mechanics* via `custom-shader-core.ts`\n * (extra-texture bindings, name validation, the `SpriteFx` UBO, key allocation) but keep their\n * own vertex stage and varying contract, which genuinely differ: billboards transform in world\n * space and expose `viewDist`/`worldPos`; a 2D layer transforms in pixel space and exposes only\n * `uv`/`tint`.\n *\n * Tree-shaking contract: the default sprite path never imports this module. `sprite-pipeline.ts`\n * only reaches the custom composer through the opaque object a caller builds here via\n * `createSprite2DCustomShader`, so a layer that uses the stock shader pays zero bytes for it.\n *\n * WGSL contract for the supplied `fragment` body:\n * - Receives `in: VOut` with `uv: vec2<f32>` and `tint: vec4<f32>` (the per-sprite `color`).\n * - Has access to `atlasTex` / `atlasSamp` (the layer atlas at bindings 1/2), each extra\n * texture as `<name>Tex` / `<name>Samp`, the `fx` UBO (`fx.time`, `fx.params`), and the\n * `L` layer UBO (e.g. `L.opacityMul`).\n * - Must `return vec4<f32>(...)` (and may `discard`). The body owns all alpha handling; no\n * per-layer opacity is applied automatically.\n */\nimport type { CustomShaderTexture, SpriteLayerFx } from \"./custom-shader-core.js\";\nimport {\n createSpriteLayerFx,\n EMPTY_PARAMS,\n makeCustomShaderLayoutEntries,\n makeExtraBindingsWgsl,\n makeFxStructWgsl,\n makeShaderModuleCache,\n nextCustomShaderKey,\n validateExtraTextureNames,\n} from \"./custom-shader-core.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { makeSpritePrologueWgsl } from \"./sprite-pipeline.js\";\nimport type { SpriteFxHook } from \"./sprite-fx-hook.js\";\nimport { _registerSpriteFxHook } from \"./sprite-fx-hook.js\";\n\n/** One extra texture bound after the atlas. In WGSL it becomes `<name>Tex` + `<name>Samp`. */\nexport type Sprite2DCustomTexture = CustomShaderTexture;\n\n/** Options for {@link createSprite2DCustomShader}. */\nexport interface Sprite2DCustomShaderOptions {\n /** WGSL fragment body. See the module docs for the in-scope identifiers. */\n readonly fragment: string;\n /** Extra textures, in binding order. Each contributes a `texture_2d` + `sampler`. */\n readonly extraTextures?: readonly Sprite2DCustomTexture[];\n}\n\n/** A compiled-on-demand custom sprite shader. Pure data; pass as `customShader` to `createSprite2DLayer`. */\nexport interface Sprite2DCustomShader {\n /** @internal */\n readonly _entityType: \"sprite-2d-custom-shader\";\n /** @internal Extra textures bound after the atlas. */\n readonly _extraTextures: readonly Sprite2DCustomTexture[];\n /** @internal Stable identity used to key pipeline + shader-module caches. */\n readonly _key: string;\n /** @internal Compose the full WGSL module for a given layout (`hasDepth` → group index). */\n readonly _composeWgsl: (hasDepth: boolean, spriteGroupIndex: 0 | 1, uvScroll: boolean) => string;\n /** @internal Compile + cache the `GPUShaderModule` for a layout (owns its per-device cache). */\n readonly _getShaderModule: (engine: EngineContext, hasDepth: boolean, uvScroll: boolean) => GPUShaderModule;\n /** @internal Extra-texture + fx UBO bind-group **layout** entries, starting at `startBinding` (3). */\n readonly _layoutEntries: (startBinding: number) => GPUBindGroupLayoutEntry[];\n /** @internal Build the opaque per-layer fx attachment (owns the `SpriteFx` UBO, scratch, and elapsed time). */\n readonly _createLayerFx: (engine: EngineContext, label: string) => SpriteLayerFx;\n}\n\nfunction makeCustomSpriteWgsl(hasDepth: boolean, spriteGroupIndex: 0 | 1, extraTextures: readonly Sprite2DCustomTexture[], fragment: string, uvScroll: boolean): string {\n const fxBinding = 3 + extraTextures.length * 2;\n return `${makeSpritePrologueWgsl(hasDepth, spriteGroupIndex, uvScroll)}\n${makeExtraBindingsWgsl(spriteGroupIndex, 3, extraTextures)}${makeFxStructWgsl(spriteGroupIndex, fxBinding)}\n@fragment\nfn fs(in: VOut) -> @location(0) vec4<f32> {\n${fragment}\n}`;\n}\n\n/**\n * The 2D-sprite custom-shader hook implementation. Lives only in this (tree-shaken) module, so the\n * always-loaded sprite path never names `customShader` / `shaderParams`. Reads both off the opaque\n * `layer` and delegates to the descriptor's underscore-prefixed (mangled) methods.\n */\nconst SPRITE_FX_HOOK: SpriteFxHook = {\n initLayer(layer, opts) {\n const customShader = opts.customShader;\n if (customShader) {\n (layer as { customShader?: Sprite2DCustomShader }).customShader = customShader;\n layer.shaderParams = [0, 0, 0, 0];\n }\n },\n pipelineKeyPart(layer) {\n return layer.customShader?._key ?? \"\";\n },\n shaderModule(engine, hasDepth, layer) {\n return layer.customShader?._getShaderModule(engine, hasDepth, layer._uvScroll === true) ?? null;\n },\n layoutEntries(layer, startBinding) {\n return layer.customShader?._layoutEntries(startBinding) ?? null;\n },\n createLayerFx(engine, label, layer) {\n return layer.customShader?._createLayerFx(engine, label) ?? null;\n },\n updateFx(fx, layer, deltaMs) {\n fx.update(layer.shaderParams ?? EMPTY_PARAMS, deltaMs);\n },\n bindEntries(fx, startBinding) {\n return fx.bindEntries(startBinding);\n },\n disposeFx(fx) {\n fx.destroy();\n },\n};\n\n/**\n * Create a custom fragment shader for a sprite layer. Pass the result as the `customShader`\n * option of `createSprite2DLayer`. See the module-level docs for the WGSL contract.\n */\nexport function createSprite2DCustomShader(options: Sprite2DCustomShaderOptions): Sprite2DCustomShader {\n _registerSpriteFxHook(SPRITE_FX_HOOK);\n const fragment = options.fragment;\n if (typeof fragment !== \"string\" || fragment.trim().length === 0) {\n throw new Error(\"createSprite2DCustomShader: `fragment` must be a non-empty WGSL string.\");\n }\n const extraTextures = options.extraTextures ?? [];\n validateExtraTextureNames(\"createSprite2DCustomShader\", extraTextures);\n const moduleCache = makeShaderModuleCache();\n return {\n _entityType: \"sprite-2d-custom-shader\",\n _extraTextures: extraTextures,\n _key: nextCustomShaderKey(\"s\"),\n _composeWgsl: (hasDepth, spriteGroupIndex, uvScroll) => makeCustomSpriteWgsl(hasDepth, spriteGroupIndex, extraTextures, fragment, uvScroll),\n // `spriteGroupIndex = hasDepth ? 1 : 0`: depth-hosted layers put the scene UBO at group 0, so the\n // sprite resources (atlas, extras, fx) shift to group 1; pure-2D layers keep them at group 0.\n _getShaderModule: (engine, hasDepth, uvScroll) =>\n moduleCache(engine, `${hasDepth ? \"1\" : \"0\"}:${uvScroll ? \"u\" : \"-\"}`, () => makeCustomSpriteWgsl(hasDepth, hasDepth ? 1 : 0, extraTextures, fragment, uvScroll)),\n _layoutEntries: (startBinding) => makeCustomShaderLayoutEntries(extraTextures, startBinding),\n _createLayerFx: (engine, label) => createSpriteLayerFx(engine, label, extraTextures),\n };\n}\n","/** Optional stable-identity Handle API for Sprite2DLayer. */\nimport type { Sprite2DIndexHandleHooks, Sprite2DLayer, Sprite2DProps } from \"./sprite-2d.js\";\nimport { addSprite2DIndex, removeSprite2DIndex, setSprite2DFrameIndex, updateSprite2DIndex } from \"./sprite-2d.js\";\n\n/** Stable identity for a single 2D sprite that survives swap-remove reindexing. */\nexport interface Sprite2DHandle {\n /** @internal */\n readonly _entityType: \"sprite-2d-handle\";\n readonly layer: Sprite2DLayer;\n readonly id: number;\n}\n\ninterface Sprite2DHandleState {\n nextId: number;\n idToIndex: Map<number, number>;\n indexToId: Uint32Array;\n}\n\ninterface Sprite2DLayerWithHandles extends Sprite2DLayer {\n _handleState?: Sprite2DHandleState;\n}\n\nconst MAX_HANDLE_ID = 0xffffffff;\n\nfunction getOrCreateState(layer: Sprite2DLayer): Sprite2DHandleState {\n const withHandles = layer as Sprite2DLayerWithHandles;\n let state = withHandles._handleState;\n if (state) {\n ensureIndexCapacity(layer, state);\n return state;\n }\n\n state = {\n nextId: 1,\n idToIndex: new Map<number, number>(),\n indexToId: new Uint32Array(layer._capacity),\n };\n const hooks: Sprite2DIndexHandleHooks = {\n removeIndex(index, last): void {\n onRemoveIndex(state!, index, last);\n },\n clear(): void {\n state!.idToIndex.clear();\n state!.indexToId.fill(0);\n },\n };\n withHandles._handleState = state;\n withHandles._handleHooks = hooks;\n return state;\n}\n\nfunction getState(layer: Sprite2DLayer): Sprite2DHandleState | undefined {\n return (layer as Sprite2DLayerWithHandles)._handleState;\n}\n\nfunction ensureIndexCapacity(layer: Sprite2DLayer, state: Sprite2DHandleState): void {\n if (state.indexToId.length >= layer._capacity) {\n return;\n }\n const next = new Uint32Array(layer._capacity);\n next.set(state.indexToId);\n state.indexToId = next;\n}\n\nfunction onRemoveIndex(state: Sprite2DHandleState, index: number, last: number): void {\n const removedId = state.indexToId[index] ?? 0;\n const movedId = state.indexToId[last] ?? 0;\n if (removedId !== 0) {\n state.idToIndex.delete(removedId);\n }\n if (index !== last) {\n if (movedId !== 0) {\n state.idToIndex.set(movedId, index);\n }\n if (index < state.indexToId.length) {\n state.indexToId[index] = movedId;\n }\n } else if (index < state.indexToId.length) {\n state.indexToId[index] = 0;\n }\n if (last < state.indexToId.length) {\n state.indexToId[last] = 0;\n }\n}\n\nfunction allocateId(state: Sprite2DHandleState): number {\n const id = state.nextId;\n if (id > MAX_HANDLE_ID) {\n throw new Error(\"addSprite2D: handle id space exhausted.\");\n }\n state.nextId = id + 1;\n return id;\n}\n\nfunction lookupIndex(handle: Sprite2DHandle): number | null {\n const state = getState(handle.layer);\n if (!state) {\n return null;\n }\n const index = state.idToIndex.get(handle.id);\n return index === undefined ? null : index;\n}\n\nfunction requireIndex(handle: Sprite2DHandle, caller: string): number {\n const index = lookupIndex(handle);\n if (index === null) {\n throw new Error(`${caller}: Sprite2DHandle ${handle.id} has been removed.`);\n }\n return index;\n}\n\n/**\n * Adds a sprite to the layer and returns a stable handle to it.\n * @param layer - Sprite layer to add the sprite to.\n * @param props - Initial sprite properties.\n * @returns A handle that stays valid as sprites are added and removed.\n */\nexport function addSprite2D(layer: Sprite2DLayer, props: Sprite2DProps): Sprite2DHandle {\n const index = addSprite2DIndex(layer, props);\n const state = getOrCreateState(layer);\n const id = allocateId(state);\n state.idToIndex.set(id, index);\n state.indexToId[index] = id;\n return { _entityType: \"sprite-2d-handle\", layer, id };\n}\n\n/**\n * Updates the properties of the sprite referenced by `handle`.\n * @param handle - Handle of the sprite to update.\n * @param patch - Partial set of properties to overwrite.\n * @throws If the handle has already been removed.\n */\nexport function updateSprite2D(handle: Sprite2DHandle, patch: Partial<Sprite2DProps>): void {\n updateSprite2DIndex(handle.layer, requireIndex(handle, \"updateSprite2D\"), patch);\n}\n\n/**\n * Removes the sprite referenced by `handle`. Does nothing if it is already gone.\n * @param handle - Handle of the sprite to remove.\n */\nexport function removeSprite2D(handle: Sprite2DHandle): void {\n const index = lookupIndex(handle);\n if (index === null) {\n return;\n }\n removeSprite2DIndex(handle.layer, index);\n}\n\n/**\n * Sets the atlas frame of the sprite referenced by `handle`.\n * @param handle - Handle of the sprite to update.\n * @param frame - Atlas frame index.\n * @throws If the handle has already been removed.\n */\nexport function setSprite2DFrame(handle: Sprite2DHandle, frame: number): void {\n setSprite2DFrameIndex(handle.layer, requireIndex(handle, \"setSprite2DFrame\"), frame);\n}\n\n/**\n * Resolves the current instance index of the sprite referenced by `handle`.\n * @param handle - Handle of the sprite to resolve.\n * @returns The current instance index in the layer's buffers.\n * @throws If the handle has already been removed.\n */\nexport function getSprite2DHandleIndex(handle: Sprite2DHandle): number {\n return requireIndex(handle, \"getSprite2DHandleIndex\");\n}\n\n/**\n * Returns `true` if the sprite referenced by `handle` is still present in its layer.\n * @param handle - Handle to test.\n */\nexport function isSprite2DHandleAlive(handle: Sprite2DHandle): boolean {\n return lookupIndex(handle) !== null;\n}\n","/**\n * `sprite-renderable.ts` — wraps a single depth-hosted `Sprite2DLayer`\n * (`depth: \"test\"` or `\"test-write\"`) as a scene `Renderable`. Drawn inside\n * the scene's main 3D pass alongside meshes, so it participates in the\n * engine's depth attachment and gets occluded by (or occludes) regular\n * geometry based on its `layerZ`.\n *\n * Reached through `addDepthHostedSpriteLayer` when a depth-hosted `Sprite2DLayer`\n * is added to a scene. Pure-2D scenes and mesh-only scenes pay zero runtime bytes\n * for this module when the depth-hosted sprite API is not imported.\n *\n * Per-layer GPU work (instance / UBO upload, capacity grow, change-detect)\n * is shared with `sprite-renderer.ts` via helpers in `sprite-pipeline.ts`.\n * Each renderable still owns its own GPU resources (one layer per renderable\n * vs. the renderer's many-layer Map) — only the per-frame sync logic is\n * shared.\n */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTargetSignature } from \"../engine/render-target.js\";\nimport type { DrawBinding, DrawUpdateContext, Renderable } from \"../render/renderable.js\";\nimport { getSceneBindGroupLayout } from \"../render/scene-helpers.js\";\nimport { createEmptyUniformBuffer, createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport type { SpriteLayerFx } from \"./custom-shader-core.js\";\nimport { _getSpriteFxHook } from \"./sprite-fx-hook.js\";\nimport type { Sprite2DLayer } from \"./sprite-2d.js\";\nimport {\n LAYER_UBO_BYTES,\n SHARED_SPRITE_INDEX_DATA,\n buildSpriteLayerUbo,\n createSpriteInstanceBuffer,\n createSpriteLayerBindGroup,\n createSpritePipelineCache,\n ensureSpriteInstanceBuffer,\n getOrCreateSpritePipeline,\n resetSpritePipelineCache,\n uploadSpriteInstances,\n writeSpriteLayerUboIfDirty,\n} from \"./sprite-pipeline.js\";\nimport type { SpritePipelineCache } from \"./sprite-pipeline.js\";\n\n// Shared sprite pipeline cache across every depth-hosted Sprite2DLayer renderable\n// in the process. Lazy-init on first acquire (per GUIDANCE §4 — module-level\n// `null` initializer + `getCache()`-style helper, never a top-level `new Map()`).\n// Refcounted so the cache (and its compiled GPUShaderModule + pipelines) is\n// released exactly when the last depth-hosted renderable is disposed; device\n// changes are handled inside `getOrCreateSpritePipeline` via its per-device cache.\n// The SpriteRenderer (HUD) path uses its own per-renderer cache.\nlet _sharedPipelineCache: SpritePipelineCache | null = null;\nlet _sharedPipelineCacheRefs = 0;\n\nfunction acquireSharedPipelineCache(): SpritePipelineCache {\n _sharedPipelineCache ??= createSpritePipelineCache();\n _sharedPipelineCacheRefs++;\n return _sharedPipelineCache;\n}\n\nfunction releaseSharedPipelineCache(): void {\n if (_sharedPipelineCacheRefs === 0) {\n return;\n }\n _sharedPipelineCacheRefs--;\n if (_sharedPipelineCacheRefs === 0 && _sharedPipelineCache) {\n resetSpritePipelineCache(_sharedPipelineCache);\n _sharedPipelineCache = null;\n }\n}\n\ninterface SpriteRenderableInternal extends Renderable {\n _engine: EngineContext;\n _layer: Sprite2DLayer;\n _indexBuffer: GPUBuffer;\n _uniformBuffer: GPUBuffer;\n _instanceBuffer: GPUBuffer;\n _instanceBufferCapacity: number;\n _pipelineCache: SpritePipelineCache;\n _bindGroups: Map<GPURenderPipeline, GPUBindGroup>;\n _uploadedVersion: number;\n _uboUploaded: boolean;\n _lastUbo: Float32Array;\n _scratchUbo: Float32Array;\n _fx: SpriteLayerFx | null;\n _disposed: boolean;\n}\n\n/**\n * Build a `Renderable` for a depth-hosted `Sprite2DLayer`. Returns the\n * renderable plus a `dispose` callback that destroys all per-layer GPU\n * resources and clears the pipeline cache.\n *\n * Throws if `layer.depth === \"none\"` — pure-2D HUD layers must be rendered\n * via `createSpriteRenderer + registerSpriteRenderer`, not as a scene\n * `Renderable`. The check lives here as a second line of defense; the public\n * opt-in scene add function also rejects pure HUD layers before registration.\n *\n * Caller is responsible for\n * pushing `renderable` into `_renderables` and `dispose` into `_disposables`.\n */\nexport function buildSpriteRenderable(engine: EngineContext, layer: Sprite2DLayer): { renderable: Renderable; dispose: () => void } {\n if (layer.depth === \"none\") {\n throw new Error('Sprite2DLayer with depth: \"none\" must be rendered via createSpriteRenderer, not addDepthHostedSpriteLayer.');\n }\n const indexBuffer = createMappedBuffer(engine, SHARED_SPRITE_INDEX_DATA, GPUBufferUsage.INDEX);\n const uniformBuffer = createEmptyUniformBuffer(engine, LAYER_UBO_BYTES, \"sprite-depth-hosted-ubo\");\n const cap = layer._capacity;\n const instanceBuffer = createSpriteInstanceBuffer(engine._device, layer, \"sprite-depth-hosted-instances\");\n const fx = _getSpriteFxHook()?.createLayerFx(engine, \"sprite-depth-hosted-fx-ubo\", layer) ?? null;\n\n const isTransparent = layer.depth === \"test\";\n const isDirect = layer.depth === \"test-write\";\n const renderable: SpriteRenderableInternal = {\n // Depth-write sprite layers are mutable instanced batches, so route them through\n // the direct-draw phase after cached opaque meshes and before transparent draws.\n order: isTransparent ? 200 : 100,\n isTransparent,\n _direct: isDirect,\n _engine: engine,\n _layer: layer,\n _indexBuffer: indexBuffer,\n _uniformBuffer: uniformBuffer,\n _instanceBuffer: instanceBuffer,\n _instanceBufferCapacity: cap,\n _pipelineCache: acquireSharedPipelineCache(),\n _bindGroups: new Map(),\n _uploadedVersion: -1,\n _uboUploaded: false,\n _lastUbo: new Float32Array(LAYER_UBO_BYTES / 4),\n _scratchUbo: new Float32Array(LAYER_UBO_BYTES / 4),\n _fx: fx,\n _disposed: false,\n bind(engine, target) {\n return bindLayer(renderable, engine, target);\n },\n };\n\n return {\n renderable,\n dispose() {\n disposeRenderable(renderable);\n },\n };\n}\n\n/** Resolve this sprite layer against a render-pass target and return the per-frame draw binding. */\nfunction bindLayer(r: SpriteRenderableInternal, engine: EngineContext, target: RenderTargetSignature): DrawBinding {\n if (!target._depthStencilFormat) {\n throw new Error(\"Depth-hosted Sprite2DLayer requires a depth-stencil render target.\");\n }\n const sampleCount = target._sampleCount === 1 ? 1 : 4;\n const depthWrite = r._layer.depth === \"test-write\";\n const pipeline = getOrCreateSpritePipeline(\n engine,\n r._pipelineCache,\n target._colorFormat!,\n sampleCount,\n r._layer.blendMode,\n true,\n depthWrite,\n target._depthStencilFormat,\n getSceneBindGroupLayout(engine),\n r._layer\n );\n let bindGroup = r._bindGroups.get(pipeline);\n if (!bindGroup) {\n bindGroup = createSpriteLayerBindGroup(engine, pipeline, 1, r._layer, r._uniformBuffer, r._fx);\n r._bindGroups.set(pipeline, bindGroup);\n }\n return {\n renderable: r,\n pipeline,\n update(context) {\n uploadLayer(r, context);\n },\n draw(pass) {\n return drawLayer(r, bindGroup, pass);\n },\n };\n}\n\n/** Sync per-instance vertex data and the per-layer UBO via the shared pipeline helpers. */\nfunction uploadLayer(r: SpriteRenderableInternal, target: DrawUpdateContext): void {\n if (r._disposed) {\n return;\n }\n // Match the pure-2D `SpriteRenderer` path: skip invisible / empty layers entirely so `fx.time`\n // (and the FX UBO write) stays consistent across both paths and we avoid wasted `writeBuffer` traffic.\n if (!r._layer.visible || r._layer.count === 0) {\n return;\n }\n if (r._fx) {\n _getSpriteFxHook()!.updateFx(r._fx, r._layer, r._engine._currentDelta);\n }\n const grown = ensureSpriteInstanceBuffer(r._engine._device, r._layer, r._instanceBuffer, r._instanceBufferCapacity, \"sprite-depth-hosted-instances\");\n if (grown.reallocated) {\n r._instanceBuffer = grown.buffer;\n r._instanceBufferCapacity = grown.capacity;\n r._uploadedVersion = -1;\n }\n r._uploadedVersion = uploadSpriteInstances(r._engine._device, r._layer, r._instanceBuffer, r._uploadedVersion);\n buildSpriteLayerUbo(r._layer, target.targetWidth, target.targetHeight, r._scratchUbo);\n r._uboUploaded = writeSpriteLayerUboIfDirty(r._engine._device, r._uniformBuffer, r._scratchUbo, r._lastUbo, r._uboUploaded);\n}\n\n/** Issue the indexed instanced draw for this depth-hosted sprite layer. */\nfunction drawLayer(r: SpriteRenderableInternal, bindGroup: GPUBindGroup, pass: GPURenderPassEncoder | GPURenderBundleEncoder): number {\n if (r._disposed || !r._layer.visible || r._layer.count === 0) {\n return 0;\n }\n pass.setBindGroup(1, bindGroup);\n pass.setIndexBuffer(r._indexBuffer, \"uint16\");\n pass.setVertexBuffer(0, r._instanceBuffer);\n pass.drawIndexed(6, r._layer.count, 0, 0, 0);\n return 1;\n}\n\nfunction disposeRenderable(r: SpriteRenderableInternal): void {\n if (r._disposed) {\n return;\n }\n r._disposed = true;\n r._instanceBuffer.destroy();\n r._uniformBuffer.destroy();\n r._indexBuffer.destroy();\n if (r._fx) {\n _getSpriteFxHook()!.disposeFx(r._fx);\n }\n r._bindGroups.clear();\n // Drop the layer back-reference so a disposed renderable doesn't keep the\n // user's Sprite2DLayer (and its CPU instance/savedSize buffers) alive.\n // Cast through unknown — the field is non-null in the live path; only\n // disposed renderables (no longer touched by render code) ever see null.\n (r as unknown as { _layer: Sprite2DLayer | null })._layer = null;\n releaseSharedPipelineCache();\n}\n","import type { SceneContext } from \"../scene/scene-core.js\";\nimport { addDeferredSceneRenderables } from \"../scene/scene-core.js\";\nimport type { Sprite2DLayer } from \"./sprite-2d.js\";\nimport { buildSpriteRenderable } from \"./sprite-renderable.js\";\n\n/**\n * Add a depth-hosted Sprite2D layer to a SceneContext via the scene's optional\n * renderable extension hook. Pure HUD layers (`depth: \"none\"`) are rendered by\n * `createSpriteRenderer + registerSpriteRenderer` instead.\n */\nexport function addDepthHostedSpriteLayer(scene: SceneContext, layer: Sprite2DLayer): void {\n if (layer.depth === \"none\") {\n throw new Error('Sprite2DLayer with depth: \"none\" must be rendered via createSpriteRenderer, not addDepthHostedSpriteLayer.');\n }\n addDeferredSceneRenderables(scene, (engine) => {\n const built = buildSpriteRenderable(engine, layer);\n return { renderables: [built.renderable], dispose: built.dispose };\n });\n}\n","/**\n * Billboard blend modes as importable, pure-data descriptor values.\n *\n * Mirrors `sprite-blend.ts` for world-space billboards. Each mode is its own tree-shaken\n * `const`, so a scene pays only for the descriptor(s) it imports. `cutout` carries no color\n * blend (`_descriptor` undefined) and drives the alpha-test depth-write path via `_depthMode`.\n */\nimport type { BillboardDepthMode } from \"./billboard-sprite.js\";\nimport { _ALPHA_BLEND_STATE, _PREMULTIPLIED_BLEND_STATE } from \"./blend-descriptors.js\";\n\n/**\n * A billboard-system blend descriptor. Pass one of the exported `billboardBlend*` values to\n * `createFacingBillboardSystem` / `createAxisLockedBillboardSystem` via `{ blendMode }`. The\n * fields are internal plumbing; treat the value as opaque.\n */\nexport interface BillboardBlendDescriptor {\n /** @internal Pipeline-cache discriminator. */\n readonly _key: string;\n /** @internal Color-target blend state; `undefined` for the alpha-tested cutout path. */\n readonly _descriptor?: GPUBlendState;\n /** @internal When true, per-system opacity scales RGB *and* A (premultiplied fade). */\n readonly _premultipliedOpacity?: boolean;\n /** @internal Depth/blend pipeline path this mode selects. */\n readonly _depthMode: BillboardDepthMode;\n}\n\n/** Straight-alpha \"over\" blending (the default) for transparent billboards. */\nexport const billboardBlendAlpha: BillboardBlendDescriptor = {\n _key: \"alpha\",\n _descriptor: _ALPHA_BLEND_STATE,\n _depthMode: \"transparent\",\n};\n\n/** Premultiplied-alpha \"over\" blending; per-system opacity scales RGB and A together. */\nexport const billboardBlendPremultiplied: BillboardBlendDescriptor = {\n _key: \"premultiplied\",\n _descriptor: _PREMULTIPLIED_BLEND_STATE,\n _premultipliedOpacity: true,\n _depthMode: \"transparent\",\n};\n\n/**\n * Alpha-test cutout: no color blend; fragments below `alphaCutoff` are discarded and surviving\n * fragments write depth, so cutout billboards occlude correctly like opaque geometry.\n */\nexport const billboardBlendCutout: BillboardBlendDescriptor = {\n _key: \"cutout\",\n _depthMode: \"cutout\",\n};\n\n/**\n * Additive blending for world-space billboards. The billboard's RGB, scaled by its own alpha, is\n * added to the framebuffer (no depth write, like the other transparent modes), so overlapping\n * billboards stack and brighten — world-space embers, sparks, muzzle flashes, and light shafts.\n */\nexport const billboardBlendAdditive: BillboardBlendDescriptor = {\n _key: \"additive\",\n _descriptor: {\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n },\n _depthMode: \"transparent\",\n};\n","/**\n * Billboard sprites: world-space quads backed by a SpriteAtlas.\n *\n * This module is pure state + standalone index API. The optional Handle API\n * lives in `billboard-sprite-handle.ts` and installs swap-remove hooks lazily.\n */\nimport type { SpriteAtlas } from \"./shared/sprite-atlas.js\";\nimport { resolveSpriteFrame } from \"./shared/sprite-atlas.js\";\nimport type { BillboardCustomShader } from \"./billboard-custom-shader.js\";\nimport type { BillboardBlendDescriptor } from \"./billboard-blend.js\";\nimport { billboardBlendAlpha } from \"./billboard-blend.js\";\nimport { _getBillboardFxHook } from \"./sprite-fx-hook.js\";\n\n/**\n * Blend mode for a billboard sprite system — a pure-data descriptor value. Import one of\n * `billboardBlendAlpha` (default), `billboardBlendPremultiplied`, or `billboardBlendCutout`\n * and pass it as `BillboardSpriteSystemOptions.blendMode`. (Type alias of\n * {@link BillboardBlendDescriptor}.)\n */\nexport type BillboardBlendMode = BillboardBlendDescriptor;\n\n/** Optional configuration for a billboard sprite system. */\nexport interface BillboardSpriteSystemOptions {\n capacity?: number;\n blendMode?: BillboardBlendMode;\n alphaCutoff?: number;\n opacity?: number;\n visible?: boolean;\n order?: number;\n /** Optional opt-in custom fragment shader (from `createBillboardCustomShader`). */\n customShader?: BillboardCustomShader;\n}\n\n/** How a billboard orients itself: `facing` always faces the camera, `axis-locked` rotates only around a fixed axis. */\nexport type BillboardOrientation = \"facing\" | \"axis-locked\";\n/** Depth/blend pipeline path used by a billboard system: alpha-blended `transparent` or alpha-tested `cutout`. */\nexport type BillboardDepthMode = \"transparent\" | \"cutout\";\n\nexport interface BillboardSpriteSystem<TOrientation extends BillboardOrientation = BillboardOrientation> {\n /** @internal */\n readonly _entityType: \"billboard-sprite-system\";\n readonly atlas: SpriteAtlas;\n readonly blendMode: BillboardBlendMode;\n alphaCutoff: number;\n opacity: number;\n visible: boolean;\n readonly order: number;\n readonly count: number;\n\n /** @internal Orientation shader path for this system. */\n readonly _orientation: TOrientation;\n /** @internal Depth/blend pipeline path for this system. */\n readonly _depthMode: BillboardDepthMode;\n /** @internal Normalized lock axis for axis-locked systems; zero for facing. */\n readonly _axis: readonly [number, number, number];\n /** @internal Capacity of the per-instance buffer in sprites. */\n _capacity: number;\n /** @internal Per-instance stride in floats. */\n readonly _instanceFloatsPerSprite: number;\n /** @internal Per-instance stride in bytes. */\n readonly _instanceStrideBytes: number;\n /** @internal Billboard instance data. */\n _instanceData: Float32Array;\n /** @internal True size shadow, unaffected by `visible: false`. */\n _savedSize: Float32Array;\n /** @internal Bumped on any instance edit. */\n _version: number;\n /** @internal Dirty min index inclusive. */\n _dirtyMin: number;\n /** @internal Dirty max index exclusive. */\n _dirtyMax: number;\n /** @internal Optional hooks installed by the opt-in handle module. */\n _handleHooks?: BillboardIndexHandleHooks;\n /** @internal Optional custom fragment shader for this system. Absent on plain systems. */\n readonly _customShader?: BillboardCustomShader;\n /**\n * Per-system custom-shader params (`fx.params`); set via `setBillboardShaderParams`.\n * **Absent** on plain systems (only allocated for custom-shader systems, or lazily by the setter).\n */\n shaderParams?: [number, number, number, number];\n}\n\n/** @internal Lazy hooks used by the opt-in Handle API to track swap-removes. */\nexport interface BillboardIndexHandleHooks {\n readonly removeIndex: (index: number, last: number) => void;\n readonly clear: () => void;\n}\n\n/** A camera-facing billboard sprite system. */\nexport type FacingBillboardSpriteSystem = BillboardSpriteSystem<\"facing\">;\n/** A billboard sprite system that rotates only around a fixed world axis. */\nexport type AxisLockedBillboardSpriteSystem = BillboardSpriteSystem<\"axis-locked\">;\n\n/** Initial properties for a single billboard sprite. */\nexport interface BillboardSpriteInit {\n position: [number, number, number];\n sizeWorld: [number, number];\n frame?: number;\n rotation?: number;\n pivot?: [number, number];\n color?: [number, number, number, number];\n flipX?: boolean;\n flipY?: boolean;\n visible?: boolean;\n}\n\nexport const BILLBOARD_INSTANCE_FLOATS_PER_SPRITE = 16;\nexport const BILLBOARD_INSTANCE_STRIDE_BYTES = BILLBOARD_INSTANCE_FLOATS_PER_SPRITE * 4;\nexport const BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE = 2;\n\nconst DEFAULT_CAPACITY = 16;\n\nfunction setBillboardCount(system: BillboardSpriteSystem, count: number): void {\n (system as { count: number }).count = count;\n}\n\nfunction resolveAlphaCutoff(opts: BillboardSpriteSystemOptions, depthMode: BillboardDepthMode): number {\n const cutoff = opts.alphaCutoff ?? (depthMode === \"cutout\" ? 0.5 : 0);\n if (!Number.isFinite(cutoff)) {\n throw new Error(\"BillboardSpriteSystem: alphaCutoff must be a finite number.\");\n }\n return cutoff;\n}\n\nfunction resolveOpacity(opts: BillboardSpriteSystemOptions): number {\n const opacity = opts.opacity ?? 1;\n if (!Number.isFinite(opacity)) {\n throw new Error(\"BillboardSpriteSystem: opacity must be a finite number.\");\n }\n return opacity;\n}\n\n/**\n * Creates a camera-facing billboard sprite system backed by the given atlas.\n * @param atlas - Sprite atlas supplying frames.\n * @param opts - Optional capacity, blend, and appearance settings.\n * @returns The new facing billboard system.\n */\nexport function createFacingBillboardSystem(atlas: SpriteAtlas, opts: BillboardSpriteSystemOptions = {}): FacingBillboardSpriteSystem {\n return createBillboardSystem(atlas, \"facing\", [0, 0, 0], opts);\n}\n\n/**\n * Creates a billboard sprite system whose quads rotate only around a fixed world axis.\n * @param atlas - Sprite atlas supplying frames.\n * @param axis - Lock axis; normalized internally and must be non-zero and finite.\n * @param opts - Optional capacity, blend, and appearance settings.\n * @returns The new axis-locked billboard system.\n * @throws If `axis` has non-finite components or is the zero vector.\n */\nexport function createAxisLockedBillboardSystem(\n atlas: SpriteAtlas,\n axis: readonly [number, number, number],\n opts: BillboardSpriteSystemOptions = {}\n): AxisLockedBillboardSpriteSystem {\n if (!Number.isFinite(axis[0]) || !Number.isFinite(axis[1]) || !Number.isFinite(axis[2])) {\n throw new Error(\"createAxisLockedBillboardSystem: axis components must be finite numbers.\");\n }\n const lengthSq = axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2];\n if (lengthSq < 1e-8) {\n throw new Error(\"createAxisLockedBillboardSystem: axis must be non-zero.\");\n }\n const invLength = 1 / Math.sqrt(lengthSq);\n const normalized: [number, number, number] = [axis[0] * invLength, axis[1] * invLength, axis[2] * invLength];\n return createBillboardSystem(atlas, \"axis-locked\", normalized, opts);\n}\n\nfunction createBillboardSystem<TOrientation extends BillboardOrientation>(\n atlas: SpriteAtlas,\n orientation: TOrientation,\n axis: readonly [number, number, number],\n opts: BillboardSpriteSystemOptions\n): BillboardSpriteSystem<TOrientation> {\n const blendMode = opts.blendMode ?? billboardBlendAlpha;\n const depthMode = blendMode._depthMode;\n const capacity = Math.max(1, opts.capacity ?? DEFAULT_CAPACITY);\n const instanceData = new Float32Array(capacity * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE);\n const system: BillboardSpriteSystem<TOrientation> = {\n _entityType: \"billboard-sprite-system\",\n atlas,\n blendMode,\n alphaCutoff: resolveAlphaCutoff(opts, depthMode),\n opacity: resolveOpacity(opts),\n visible: opts.visible ?? true,\n order: opts.order ?? (depthMode === \"transparent\" ? 200 : 100),\n count: 0,\n _orientation: orientation,\n _depthMode: depthMode,\n _axis: axis,\n _capacity: capacity,\n _instanceFloatsPerSprite: BILLBOARD_INSTANCE_FLOATS_PER_SPRITE,\n _instanceStrideBytes: BILLBOARD_INSTANCE_STRIDE_BYTES,\n _instanceData: instanceData,\n _savedSize: new Float32Array(capacity * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE),\n _version: 0,\n _dirtyMin: 0,\n _dirtyMax: 0,\n };\n // Zero-default-init discipline: the base system never names `_customShader` / `shaderParams`.\n // The registered hook copies them on only when a custom shader was supplied; the impl lives in\n // the tree-shaken `billboard-custom-shader` module, so plain scenes ship none of it.\n _getBillboardFxHook()?.initSystem(system, opts);\n return system;\n}\n\n/**\n * Set the custom-shader `fx.params` vec4 for a billboard system created with a `customShader`.\n * No-op effect on systems without one (the value is simply stored). Read in WGSL as `fx.params`.\n */\nexport function setBillboardShaderParams(system: BillboardSpriteSystem, params: readonly [number, number, number, number]): void {\n const target = (system.shaderParams ??= [0, 0, 0, 0]);\n target[0] = params[0];\n target[1] = params[1];\n target[2] = params[2];\n target[3] = params[3];\n}\n\nfunction growCapacity(system: BillboardSpriteSystem, minCapacity: number): void {\n let capacity = system._capacity;\n while (capacity < minCapacity) {\n capacity *= 2;\n }\n const next = new Float32Array(capacity * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE);\n next.set(system._instanceData);\n system._instanceData = next;\n const nextSavedSize = new Float32Array(capacity * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE);\n nextSavedSize.set(system._savedSize);\n system._savedSize = nextSavedSize;\n system._capacity = capacity;\n}\n\nfunction writeInstance(system: BillboardSpriteSystem, slotIndex: number, props: Partial<BillboardSpriteInit>, prev: Float32Array | null): void {\n const data = system._instanceData;\n const base = slotIndex * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n const savedBase = slotIndex * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE;\n const isAdd = prev === null;\n const frame = props.frame !== undefined ? system.atlas.frames[resolveSpriteFrame(system.atlas, props.frame)]! : null;\n\n const posX = props.position ? props.position[0] : prev![0]!;\n const posY = props.position ? props.position[1] : prev![1]!;\n const posZ = props.position ? props.position[2] : prev![2]!;\n\n let trueWidth: number;\n let trueHeight: number;\n if (props.sizeWorld) {\n trueWidth = props.sizeWorld[0];\n trueHeight = props.sizeWorld[1];\n } else if (isAdd) {\n trueWidth = 0;\n trueHeight = 0;\n } else {\n trueWidth = system._savedSize[savedBase]!;\n trueHeight = system._savedSize[savedBase + 1]!;\n }\n system._savedSize[savedBase] = trueWidth;\n system._savedSize[savedBase + 1] = trueHeight;\n\n let visible: boolean;\n if (props.visible !== undefined) {\n visible = props.visible;\n } else if (isAdd) {\n visible = true;\n } else {\n visible = prev![3]! !== 0 || prev![4]! !== 0;\n }\n\n let uvMinX: number;\n let uvMinY: number;\n let uvMaxX: number;\n let uvMaxY: number;\n if (frame) {\n uvMinX = frame.uvMin[0];\n uvMinY = frame.uvMin[1];\n uvMaxX = frame.uvMax[0];\n uvMaxY = frame.uvMax[1];\n } else if (isAdd) {\n uvMinX = 0;\n uvMinY = 0;\n uvMaxX = 1;\n uvMaxY = 1;\n } else {\n uvMinX = prev![5]!;\n uvMinY = prev![6]!;\n uvMaxX = prev![7]!;\n uvMaxY = prev![8]!;\n }\n // Flip currently baked into the (possibly preserved) UV endpoints.\n const currentFlipX = uvMinX > uvMaxX;\n const currentFlipY = uvMinY > uvMaxY;\n // Flip carried over from the previous instance (used when the flag is omitted,\n // so a frame change keeps the existing flip).\n const prevFlipX = !isAdd && prev![5]! > prev![7]!;\n const prevFlipY = !isAdd && prev![6]! > prev![8]!;\n // Resolve the desired flip. The explicit `=== true` test (rather than a\n // `boolean !== flag` XOR) keeps both operands genuine booleans so terser's\n // `booleans_as_integers` pass cannot turn the flag into a number and break the\n // strict comparison (a boolean is never `!==`-equal to the integer 0/1 it maps\n // a flag onto).\n const wantsFlipX = props.flipX !== undefined ? props.flipX === true : prevFlipX;\n const wantsFlipY = props.flipY !== undefined ? props.flipY === true : prevFlipY;\n if (currentFlipX !== wantsFlipX) {\n const previousMinX = uvMinX;\n uvMinX = uvMaxX;\n uvMaxX = previousMinX;\n }\n if (currentFlipY !== wantsFlipY) {\n const previousMinY = uvMinY;\n uvMinY = uvMaxY;\n uvMaxY = previousMinY;\n }\n\n const rotation = props.rotation ?? (prev ? prev[9]! : 0);\n const pivotX = props.pivot ? props.pivot[0] : prev ? prev[10]! : (frame?.pivot[0] ?? 0.5);\n const pivotY = props.pivot ? props.pivot[1] : prev ? prev[11]! : (frame?.pivot[1] ?? 0.5);\n\n data[base + 0] = posX;\n data[base + 1] = posY;\n data[base + 2] = posZ;\n data[base + 3] = visible ? trueWidth : 0;\n data[base + 4] = visible ? trueHeight : 0;\n data[base + 5] = uvMinX;\n data[base + 6] = uvMinY;\n data[base + 7] = uvMaxX;\n data[base + 8] = uvMaxY;\n data[base + 9] = rotation;\n data[base + 10] = pivotX;\n data[base + 11] = pivotY;\n if (props.color) {\n data[base + 12] = props.color[0];\n data[base + 13] = props.color[1];\n data[base + 14] = props.color[2];\n data[base + 15] = props.color[3];\n } else if (isAdd) {\n data[base + 12] = 1;\n data[base + 13] = 1;\n data[base + 14] = 1;\n data[base + 15] = 1;\n }\n}\n\nfunction markDirty(system: BillboardSpriteSystem, dirtyMin: number, dirtyMax: number): void {\n if (system._dirtyMin >= system._dirtyMax) {\n system._dirtyMin = dirtyMin;\n system._dirtyMax = dirtyMax;\n } else {\n if (dirtyMin < system._dirtyMin) {\n system._dirtyMin = dirtyMin;\n }\n if (dirtyMax > system._dirtyMax) {\n system._dirtyMax = dirtyMax;\n }\n }\n system._version = (system._version + 1) | 0;\n}\n\n/**\n * Appends a billboard sprite to the system and returns its instance index.\n * @param system - Billboard system to add to.\n * @param props - Sprite properties; `position` and `sizeWorld` are required.\n * @returns The new sprite's instance index.\n * @throws If `position` or `sizeWorld` is missing.\n */\nexport function addBillboardSpriteIndex(system: BillboardSpriteSystem, props: BillboardSpriteInit): number {\n if (props.position === undefined) {\n throw new Error(\"addBillboardSpriteIndex: props.position is required.\");\n }\n if (props.sizeWorld === undefined) {\n throw new Error(\"addBillboardSpriteIndex: props.sizeWorld is required.\");\n }\n const index = system.count;\n if (index >= system._capacity) {\n growCapacity(system, index + 1);\n }\n writeInstance(system, index, props, null);\n setBillboardCount(system, system.count + 1);\n markDirty(system, index, index + 1);\n return index;\n}\n\n/**\n * Updates the billboard sprite at the given instance index.\n * @param system - Billboard system that owns the sprite.\n * @param index - Instance index to update.\n * @param patch - Partial set of properties to overwrite.\n * @throws If `index` is out of range.\n */\nexport function updateBillboardSpriteIndex(system: BillboardSpriteSystem, index: number, patch: Partial<BillboardSpriteInit>): void {\n if (index < 0 || index >= system.count) {\n throw new Error(`updateBillboardSpriteIndex: index ${index} out of range [0, ${system.count})`);\n }\n const base = index * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n const prev = system._instanceData.subarray(base, base + BILLBOARD_INSTANCE_FLOATS_PER_SPRITE);\n writeInstance(system, index, patch, prev);\n markDirty(system, index, index + 1);\n}\n\n/**\n * Removes the billboard sprite at the given instance index using swap-remove with the last sprite.\n * @param system - Billboard system that owns the sprite.\n * @param index - Instance index to remove.\n * @throws If `index` is out of range.\n */\nexport function removeBillboardSpriteIndex(system: BillboardSpriteSystem, index: number): void {\n if (index < 0 || index >= system.count) {\n throw new Error(`removeBillboardSpriteIndex: index ${index} out of range [0, ${system.count})`);\n }\n const last = system.count - 1;\n system._handleHooks?.removeIndex(index, last);\n if (index !== last) {\n system._instanceData.copyWithin(\n index * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE,\n last * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE,\n (last + 1) * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE\n );\n system._savedSize.copyWithin(\n index * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE,\n last * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE,\n (last + 1) * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE\n );\n }\n system._savedSize[last * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE] = 0;\n system._savedSize[last * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE + 1] = 0;\n setBillboardCount(system, last);\n markDirty(system, index, index + 1);\n}\n\n/**\n * Removes every sprite from the system, resetting its count to zero.\n * @param system - Billboard system to clear.\n */\nexport function clearBillboardSprites(system: BillboardSpriteSystem): void {\n const count = system.count;\n system._dirtyMin = 0;\n system._dirtyMax = 0;\n system._handleHooks?.clear();\n if (count === 0) {\n return;\n }\n system._savedSize.fill(0, 0, count * BILLBOARD_SAVED_SIZE_FLOATS_PER_SPRITE);\n setBillboardCount(system, 0);\n system._version = (system._version + 1) | 0;\n}\n\n/**\n * Update only the frame UVs for one billboard sprite.\n *\n * The sprite keeps its explicit `sizeWorld`/saved size. Pixel frame dimensions\n * do not imply a world-space resize; call `updateBillboardSpriteIndex` with\n * both `frame` and `sizeWorld` when that is desired. Existing flip state is\n * preserved for non-degenerate UV ranges.\n */\nexport function setBillboardSpriteFrameIndex(system: BillboardSpriteSystem, index: number, frame: number): void {\n if (index < 0 || index >= system.count) {\n throw new Error(`setBillboardSpriteFrameIndex: index ${index} out of range [0, ${system.count})`);\n }\n const frameIndex = resolveSpriteFrame(system.atlas, frame);\n const spriteFrame = system.atlas.frames[frameIndex]!;\n const base = index * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n const flipX = system._instanceData[base + 5]! > system._instanceData[base + 7]!;\n const flipY = system._instanceData[base + 6]! > system._instanceData[base + 8]!;\n system._instanceData[base + 5] = flipX ? spriteFrame.uvMax[0] : spriteFrame.uvMin[0];\n system._instanceData[base + 6] = flipY ? spriteFrame.uvMax[1] : spriteFrame.uvMin[1];\n system._instanceData[base + 7] = flipX ? spriteFrame.uvMin[0] : spriteFrame.uvMax[0];\n system._instanceData[base + 8] = flipY ? spriteFrame.uvMin[1] : spriteFrame.uvMax[1];\n markDirty(system, index, index + 1);\n}\n","import type { EngineContext } from \"../engine/engine.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport { SCENE_UBO_WGSL } from \"../shader/scene-uniforms.js\";\nimport type { BillboardDepthMode, BillboardOrientation, BillboardSpriteSystem } from \"./billboard-sprite.js\";\nimport type { SpriteLayerFx } from \"./custom-shader-core.js\";\nimport { _getBillboardFxHook } from \"./sprite-fx-hook.js\";\nimport { BILLBOARD_INSTANCE_FLOATS_PER_SPRITE, BILLBOARD_INSTANCE_STRIDE_BYTES } from \"./billboard-sprite.js\";\n\nexport interface BillboardPipelineDeviceCache {\n /** @internal */\n _shaderModules: Map<string, GPUShaderModule>;\n /** @internal */\n _pipelines: Map<string, GPURenderPipeline>;\n}\n\nexport interface BillboardPipelineCache {\n /** @internal */\n _devices: WeakMap<GPUDevice, BillboardPipelineDeviceCache>;\n}\n\nconst DEPTH_MODE_TABLE: Readonly<Record<BillboardDepthMode, { index: number; writeEnabled: boolean }>> = {\n transparent: { index: 0, writeEnabled: false },\n cutout: { index: 1, writeEnabled: true },\n};\n\nconst BILLBOARD_POSITION_OFFSET_BYTES = 0;\nconst BILLBOARD_SIZE_OFFSET_BYTES = 12;\nconst BILLBOARD_UV_MIN_OFFSET_BYTES = 20;\nconst BILLBOARD_UV_MAX_OFFSET_BYTES = 28;\nconst BILLBOARD_ROTATION_OFFSET_BYTES = 36;\nconst BILLBOARD_PIVOT_OFFSET_BYTES = 40;\nconst BILLBOARD_COLOR_OFFSET_BYTES = 48;\n\nexport const BILLBOARD_SYSTEM_UBO_BYTES = 32;\nconst BILLBOARD_SYSTEM_UBO_FLOATS = BILLBOARD_SYSTEM_UBO_BYTES / 4;\nexport const BILLBOARD_INDEX_DATA: Readonly<Uint16Array> = new Uint16Array([0, 1, 2, 0, 2, 3]);\n\nexport interface BillboardInstanceSortScratch {\n /** @internal */\n _capacity: number;\n /** @internal */\n _sortedInstanceData: Float32Array;\n /** @internal */\n _sortIndices: Uint32Array;\n /** @internal */\n _sortDepths: Float32Array;\n}\n\nfunction getDepthModeEntry(depthMode: BillboardDepthMode): (typeof DEPTH_MODE_TABLE)[BillboardDepthMode] {\n return DEPTH_MODE_TABLE[depthMode];\n}\n\n/** @internal Shared by the optional billboard custom-shader composer. */\nexport function makeBillboardBasisWgsl(orientation: BillboardOrientation): string {\n switch (orientation) {\n case \"facing\":\n return `struct BillboardBasis {\nright: vec3<f32>,\nup: vec3<f32>,\n};\nfn getBillboardBasis(_anchor: vec3<f32>) -> BillboardBasis {\nlet cameraRight = normalize(vec3<f32>(scene.view[0][0], scene.view[1][0], scene.view[2][0]));\nlet cameraUp = normalize(vec3<f32>(scene.view[0][1], scene.view[1][1], scene.view[2][1]));\nreturn BillboardBasis(cameraRight, -cameraUp);\n}`;\n case \"axis-locked\":\n return `struct BillboardBasis {\nright: vec3<f32>,\nup: vec3<f32>,\n};\nfn getBillboardBasis(_anchor: vec3<f32>) -> BillboardBasis {\nlet lockAxis = normalize(billboards.axisAndCutoff.xyz);\nlet cameraRight = normalize(vec3<f32>(scene.view[0][0], scene.view[1][0], scene.view[2][0]));\nlet projectedRight = cameraRight - lockAxis * dot(cameraRight, lockAxis);\nlet projectedRightLen = length(projectedRight);\nlet safeProjectedRightLen = max(projectedRightLen, 1e-4);\nlet fallbackSeed = select(vec3<f32>(0.0, 0.0, 1.0), vec3<f32>(1.0, 0.0, 0.0), abs(lockAxis.z) > 0.999);\nlet fallbackRightRaw = cross(lockAxis, fallbackSeed);\nlet fallbackRight = fallbackRightRaw / max(length(fallbackRightRaw), 1e-4);\nlet right = select(fallbackRight, projectedRight / safeProjectedRightLen, projectedRightLen > 1e-4);\nreturn BillboardBasis(right, -lockAxis);\n}`;\n }\n}\n\nfunction makeBillboardFragmentWgsl(depthMode: BillboardDepthMode): string {\n if (depthMode === \"cutout\") {\n return `@fragment\nfn fs(in: VOut) -> @location(0) vec4<f32> {\nlet sampleColor = textureSample(atlasTex, atlasSamp, in.uv);\nif (sampleColor.a < billboards.axisAndCutoff.w) {\ndiscard;\n}\nreturn sampleColor * in.tint * billboards.opacityMul;\n}`;\n }\n return `@fragment\nfn fs(in: VOut) -> @location(0) vec4<f32> {\nlet sampleColor = textureSample(atlasTex, atlasSamp, in.uv);\nreturn sampleColor * in.tint * billboards.opacityMul;\n}`;\n}\n\nfunction makeBillboardWgsl(orientation: BillboardOrientation, depthMode: BillboardDepthMode): string {\n return `${SCENE_UBO_WGSL}\nstruct BillboardSystem {\nopacityMul: vec4<f32>,\naxisAndCutoff: vec4<f32>,\n};\n@group(1) @binding(0) var<uniform> billboards: BillboardSystem;\n@group(1) @binding(1) var atlasTex: texture_2d<f32>;\n@group(1) @binding(2) var atlasSamp: sampler;\n${makeBillboardBasisWgsl(orientation)}\nstruct VIn {\n@builtin(vertex_index) vid: u32,\n@location(0) iPos: vec3<f32>,\n@location(1) iSize: vec2<f32>,\n@location(2) iUvMin: vec2<f32>,\n@location(3) iUvMax: vec2<f32>,\n@location(4) iRot: f32,\n@location(5) iPivot: vec2<f32>,\n@location(6) iColor: vec4<f32>,\n};\nstruct VOut {\n@builtin(position) pos: vec4<f32>,\n@location(0) uv: vec2<f32>,\n@location(1) tint: vec4<f32>,\n};\n@vertex\nfn vs(in: VIn) -> VOut {\nlet corner = vec2<f32>(select(0.0, 1.0, in.vid == 1u || in.vid == 2u), select(0.0, 1.0, in.vid >= 2u));\nlet local = (corner - in.iPivot) * in.iSize;\nlet cosRot = cos(in.iRot);\nlet sinRot = sin(in.iRot);\nlet rotated = vec2<f32>(local.x * cosRot - local.y * sinRot, local.x * sinRot + local.y * cosRot);\nlet basis = getBillboardBasis(in.iPos);\nlet worldPos = in.iPos + basis.right * rotated.x + basis.up * rotated.y;\nvar out: VOut;\nout.pos = scene.viewProjection * vec4<f32>(worldPos, 1.0);\nout.uv = mix(in.iUvMin, in.iUvMax, corner);\nout.tint = in.iColor;\nreturn out;\n}\n${makeBillboardFragmentWgsl(depthMode)}`;\n}\n\nexport function createBillboardPipelineCache(): BillboardPipelineCache {\n return {\n _devices: new WeakMap(),\n };\n}\n\nexport function resetBillboardPipelineCache(cache: BillboardPipelineCache): void {\n cache._devices = new WeakMap();\n}\n\nexport function getOrCreateBillboardPipeline(\n engine: EngineContext,\n cache: BillboardPipelineCache,\n format: GPUTextureFormat,\n sampleCount: 1 | 4,\n system: BillboardSpriteSystem,\n depthStencilFormat: GPUTextureFormat,\n sceneBindGroupLayout: GPUBindGroupLayout\n): GPURenderPipeline {\n const deviceCache = getBillboardPipelineDeviceCache(engine, cache);\n const depthEntry = getDepthModeEntry(system._depthMode);\n const customKey = _getBillboardFxHook()?.pipelineKeyPart(system) ?? \"\";\n const key = `${format}:${sampleCount}:${system._orientation}:${system.blendMode._key}:${depthEntry.index}:${depthStencilFormat}:${customKey}`;\n const cached = deviceCache._pipelines.get(key);\n if (cached) {\n return cached;\n }\n const pipeline = buildBillboardPipeline(engine, deviceCache, format, sampleCount, system, depthStencilFormat, sceneBindGroupLayout);\n deviceCache._pipelines.set(key, pipeline);\n return pipeline;\n}\n\nexport function createBillboardInstanceBuffer(device: GPUDevice, system: BillboardSpriteSystem, label?: string): GPUBuffer {\n return device.createBuffer({\n label,\n size: system._capacity * BILLBOARD_INSTANCE_STRIDE_BYTES,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n}\n\nexport function createBillboardInstanceSortScratch(): BillboardInstanceSortScratch {\n return {\n _capacity: 0,\n _sortedInstanceData: new Float32Array(0),\n _sortIndices: new Uint32Array(0),\n _sortDepths: new Float32Array(0),\n };\n}\n\nexport function uploadSortedBillboardInstances(\n device: GPUDevice,\n system: BillboardSpriteSystem,\n instanceBuffer: GPUBuffer,\n scratch: BillboardInstanceSortScratch,\n cameraViewMatrix: Mat4\n): void {\n const count = system.count;\n if (count === 0) {\n system._dirtyMin = 0;\n system._dirtyMax = 0;\n return;\n }\n ensureBillboardInstanceSortScratch(scratch, count);\n const sourceData = system._instanceData;\n const sortedData = scratch._sortedInstanceData;\n const indices = scratch._sortIndices;\n const depths = scratch._sortDepths;\n for (let index = 0; index < count; index++) {\n const base = index * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n const anchorX = sourceData[base]!;\n const anchorY = sourceData[base + 1]!;\n const anchorZ = sourceData[base + 2]!;\n indices[index] = index;\n depths[index] = cameraViewMatrix[2]! * anchorX + cameraViewMatrix[6]! * anchorY + cameraViewMatrix[10]! * anchorZ + cameraViewMatrix[14]!;\n }\n indices.subarray(0, count).sort((left, right) => depths[right]! - depths[left]! || left - right);\n for (let outIndex = 0; outIndex < count; outIndex++) {\n const sourceBase = indices[outIndex]! * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n const destBase = outIndex * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE;\n for (let field = 0; field < BILLBOARD_INSTANCE_FLOATS_PER_SPRITE; field++) {\n sortedData[destBase + field] = sourceData[sourceBase + field]!;\n }\n }\n device.queue.writeBuffer(instanceBuffer, 0, sortedData.buffer, sortedData.byteOffset, count * BILLBOARD_INSTANCE_STRIDE_BYTES);\n system._dirtyMin = 0;\n system._dirtyMax = 0;\n}\n\nexport function ensureBillboardInstanceBuffer(\n device: GPUDevice,\n system: BillboardSpriteSystem,\n currentBuffer: GPUBuffer,\n currentCapacity: number,\n label?: string\n): { buffer: GPUBuffer; capacity: number; reallocated: boolean } {\n if (currentCapacity >= system._capacity) {\n return { buffer: currentBuffer, capacity: currentCapacity, reallocated: false };\n }\n currentBuffer.destroy();\n return { buffer: createBillboardInstanceBuffer(device, system, label), capacity: system._capacity, reallocated: true };\n}\n\nexport function uploadBillboardInstances(device: GPUDevice, system: BillboardSpriteSystem, instanceBuffer: GPUBuffer, uploadedVersion: number): number {\n if (uploadedVersion === system._version) {\n return uploadedVersion;\n }\n if (system.count === 0) {\n system._dirtyMin = 0;\n system._dirtyMax = 0;\n return system._version;\n }\n let lowIndex: number;\n let highIndex: number;\n if (uploadedVersion === -1) {\n lowIndex = 0;\n highIndex = system.count;\n } else {\n lowIndex = system._dirtyMin;\n highIndex = Math.min(system._dirtyMax, system.count);\n }\n if (highIndex > lowIndex) {\n const offsetBytes = lowIndex * BILLBOARD_INSTANCE_STRIDE_BYTES;\n const byteLength = (highIndex - lowIndex) * BILLBOARD_INSTANCE_STRIDE_BYTES;\n device.queue.writeBuffer(instanceBuffer, offsetBytes, system._instanceData.buffer, system._instanceData.byteOffset + offsetBytes, byteLength);\n }\n system._dirtyMin = 0;\n system._dirtyMax = 0;\n return system._version;\n}\n\nfunction ensureBillboardInstanceSortScratch(scratch: BillboardInstanceSortScratch, count: number): void {\n if (scratch._capacity >= count) {\n return;\n }\n scratch._capacity = count;\n scratch._sortedInstanceData = new Float32Array(count * BILLBOARD_INSTANCE_FLOATS_PER_SPRITE);\n scratch._sortIndices = new Uint32Array(count);\n scratch._sortDepths = new Float32Array(count);\n}\n\nexport function buildBillboardSystemUbo(system: BillboardSpriteSystem, ubo: Float32Array): void {\n const opacity = system.opacity;\n if (system.blendMode._premultipliedOpacity) {\n ubo[0] = opacity;\n ubo[1] = opacity;\n ubo[2] = opacity;\n ubo[3] = opacity;\n } else {\n ubo[0] = 1;\n ubo[1] = 1;\n ubo[2] = 1;\n ubo[3] = opacity;\n }\n ubo[4] = system._axis[0];\n ubo[5] = system._axis[1];\n ubo[6] = system._axis[2];\n ubo[7] = system.alphaCutoff;\n}\n\nexport function writeBillboardSystemUboIfDirty(device: GPUDevice, uniformBuffer: GPUBuffer, scratchUbo: Float32Array, lastUbo: Float32Array, forceWrite: boolean): void {\n let dirty = forceWrite;\n if (!dirty) {\n for (let index = 0; index < BILLBOARD_SYSTEM_UBO_FLOATS; index++) {\n if (lastUbo[index] !== scratchUbo[index]) {\n dirty = true;\n break;\n }\n }\n }\n if (dirty) {\n device.queue.writeBuffer(uniformBuffer, 0, scratchUbo.buffer, scratchUbo.byteOffset, BILLBOARD_SYSTEM_UBO_BYTES);\n lastUbo.set(scratchUbo);\n }\n}\n\nexport function createBillboardSystemBindGroup(\n engine: EngineContext,\n pipeline: GPURenderPipeline,\n system: BillboardSpriteSystem,\n uniformBuffer: GPUBuffer,\n fx?: SpriteLayerFx | null\n): GPUBindGroup {\n const texture = system.atlas.texture;\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: uniformBuffer } },\n { binding: 1, resource: texture.view },\n { binding: 2, resource: texture.sampler },\n ];\n if (fx) {\n for (const entry of _getBillboardFxHook()!.bindEntries(fx, 3)) {\n entries.push(entry);\n }\n }\n return engine._device.createBindGroup({\n layout: pipeline.getBindGroupLayout(1),\n entries,\n });\n}\n\nfunction getBillboardPipelineDeviceCache(engine: EngineContext, cache: BillboardPipelineCache): BillboardPipelineDeviceCache {\n let deviceCache = cache._devices.get(engine._device);\n if (!deviceCache) {\n deviceCache = { _shaderModules: new Map(), _pipelines: new Map() };\n cache._devices.set(engine._device, deviceCache);\n }\n return deviceCache;\n}\n\nfunction getShaderModule(engine: EngineContext, cache: BillboardPipelineDeviceCache, system: BillboardSpriteSystem): GPUShaderModule {\n const orientation = system._orientation;\n const depthMode = system._depthMode;\n const customModule = _getBillboardFxHook()?.shaderModule(engine, system);\n if (customModule) {\n return customModule;\n }\n const key = `${orientation}:${getDepthModeEntry(depthMode).index}`;\n let module = cache._shaderModules.get(key);\n if (!module) {\n module = engine._device.createShaderModule({ code: makeBillboardWgsl(orientation, depthMode) });\n cache._shaderModules.set(key, module);\n }\n return module;\n}\n\nfunction buildBillboardPipeline(\n engine: EngineContext,\n cache: BillboardPipelineDeviceCache,\n format: GPUTextureFormat,\n sampleCount: 1 | 4,\n system: BillboardSpriteSystem,\n depthStencilFormat: GPUTextureFormat,\n sceneBindGroupLayout: GPUBindGroupLayout\n): GPURenderPipeline {\n const device = engine._device;\n const depthEntry = getDepthModeEntry(system._depthMode);\n const shaderModule = getShaderModule(engine, cache, system);\n const layoutEntries: GPUBindGroupLayoutEntry[] = [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n ];\n const extraLayoutEntries = _getBillboardFxHook()?.layoutEntries(system, 3);\n if (extraLayoutEntries) {\n for (const entry of extraLayoutEntries) {\n layoutEntries.push(entry);\n }\n }\n const billboardBindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });\n return device.createRenderPipeline({\n label: `${system._orientation}-billboard-sprite-pipeline`,\n layout: device.createPipelineLayout({ bindGroupLayouts: [sceneBindGroupLayout, billboardBindGroupLayout] }),\n vertex: {\n module: shaderModule,\n entryPoint: \"vs\",\n buffers: [\n {\n arrayStride: BILLBOARD_INSTANCE_STRIDE_BYTES,\n stepMode: \"instance\",\n attributes: [\n { shaderLocation: 0, offset: BILLBOARD_POSITION_OFFSET_BYTES, format: \"float32x3\" },\n { shaderLocation: 1, offset: BILLBOARD_SIZE_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 2, offset: BILLBOARD_UV_MIN_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 3, offset: BILLBOARD_UV_MAX_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 4, offset: BILLBOARD_ROTATION_OFFSET_BYTES, format: \"float32\" },\n { shaderLocation: 5, offset: BILLBOARD_PIVOT_OFFSET_BYTES, format: \"float32x2\" },\n { shaderLocation: 6, offset: BILLBOARD_COLOR_OFFSET_BYTES, format: \"float32x4\" },\n ],\n },\n ],\n },\n fragment: {\n module: shaderModule,\n entryPoint: \"fs\",\n targets: [system.blendMode._descriptor ? { format, blend: system.blendMode._descriptor, writeMask: GPUColorWrite.ALL } : { format, writeMask: GPUColorWrite.ALL }],\n },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n depthStencil: { format: depthStencilFormat, depthCompare: \"greater-equal\", depthWriteEnabled: depthEntry.writeEnabled },\n multisample: { count: sampleCount },\n });\n}\n","/**\n * Optional, tree-shakable custom-shader hook for `*BillboardSpriteSystem`.\n *\n * The default billboard pipeline bakes a fixed fragment (sample × tint, with an optional cutout\n * discard). Some scenes need a different per-fragment treatment — palette-indexed sampling,\n * COLORMAP light banding, toon shading, custom fog — and/or extra texture bindings beyond the\n * atlas. This module lets a caller supply a WGSL fragment body plus extra textures while the\n * billboard system keeps full ownership of geometry, instancing, sorting, and depth.\n *\n * Tree-shaking contract: the default billboard path never imports this module.\n * `billboard-pipeline.ts` only reaches the custom composer through the opaque object a caller\n * builds here via `createBillboardCustomShader`, so a scene that uses only stock billboards\n * pays zero bytes for this code.\n *\n * WGSL contract for the supplied `fragment` body:\n * - Receives `in: VOut` with: `uv: vec2<f32>`, `tint: vec4<f32>` (the per-sprite `color`),\n * `viewDist: f32` (distance from the camera to the sprite anchor in world units, constant\n * across the quad), `vWorldPos: vec3<f32>` (this fragment's world position).\n * - Has access to `atlasTex` / `atlasSamp` (the system atlas at group 1, bindings 1/2), each\n * extra texture as `<name>Tex` / `<name>Samp`, the `fx` UBO (`fx.time`, `fx.params`), and\n * the `billboards` system UBO (e.g. `billboards.opacityMul`).\n * - Must `return vec4<f32>(...)` (and may `discard`). No automatic cutout is injected — the\n * body owns all alpha handling.\n */\nimport { SCENE_UBO_WGSL } from \"../shader/scene-uniforms.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { BillboardDepthMode, BillboardOrientation } from \"./billboard-sprite.js\";\nimport { makeBillboardBasisWgsl } from \"./billboard-pipeline.js\";\nimport type { CustomShaderTexture, SpriteLayerFx } from \"./custom-shader-core.js\";\nimport {\n createSpriteLayerFx,\n EMPTY_PARAMS,\n makeCustomShaderLayoutEntries,\n makeExtraBindingsWgsl,\n makeFxStructWgsl,\n makeShaderModuleCache,\n nextCustomShaderKey,\n validateExtraTextureNames,\n} from \"./custom-shader-core.js\";\nimport type { BillboardFxHook } from \"./sprite-fx-hook.js\";\nimport { _registerBillboardFxHook } from \"./sprite-fx-hook.js\";\n\n/** One extra texture bound after the atlas (group 1, bindings 3, 5, 7, …). */\nexport type BillboardCustomTexture = CustomShaderTexture;\n\n/** Options for {@link createBillboardCustomShader}. */\nexport interface BillboardCustomShaderOptions {\n /** WGSL fragment body. See the module docs for the in-scope identifiers. */\n readonly fragment: string;\n /** Extra textures, in binding order. Each contributes a `texture_2d` + `sampler`. */\n readonly extraTextures?: readonly BillboardCustomTexture[];\n}\n\n/** Opaque custom-shader descriptor produced by {@link createBillboardCustomShader}. */\nexport interface BillboardCustomShader {\n /** @internal */\n readonly _entityType: \"billboard-custom-shader\";\n /** @internal Extra textures bound after the atlas. */\n readonly _extraTextures: readonly BillboardCustomTexture[];\n /** @internal Pipeline/shader-module cache discriminator. */\n readonly _key: string;\n /** @internal Builds the full WGSL for the given orientation (depth mode is irrelevant — the body owns alpha). */\n readonly _composeWgsl: (orientation: BillboardOrientation, depthMode: BillboardDepthMode) => string;\n /** @internal Compile + cache the `GPUShaderModule` for an orientation (owns its per-device cache). */\n readonly _getShaderModule: (engine: EngineContext, orientation: BillboardOrientation, depthMode: BillboardDepthMode) => GPUShaderModule;\n /** @internal Extra-texture + fx UBO bind-group **layout** entries, starting at `startBinding` (3). */\n readonly _layoutEntries: (startBinding: number) => GPUBindGroupLayoutEntry[];\n /** @internal Build the opaque per-system fx attachment (owns the `SpriteFx` UBO, scratch, and elapsed time). */\n readonly _createLayerFx: (engine: EngineContext, label: string) => SpriteLayerFx;\n}\n\nfunction makeCustomBillboardWgsl(orientation: BillboardOrientation, extraTextures: readonly BillboardCustomTexture[], fragment: string): string {\n const fxBinding = 3 + extraTextures.length * 2;\n return `${SCENE_UBO_WGSL}\nstruct BillboardSystem {\nopacityMul: vec4<f32>,\naxisAndCutoff: vec4<f32>,\n};\n@group(1) @binding(0) var<uniform> billboards: BillboardSystem;\n@group(1) @binding(1) var atlasTex: texture_2d<f32>;\n@group(1) @binding(2) var atlasSamp: sampler;\n${makeExtraBindingsWgsl(1, 3, extraTextures)}${makeFxStructWgsl(1, fxBinding)}\n${makeBillboardBasisWgsl(orientation)}\nstruct VIn {\n@builtin(vertex_index) vid: u32,\n@location(0) iPos: vec3<f32>,\n@location(1) iSize: vec2<f32>,\n@location(2) iUvMin: vec2<f32>,\n@location(3) iUvMax: vec2<f32>,\n@location(4) iRot: f32,\n@location(5) iPivot: vec2<f32>,\n@location(6) iColor: vec4<f32>,\n};\nstruct VOut {\n@builtin(position) pos: vec4<f32>,\n@location(0) uv: vec2<f32>,\n@location(1) tint: vec4<f32>,\n@location(2) viewDist: f32,\n@location(3) vWorldPos: vec3<f32>,\n};\n@vertex\nfn vs(in: VIn) -> VOut {\nlet corner = vec2<f32>(select(0.0, 1.0, in.vid == 1u || in.vid == 2u), select(0.0, 1.0, in.vid >= 2u));\nlet local = (corner - in.iPivot) * in.iSize;\nlet cosRot = cos(in.iRot);\nlet sinRot = sin(in.iRot);\nlet rotated = vec2<f32>(local.x * cosRot - local.y * sinRot, local.x * sinRot + local.y * cosRot);\nlet basis = getBillboardBasis(in.iPos);\nlet worldPos = in.iPos + basis.right * rotated.x + basis.up * rotated.y;\nvar out: VOut;\nout.pos = scene.viewProjection * vec4<f32>(worldPos, 1.0);\nout.uv = mix(in.iUvMin, in.iUvMax, corner);\nout.tint = in.iColor;\nlet viewCenter = scene.view * vec4<f32>(in.iPos, 1.0);\nout.viewDist = length(viewCenter.xyz);\nout.vWorldPos = worldPos;\nreturn out;\n}\n@fragment\nfn fs(in: VOut) -> @location(0) vec4<f32> {\n${fragment}\n}`;\n}\n\n/**\n * The billboard custom-shader hook implementation. Lives only in this (tree-shaken) module, so the\n * always-loaded billboard path never names `_customShader` / `shaderParams`. Reads both off the\n * opaque `system` and delegates to the descriptor's underscore-prefixed (mangled) methods.\n */\nconst BILLBOARD_FX_HOOK: BillboardFxHook = {\n initSystem(system, opts) {\n const customShader = opts.customShader;\n if (customShader) {\n (system as { _customShader?: BillboardCustomShader })._customShader = customShader;\n system.shaderParams = [0, 0, 0, 0];\n }\n },\n pipelineKeyPart(system) {\n return system._customShader?._key ?? \"\";\n },\n shaderModule(engine, system) {\n return system._customShader?._getShaderModule(engine, system._orientation, system._depthMode) ?? null;\n },\n layoutEntries(system, startBinding) {\n return system._customShader?._layoutEntries(startBinding) ?? null;\n },\n createLayerFx(engine, label, system) {\n return system._customShader?._createLayerFx(engine, label) ?? null;\n },\n updateFx(fx, system, deltaMs) {\n fx.update(system.shaderParams ?? EMPTY_PARAMS, deltaMs);\n },\n bindEntries(fx, startBinding) {\n return fx.bindEntries(startBinding);\n },\n disposeFx(fx) {\n fx.destroy();\n },\n};\n\n/**\n * Build a custom-shader descriptor to pass as `customShader` when creating a billboard system.\n * The descriptor is opaque; the pipeline consumes it lazily.\n */\nexport function createBillboardCustomShader(options: BillboardCustomShaderOptions): BillboardCustomShader {\n _registerBillboardFxHook(BILLBOARD_FX_HOOK);\n const fragment = options.fragment;\n if (typeof fragment !== \"string\" || fragment.trim().length === 0) {\n throw new Error(\"createBillboardCustomShader: `fragment` must be a non-empty WGSL string.\");\n }\n const extraTextures = options.extraTextures ?? [];\n validateExtraTextureNames(\"createBillboardCustomShader\", extraTextures);\n const moduleCache = makeShaderModuleCache();\n return {\n _entityType: \"billboard-custom-shader\",\n _extraTextures: extraTextures,\n _key: nextCustomShaderKey(\"c\"),\n _composeWgsl: (orientation) => makeCustomBillboardWgsl(orientation, extraTextures, fragment),\n _getShaderModule: (engine, orientation, depthMode) =>\n moduleCache(engine, `${orientation}:${depthMode}`, () => makeCustomBillboardWgsl(orientation, extraTextures, fragment)),\n _layoutEntries: (startBinding) => makeCustomShaderLayoutEntries(extraTextures, startBinding),\n _createLayerFx: (engine, label) => createSpriteLayerFx(engine, label, extraTextures),\n };\n}\n","/** Optional stable-identity Handle API for BillboardSpriteSystem. */\nimport type { BillboardIndexHandleHooks, BillboardSpriteInit, BillboardSpriteSystem } from \"./billboard-sprite.js\";\nimport { addBillboardSpriteIndex, removeBillboardSpriteIndex, setBillboardSpriteFrameIndex, updateBillboardSpriteIndex } from \"./billboard-sprite.js\";\n\n/** Stable identity for a single billboard sprite that survives swap-remove reindexing. */\nexport interface BillboardSpriteHandle {\n /** @internal */\n readonly _entityType: \"billboard-sprite-handle\";\n readonly system: BillboardSpriteSystem;\n readonly id: number;\n}\n\ninterface BillboardHandleState {\n nextId: number;\n idToIndex: Map<number, number>;\n indexToId: Uint32Array;\n}\n\ninterface BillboardSystemWithHandles extends BillboardSpriteSystem {\n _handleState?: BillboardHandleState;\n}\n\nconst MAX_HANDLE_ID = 0xffffffff;\n\nfunction getOrCreateState(system: BillboardSpriteSystem): BillboardHandleState {\n const withHandles = system as BillboardSystemWithHandles;\n let state = withHandles._handleState;\n if (state) {\n ensureIndexCapacity(system, state);\n return state;\n }\n\n state = {\n nextId: 1,\n idToIndex: new Map<number, number>(),\n indexToId: new Uint32Array(system._capacity),\n };\n const hooks: BillboardIndexHandleHooks = {\n removeIndex(index, last): void {\n onRemoveIndex(state!, index, last);\n },\n clear(): void {\n state!.idToIndex.clear();\n state!.indexToId.fill(0);\n },\n };\n withHandles._handleState = state;\n withHandles._handleHooks = hooks;\n return state;\n}\n\nfunction getState(system: BillboardSpriteSystem): BillboardHandleState | undefined {\n return (system as BillboardSystemWithHandles)._handleState;\n}\n\nfunction ensureIndexCapacity(system: BillboardSpriteSystem, state: BillboardHandleState): void {\n if (state.indexToId.length >= system._capacity) {\n return;\n }\n const next = new Uint32Array(system._capacity);\n next.set(state.indexToId);\n state.indexToId = next;\n}\n\nfunction onRemoveIndex(state: BillboardHandleState, index: number, last: number): void {\n const removedId = state.indexToId[index] ?? 0;\n const movedId = state.indexToId[last] ?? 0;\n if (removedId !== 0) {\n state.idToIndex.delete(removedId);\n }\n if (index !== last) {\n if (movedId !== 0) {\n state.idToIndex.set(movedId, index);\n }\n if (index < state.indexToId.length) {\n state.indexToId[index] = movedId;\n }\n } else if (index < state.indexToId.length) {\n state.indexToId[index] = 0;\n }\n if (last < state.indexToId.length) {\n state.indexToId[last] = 0;\n }\n}\n\nfunction allocateId(state: BillboardHandleState): number {\n const id = state.nextId;\n if (id > MAX_HANDLE_ID) {\n throw new Error(\"addBillboardSprite: handle id space exhausted.\");\n }\n state.nextId = id + 1;\n return id;\n}\n\nfunction lookupIndex(handle: BillboardSpriteHandle): number | null {\n const state = getState(handle.system);\n if (!state) {\n return null;\n }\n const index = state.idToIndex.get(handle.id);\n return index === undefined ? null : index;\n}\n\nfunction requireIndex(handle: BillboardSpriteHandle, caller: string): number {\n const index = lookupIndex(handle);\n if (index === null) {\n throw new Error(`${caller}: BillboardSpriteHandle ${handle.id} has been removed.`);\n }\n return index;\n}\n\n/**\n * Adds a billboard sprite to the system and returns a stable handle to it.\n * @param system - Billboard system to add the sprite to.\n * @param init - Initial sprite properties.\n * @returns A handle that stays valid as sprites are added and removed.\n */\nexport function addBillboardSprite(system: BillboardSpriteSystem, init: BillboardSpriteInit): BillboardSpriteHandle {\n const index = addBillboardSpriteIndex(system, init);\n const state = getOrCreateState(system);\n const id = allocateId(state);\n state.idToIndex.set(id, index);\n state.indexToId[index] = id;\n return { _entityType: \"billboard-sprite-handle\", system, id };\n}\n\n/**\n * Updates the properties of the billboard sprite referenced by `handle`.\n * @param handle - Handle of the sprite to update.\n * @param patch - Partial set of properties to overwrite.\n * @throws If the handle has already been removed.\n */\nexport function updateBillboardSprite(handle: BillboardSpriteHandle, patch: Partial<BillboardSpriteInit>): void {\n updateBillboardSpriteIndex(handle.system, requireIndex(handle, \"updateBillboardSprite\"), patch);\n}\n\n/**\n * Removes the billboard sprite referenced by `handle`. Does nothing if it is already gone.\n * @param handle - Handle of the sprite to remove.\n */\nexport function removeBillboardSprite(handle: BillboardSpriteHandle): void {\n const index = lookupIndex(handle);\n if (index === null) {\n return;\n }\n removeBillboardSpriteIndex(handle.system, index);\n}\n\n/**\n * Sets the atlas frame of the billboard sprite referenced by `handle`, preserving its world size and flip state.\n * @param handle - Handle of the sprite to update.\n * @param frame - Atlas frame index.\n * @throws If the handle has already been removed.\n */\nexport function setBillboardSpriteFrame(handle: BillboardSpriteHandle, frame: number): void {\n setBillboardSpriteFrameIndex(handle.system, requireIndex(handle, \"setBillboardSpriteFrame\"), frame);\n}\n\n/**\n * Resolves the current instance index of the sprite referenced by `handle`.\n * @param handle - Handle of the sprite to resolve.\n * @returns The current instance index in the system's buffers.\n * @throws If the handle has already been removed.\n */\nexport function getBillboardSpriteHandleIndex(handle: BillboardSpriteHandle): number {\n return requireIndex(handle, \"getBillboardSpriteHandleIndex\");\n}\n\n/**\n * Returns `true` if the sprite referenced by `handle` is still present in its system.\n * @param handle - Handle to test.\n */\nexport function isBillboardSpriteHandleAlive(handle: BillboardSpriteHandle): boolean {\n return lookupIndex(handle) !== null;\n}\n","import type { SceneContext } from \"../scene/scene-core.js\";\nimport { addDeferredSceneRenderables } from \"../scene/scene-core.js\";\nimport type { AxisLockedBillboardSpriteSystem, BillboardSpriteSystem, FacingBillboardSpriteSystem } from \"./billboard-sprite.js\";\n\nfunction addBillboardSystem(scene: SceneContext, system: BillboardSpriteSystem): void {\n addDeferredSceneRenderables(scene, async (engine) => {\n const { buildBillboardRenderable } = await import(\"./billboard-renderable.js\");\n const built = buildBillboardRenderable(engine, system);\n return { renderables: [built.renderable], dispose: built.dispose };\n });\n}\n\n/**\n * Adds a camera-facing billboard sprite system to the scene so it is rendered each frame.\n * @param scene - Scene that will own and draw the system.\n * @param system - Facing billboard system to register.\n */\nexport function addFacingBillboardSystem(scene: SceneContext, system: FacingBillboardSpriteSystem): void {\n addBillboardSystem(scene, system);\n}\n\n/**\n * Adds an axis-locked billboard sprite system to the scene so it is rendered each frame.\n * @param scene - Scene that will own and draw the system.\n * @param system - Axis-locked billboard system to register.\n */\nexport function addAxisLockedBillboardSystem(scene: SceneContext, system: AxisLockedBillboardSpriteSystem): void {\n addBillboardSystem(scene, system);\n}\n","/** Optional Babylon.js-style frame animation core for sprite families. */\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { SpriteRenderer } from \"./sprite-renderer.js\";\n\n/** Abstracts the sprite a frame animation drives, decoupling the animation core from each sprite family. */\nexport interface SpriteAnimationTarget {\n /** Sets the target's current atlas frame. */\n readonly setFrame: (frame: number) => void;\n /** Optional. Removes the target from its system, used when `removeWhenFinished` is set. */\n readonly remove?: () => void;\n /** Optional. Returns `false` when the target no longer exists, stopping the animation. */\n readonly isAlive?: () => boolean;\n}\n\n/** Optional callbacks and behaviour applied when starting a sprite frame animation. */\nexport interface PlaySpriteAnimationOptions {\n /** Optional. Called once when a non-looping animation reaches its last frame. */\n readonly onEnd?: () => void;\n readonly removeWhenFinished?: boolean;\n}\n\n/** A single frame-range animation playing on a {@link SpriteAnimationTarget}. */\nexport interface SpriteFrameAnimation {\n /** @internal */\n readonly _entityType: \"sprite-frame-animation\";\n readonly target: SpriteAnimationTarget;\n from: number;\n to: number;\n current: number;\n loop: boolean;\n delayMs: number;\n accumulatedMs: number;\n animationStarted: boolean;\n /** Optional. Called once when a non-looping animation reaches its last frame. */\n onEnd?: () => void;\n removeWhenFinished: boolean;\n}\n\n/** Optional configuration for a sprite animation manager. */\nexport interface SpriteAnimationManagerOptions {\n readonly fixedDeltaMs?: number;\n /** Optional. Called each tick of the manager's autonomous loop with the elapsed milliseconds. */\n readonly onUpdate?: (deltaMs: number) => void;\n}\n\n/** Owns a set of sprite frame animations and advances them in lockstep. */\nexport interface SpriteAnimationManager {\n /** @internal */\n readonly _entityType: \"sprite-animation-manager\";\n animations: SpriteFrameAnimation[];\n fixedDeltaMs: number;\n running: boolean;\n /** @internal */\n readonly _onUpdate?: (deltaMs: number) => void;\n /** @internal */\n _binding?: SpriteAnimationBinding;\n /** @internal */\n _animationManager?: import(\"../animation/animation-manager.js\").AnimationManager;\n /** @internal */\n _loopManager?: import(\"../animation/animation-manager.js\").AnimationManager;\n /** @internal Animation task created by sprite-animation-task. */\n _animationTask?: import(\"../animation/animation-manager.js\").AnimationTask;\n}\n\n/** Handle to a sprite animation manager attached to a scene or renderer; dispose it to detach. */\nexport interface SpriteAnimationBinding {\n /** @internal */\n readonly _entityType: \"sprite-animation-binding\";\n active: boolean;\n /** @internal */\n _dispose: () => void;\n}\n\nlet spriteAnimationOwners: WeakMap<SpriteFrameAnimation, SpriteAnimationManager> | undefined;\n\nfunction getSpriteAnimationOwners(): WeakMap<SpriteFrameAnimation, SpriteAnimationManager> {\n if (!spriteAnimationOwners) {\n spriteAnimationOwners = new WeakMap();\n }\n return spriteAnimationOwners;\n}\n\nfunction getSpriteAnimationOwner(animation: SpriteFrameAnimation): SpriteAnimationManager | undefined {\n return spriteAnimationOwners?.get(animation);\n}\n\nfunction setSpriteAnimationOwner(animation: SpriteFrameAnimation, manager: SpriteAnimationManager): void {\n getSpriteAnimationOwners().set(animation, manager);\n}\n\nfunction clearSpriteAnimationOwner(animation: SpriteFrameAnimation): void {\n spriteAnimationOwners?.delete(animation);\n}\n\nfunction normalizeDelay(delayMs: number): number {\n return Number.isFinite(delayMs) && delayMs > 1 ? delayMs : 1;\n}\n\n/**\n * Creates an empty sprite animation manager.\n * @param options - Optional fixed time step and per-tick update callback.\n * @returns The new manager.\n */\nexport function createSpriteAnimationManager(options?: SpriteAnimationManagerOptions): SpriteAnimationManager {\n const manager: SpriteAnimationManager = {\n _entityType: \"sprite-animation-manager\",\n animations: [],\n fixedDeltaMs: options?.fixedDeltaMs ?? 0,\n running: false,\n _onUpdate: options?.onUpdate,\n };\n return manager;\n}\n\n/**\n * Creates a sprite frame animation and immediately shows its first frame.\n * @param target - Sprite the animation drives.\n * @param from - First frame index of the range.\n * @param to - Last frame index of the range; may be less than `from` to play in reverse.\n * @param loop - When `true`, the animation restarts after reaching `to`.\n * @param delayMs - Delay in milliseconds between frame steps.\n * @param options - Optional end callback and removal behaviour.\n * @returns The new animation, not yet attached to any manager.\n * @throws If `from` or `to` is not finite.\n */\nexport function createSpriteFrameAnimation(\n target: SpriteAnimationTarget,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n if (!Number.isFinite(from) || !Number.isFinite(to)) {\n throw new Error(\"Sprite frame animation requires finite from/to frame indices.\");\n }\n const fromFrame = Math.trunc(from);\n const toFrame = Math.trunc(to);\n const animation: SpriteFrameAnimation = {\n _entityType: \"sprite-frame-animation\",\n target,\n from: fromFrame,\n to: toFrame,\n current: fromFrame,\n loop,\n delayMs: normalizeDelay(delayMs),\n accumulatedMs: 0,\n animationStarted: true,\n onEnd: options?.onEnd,\n removeWhenFinished: options?.removeWhenFinished === true,\n };\n target.setFrame(fromFrame);\n return animation;\n}\n\n/** Add an animation to a manager, transferring ownership if it already belongs to another manager. */\nexport function addSpriteAnimation(manager: SpriteAnimationManager, animation: SpriteFrameAnimation): void {\n const owner = getSpriteAnimationOwner(animation);\n if (owner === manager) {\n return;\n }\n if (owner) {\n removeSpriteAnimation(owner, animation);\n }\n setSpriteAnimationOwner(animation, manager);\n manager.animations.push(animation);\n}\n\nexport function playSpriteTargetAnimation(\n manager: SpriteAnimationManager,\n target: SpriteAnimationTarget,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n const animation = createSpriteFrameAnimation(target, from, to, loop, delayMs, options);\n addSpriteAnimation(manager, animation);\n return animation;\n}\n\n/**\n * Removes an animation from a manager and clears its ownership if the manager owns it.\n * @param manager - Manager to remove the animation from.\n * @param animation - Animation to remove.\n */\nexport function removeSpriteAnimation(manager: SpriteAnimationManager, animation: SpriteFrameAnimation): void {\n const index = manager.animations.indexOf(animation);\n if (index !== -1) {\n manager.animations.splice(index, 1);\n }\n if (getSpriteAnimationOwner(animation) === manager) {\n clearSpriteAnimationOwner(animation);\n }\n}\n\n/**\n * Removes every animation owned by the manager, leaving it empty.\n * @param manager - Manager to clear.\n */\nexport function clearSpriteAnimations(manager: SpriteAnimationManager): void {\n for (const animation of manager.animations) {\n if (getSpriteAnimationOwner(animation) === manager) {\n clearSpriteAnimationOwner(animation);\n }\n }\n manager.animations.length = 0;\n}\n\n/** Replay an animation; omit options to keep callbacks/removal, pass options to overwrite them, or `{}` to clear them. */\nexport function playSpriteFrameAnimation(\n animation: SpriteFrameAnimation,\n from = animation.from,\n to = animation.to,\n loop = animation.loop,\n delayMs = animation.delayMs,\n options?: PlaySpriteAnimationOptions\n): void {\n if (!Number.isFinite(from) || !Number.isFinite(to)) {\n throw new Error(\"Sprite frame animation requires finite from/to frame indices.\");\n }\n const fromFrame = Math.trunc(from);\n const toFrame = Math.trunc(to);\n animation.from = fromFrame;\n animation.to = toFrame;\n animation.current = fromFrame;\n animation.loop = loop;\n animation.delayMs = normalizeDelay(delayMs);\n animation.accumulatedMs = 0;\n animation.animationStarted = true;\n if (options !== undefined) {\n animation.onEnd = options.onEnd;\n animation.removeWhenFinished = options.removeWhenFinished === true;\n }\n animation.target.setFrame(fromFrame);\n}\n\n/**\n * Pauses an animation without removing it; it can be resumed with `playSpriteFrameAnimation`.\n * @param animation - Animation to stop.\n */\nexport function stopSpriteAnimation(animation: SpriteFrameAnimation): void {\n animation.animationStarted = false;\n}\n\n/**\n * Advances every animation in the manager by one time step, removing those that have finished.\n * Uses the manager's `fixedDeltaMs` when set, otherwise `deltaMs`.\n * @param manager - Manager to update.\n * @param deltaMs - Elapsed time in milliseconds since the last update.\n */\nexport function updateSpriteAnimationManager(manager: SpriteAnimationManager, deltaMs: number): void {\n const stepMs = manager.fixedDeltaMs > 0 ? manager.fixedDeltaMs : deltaMs;\n if (!Number.isFinite(stepMs) || stepMs < 0) {\n return;\n }\n // Snapshot the list so onEnd callbacks (invoked from advanceSpriteAnimation)\n // can safely clear or remove animations from the same manager without\n // corrupting iteration, and remove finished animations by identity rather\n // than by a possibly-stale index.\n const animations = manager.animations.slice();\n for (const animation of animations) {\n if (!advanceSpriteAnimation(animation, stepMs)) {\n removeSpriteAnimation(manager, animation);\n }\n }\n}\n\nfunction advanceSpriteAnimation(animation: SpriteFrameAnimation, deltaMs: number): boolean {\n if (animation.target.isAlive?.() === false) {\n animation.animationStarted = false;\n return false;\n }\n if (!animation.animationStarted) {\n return true;\n }\n\n animation.accumulatedMs += deltaMs;\n // Match Babylon ThinSprite timing: exact delay does not step, and each update advances at most one frame.\n if (animation.accumulatedMs <= animation.delayMs) {\n return true;\n }\n\n animation.accumulatedMs = animation.accumulatedMs % animation.delayMs;\n const direction = animation.from > animation.to ? -1 : 1;\n const next = animation.current + direction;\n const passedEnd = direction > 0 ? next > animation.to : next < animation.to;\n if (!passedEnd) {\n animation.current = next;\n animation.target.setFrame(next);\n return true;\n }\n\n if (animation.loop) {\n animation.current = animation.from;\n animation.target.setFrame(animation.from);\n return true;\n }\n\n animation.current = animation.to;\n animation.target.setFrame(animation.to);\n animation.animationStarted = false;\n animation.onEnd?.();\n if (animation.removeWhenFinished) {\n animation.target.remove?.();\n }\n return false;\n}\n\n/**\n * Attaches a manager to a scene's before-render hooks so its animations advance each frame.\n * @param scene - Scene whose render loop drives the manager.\n * @param manager - Sprite animation manager to attach.\n * @returns A binding that detaches the manager when disposed.\n * @throws If the manager is already running or attached elsewhere.\n */\nexport function attachSpriteAnimationsToScene(scene: SceneContext, manager: SpriteAnimationManager): SpriteAnimationBinding {\n assertCanAttachToRenderLoop(manager);\n const hook = (deltaMs: number): void => {\n updateSpriteAnimationManager(manager, deltaMs);\n };\n // Run before hooks currently registered on the scene; later onBeforeRender calls can still prepend ahead of it.\n scene._beforeRender.unshift(hook);\n\n const binding: SpriteAnimationBinding = {\n _entityType: \"sprite-animation-binding\",\n active: true,\n _dispose: () => {\n const index = scene._beforeRender.indexOf(hook);\n if (index !== -1) {\n scene._beforeRender.splice(index, 1);\n }\n if (manager._binding === binding) {\n manager._binding = undefined;\n }\n },\n };\n manager._binding = binding;\n scene._disposables.push(() => disposeSpriteAnimationBinding(binding));\n return binding;\n}\n\n/**\n * Attaches a manager to a sprite renderer's update hooks so its animations advance each frame.\n * @param renderer - Sprite renderer whose update loop drives the manager.\n * @param manager - Sprite animation manager to attach.\n * @returns A binding that detaches the manager when disposed.\n * @throws If the manager is already running or attached elsewhere.\n */\nexport function attachSpriteAnimationsToRenderer(renderer: SpriteRenderer, manager: SpriteAnimationManager): SpriteAnimationBinding {\n assertCanAttachToRenderLoop(manager);\n const hook = (deltaMs: number): void => {\n updateSpriteAnimationManager(manager, deltaMs);\n };\n renderer._beforeUpdate.push(hook);\n\n const binding: SpriteAnimationBinding = {\n _entityType: \"sprite-animation-binding\",\n active: true,\n _dispose: () => {\n const index = renderer._beforeUpdate.indexOf(hook);\n if (index !== -1) {\n renderer._beforeUpdate.splice(index, 1);\n }\n const disposeIndex = renderer._disposeCallbacks.indexOf(disposeWithRenderer);\n if (disposeIndex !== -1) {\n renderer._disposeCallbacks.splice(disposeIndex, 1);\n }\n if (manager._binding === binding) {\n manager._binding = undefined;\n }\n },\n };\n function disposeWithRenderer(): void {\n disposeSpriteAnimationBinding(binding);\n }\n manager._binding = binding;\n renderer._disposeCallbacks.push(disposeWithRenderer);\n return binding;\n}\n\n/**\n * Detaches a binding created by {@link attachSpriteAnimationsToScene} or\n * {@link attachSpriteAnimationsToRenderer}. Safe to call more than once.\n * @param binding - Binding to dispose.\n */\nexport function disposeSpriteAnimationBinding(binding: SpriteAnimationBinding): void {\n if (!binding.active) {\n return;\n }\n binding.active = false;\n binding._dispose();\n}\n\nfunction assertNoActiveBinding(manager: SpriteAnimationManager): void {\n if (manager._binding?.active) {\n throw new Error(\"SpriteAnimationManager is already attached to a render loop.\");\n }\n if (manager._animationManager && manager._animationManager !== manager._loopManager) {\n throw new Error(\"SpriteAnimationManager is already attached to an AnimationManager.\");\n }\n}\n\nfunction assertCanAttachToRenderLoop(manager: SpriteAnimationManager): void {\n if (manager.running) {\n throw new Error(\"SpriteAnimationManager is already running autonomously.\");\n }\n assertNoActiveBinding(manager);\n}\n","import { addAnimationTask, createAnimationManager, createAnimationTask, removeAnimationTask, startAnimationManager, stopAnimationManager } from \"../animation/animation-manager.js\";\nimport type { AnimationManager, AnimationTask } from \"../animation/animation-manager.js\";\nimport type { SpriteAnimationManager } from \"./sprite-animation.js\";\nimport { updateSpriteAnimationManager } from \"./sprite-animation.js\";\n\nfunction getSpriteAnimationTask(manager: SpriteAnimationManager): AnimationTask {\n if (!manager._animationTask) {\n manager._animationTask = createAnimationTask(\n (_animationManager, deltaMs) => {\n updateSpriteAnimationManager(manager, deltaMs);\n },\n {\n dispose: (animationManager) => {\n if (manager._animationManager === animationManager) {\n manager._animationManager = undefined;\n }\n if (manager._loopManager === animationManager) {\n manager.running = false;\n }\n },\n }\n );\n }\n return manager._animationTask;\n}\n\n/**\n * Attaches a sprite animation manager to a shared animation manager so it ticks with it.\n * @param manager - Animation manager that will drive the sprite manager.\n * @param spriteManager - Sprite animation manager to attach.\n * @throws If the sprite manager is already running or attached elsewhere.\n */\nexport function addSpriteAnimationManager(manager: AnimationManager, spriteManager: SpriteAnimationManager): void {\n if (spriteManager._animationManager === manager) {\n return;\n }\n assertCanAttachToAnimationManager(spriteManager);\n addAnimationTask(manager, getSpriteAnimationTask(spriteManager));\n spriteManager._animationManager = manager;\n}\n\n/**\n * Detaches a sprite animation manager previously attached with {@link addSpriteAnimationManager}.\n * @param manager - Animation manager the sprite manager was attached to.\n * @param spriteManager - Sprite animation manager to detach.\n */\nexport function removeSpriteAnimationManager(manager: AnimationManager, spriteManager: SpriteAnimationManager): void {\n const task = spriteManager._animationTask;\n if (task) {\n removeAnimationTask(manager, task);\n }\n}\n\n/**\n * Starts a sprite animation manager on its own autonomous animation loop.\n * @param manager - Sprite animation manager to start.\n * @throws If the manager is already attached to a render loop or another manager.\n */\nexport function startSpriteAnimationManager(manager: SpriteAnimationManager): void {\n if (manager.running) {\n return;\n }\n assertNoActiveBinding(manager);\n let loopManager = manager._loopManager;\n if (!loopManager) {\n loopManager = createAnimationManager({ fixedDeltaMs: manager.fixedDeltaMs, onUpdate: manager._onUpdate });\n manager._loopManager = loopManager;\n }\n loopManager.fixedDeltaMs = manager.fixedDeltaMs;\n if (manager._animationManager !== loopManager) {\n addAnimationTask(loopManager, getSpriteAnimationTask(manager));\n manager._animationManager = loopManager;\n }\n startAnimationManager(loopManager);\n manager.running = loopManager.running;\n}\n\n/**\n * Stops a sprite animation manager started with {@link startSpriteAnimationManager}.\n * @param manager - Sprite animation manager to stop.\n */\nexport function stopSpriteAnimationManager(manager: SpriteAnimationManager): void {\n const loopManager = manager._loopManager;\n if (!loopManager) {\n manager.running = false;\n return;\n }\n stopAnimationManager(loopManager);\n const task = manager._animationTask;\n if (task) {\n removeAnimationTask(loopManager, task);\n }\n manager.running = false;\n}\n\nfunction assertNoActiveBinding(manager: SpriteAnimationManager): void {\n if (manager._binding?.active) {\n throw new Error(\"SpriteAnimationManager is already attached to a render loop.\");\n }\n if (manager._animationManager && manager._animationManager !== manager._loopManager) {\n throw new Error(\"SpriteAnimationManager is already attached to an AnimationManager.\");\n }\n}\n\nfunction assertCanAttachToAnimationManager(manager: SpriteAnimationManager): void {\n if (manager.running) {\n throw new Error(\"SpriteAnimationManager is already running autonomously.\");\n }\n if (manager._binding?.active) {\n throw new Error(\"SpriteAnimationManager is already attached to a render loop.\");\n }\n if (manager._animationManager) {\n throw new Error(\"SpriteAnimationManager is already attached to an AnimationManager.\");\n }\n}\n","/**\n * Optional Sprite2D raw-index frame animation helper.\n * Keeps zero-handle slot animation separate from stable-handle tracking.\n */\nimport { playSpriteTargetAnimation } from \"./sprite-animation.js\";\nimport type { PlaySpriteAnimationOptions, SpriteAnimationManager, SpriteFrameAnimation } from \"./sprite-animation.js\";\nimport type { Sprite2DLayer } from \"./sprite-2d.js\";\nimport { removeSprite2DIndex, setSprite2DFrameIndex } from \"./sprite-2d.js\";\n\n/**\n * Play a frame animation against a raw Sprite2D slot index.\n *\n * This is the zero-handle, slot-based path for structurally stable layers.\n * If the slot is swap-removed externally, the animation follows whatever\n * sprite later occupies the same index. Use `playSprite2DAnimation` with a\n * handle when animation must track a stable sprite identity across removals.\n */\nexport function playSprite2DIndexAnimation(\n manager: SpriteAnimationManager,\n layer: Sprite2DLayer,\n index: number,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n return playSpriteTargetAnimation(\n manager,\n {\n setFrame(frame): void {\n setSprite2DFrameIndex(layer, index, frame);\n },\n remove(): void {\n removeSprite2DIndex(layer, index);\n },\n isAlive(): boolean {\n return index >= 0 && index < layer.count;\n },\n },\n from,\n to,\n loop,\n delayMs,\n options\n );\n}\n","/**\n * Optional Sprite2D stable-handle frame animation helper.\n * Imports handle tracking only when callers opt into this entry point.\n */\nimport { playSpriteTargetAnimation } from \"./sprite-animation.js\";\nimport type { PlaySpriteAnimationOptions, SpriteAnimationManager, SpriteFrameAnimation } from \"./sprite-animation.js\";\nimport type { Sprite2DHandle } from \"./sprite-2d-handle.js\";\nimport { isSprite2DHandleAlive, removeSprite2D, setSprite2DFrame } from \"./sprite-2d-handle.js\";\n\n/**\n * Plays a frame animation on a 2D sprite addressed by its stable handle.\n * The handle is resolved each tick, so the animation survives swap-remove reindexing.\n * @param manager - Animation manager that drives the playback.\n * @param handle - Stable handle of the sprite to animate.\n * @param from - First frame index of the range.\n * @param to - Last frame index of the range.\n * @param loop - When `true`, the animation restarts after reaching `to`.\n * @param delayMs - Delay in milliseconds between frame steps.\n * @param options - Optional end callback and removal behaviour.\n * @returns The created sprite frame animation.\n */\nexport function playSprite2DAnimation(\n manager: SpriteAnimationManager,\n handle: Sprite2DHandle,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n return playSpriteTargetAnimation(\n manager,\n {\n setFrame(frame): void {\n setSprite2DFrame(handle, frame);\n },\n remove(): void {\n removeSprite2D(handle);\n },\n isAlive(): boolean {\n return isSprite2DHandleAlive(handle);\n },\n },\n from,\n to,\n loop,\n delayMs,\n options\n );\n}\n","/**\n * Optional billboard raw-index frame animation helper.\n * Keeps zero-handle slot animation separate from stable-handle tracking.\n */\nimport { playSpriteTargetAnimation } from \"./sprite-animation.js\";\nimport type { PlaySpriteAnimationOptions, SpriteAnimationManager, SpriteFrameAnimation } from \"./sprite-animation.js\";\nimport type { BillboardSpriteSystem } from \"./billboard-sprite.js\";\nimport { removeBillboardSpriteIndex, setBillboardSpriteFrameIndex } from \"./billboard-sprite.js\";\n\n/**\n * Play a frame animation against a raw billboard sprite slot index.\n *\n * This is the zero-handle, slot-based path for structurally stable systems.\n * If the slot is swap-removed externally, the animation follows whatever\n * sprite later occupies the same index. Use `playBillboardSpriteAnimation`\n * with a handle when animation must track a stable sprite identity across removals.\n */\nexport function playBillboardSpriteIndexAnimation(\n manager: SpriteAnimationManager,\n system: BillboardSpriteSystem,\n index: number,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n return playSpriteTargetAnimation(\n manager,\n {\n setFrame(frame): void {\n setBillboardSpriteFrameIndex(system, index, frame);\n },\n remove(): void {\n removeBillboardSpriteIndex(system, index);\n },\n isAlive(): boolean {\n return index >= 0 && index < system.count;\n },\n },\n from,\n to,\n loop,\n delayMs,\n options\n );\n}\n","/**\n * Optional billboard stable-handle frame animation helper.\n * Imports handle tracking only when callers opt into this entry point.\n */\nimport { playSpriteTargetAnimation } from \"./sprite-animation.js\";\nimport type { PlaySpriteAnimationOptions, SpriteAnimationManager, SpriteFrameAnimation } from \"./sprite-animation.js\";\nimport type { BillboardSpriteHandle } from \"./billboard-sprite-handle.js\";\nimport { isBillboardSpriteHandleAlive, removeBillboardSprite, setBillboardSpriteFrame } from \"./billboard-sprite-handle.js\";\n\n/**\n * Plays a frame animation on a billboard sprite addressed by its stable handle.\n * The handle is resolved each tick, so the animation survives swap-remove reindexing.\n * @param manager - Animation manager that drives the playback.\n * @param handle - Stable handle of the billboard sprite to animate.\n * @param from - First frame index of the range.\n * @param to - Last frame index of the range.\n * @param loop - When `true`, the animation restarts after reaching `to`.\n * @param delayMs - Delay in milliseconds between frame steps.\n * @param options - Optional end callback and removal behaviour.\n * @returns The created sprite frame animation.\n */\nexport function playBillboardSpriteAnimation(\n manager: SpriteAnimationManager,\n handle: BillboardSpriteHandle,\n from: number,\n to: number,\n loop: boolean,\n delayMs: number,\n options?: PlaySpriteAnimationOptions\n): SpriteFrameAnimation {\n return playSpriteTargetAnimation(\n manager,\n {\n setFrame(frame): void {\n setBillboardSpriteFrame(handle, frame);\n },\n remove(): void {\n removeBillboardSprite(handle);\n },\n isAlive(): boolean {\n return isBillboardSpriteHandleAlive(handle);\n },\n },\n from,\n to,\n loop,\n delayMs,\n options\n );\n}\n","/**\n * `SpriteRenderer` — owns the shared index buffer and per-layer GPU state\n * required to draw `Sprite2DLayer`s. Implements\n * `RenderingContext` directly, so it plugs into `engine._renderingContexts`\n * the same way a `SceneContext` does.\n *\n * Scope:\n * - Pure-2D / HUD path only — all layers must use `depth: \"none\"`.\n * - One sprite-pipeline cache per renderer instance, keyed by format,\n * blend mode, and sample count. The direct HUD path always uses\n * `sampleCount=1` and `hasDepth=false`.\n * - The renderer opens a sprite-only swapchain pass using the engine's\n * current command encoder and swapchain view. Off-screen / HUD-to-texture\n * rendering is deferred until there is a concrete caller.\n */\nimport { getRenderTargetSize, registerRenderingContext, unregisterRenderingContext } from \"../engine/engine.js\";\nimport type { EngineContext, RenderingContext } from \"../engine/engine.js\";\nimport { createEmptyUniformBuffer, createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport type { SpriteLayerFx } from \"./custom-shader-core.js\";\nimport { _getSpriteFxHook } from \"./sprite-fx-hook.js\";\nimport type { Sprite2DLayer } from \"./sprite-2d.js\";\nimport {\n LAYER_UBO_BYTES,\n SHARED_SPRITE_INDEX_DATA,\n buildSpriteLayerUbo,\n createSpriteInstanceBuffer,\n createSpriteLayerBindGroup,\n createSpritePipelineCache,\n ensureSpriteInstanceBuffer,\n getOrCreateSpritePipeline,\n getSpritePipelineCacheSize,\n resetSpritePipelineCache,\n uploadSpriteInstances,\n writeSpriteLayerUboIfDirty,\n} from \"./sprite-pipeline.js\";\nimport type { SpritePipelineCache } from \"./sprite-pipeline.js\";\n\n/** Tag used by the engine and by tests to identify a sprite renderer. */\nconst KIND = \"sprite-renderer\" as const;\n\n/** Options accepted by `createSpriteRenderer`. */\nexport interface SpriteRendererOptions {\n /** Layers to draw, in registration order. The renderer also re-sorts internally each frame. */\n layers: readonly Sprite2DLayer[];\n /** Default true. Set false for HUD overlays so the sprite pass preserves existing scene color. */\n clear?: boolean;\n /** Default `{ r: 0, g: 0, b: 0, a: 1 }`. */\n clearValue?: GPUColorDict;\n}\n\n/**\n * A `SpriteRenderer` — pure data, plugs into `engine._renderingContexts`.\n * Inherits `clearColor`, `_drawCallsPre`, `_update`, `_record` from `RenderingContext`;\n * adds only its discriminator tag and the renderer-owned layer list.\n *\n * **Lifecycle.** A `SpriteRenderer` is independent of any `SceneContext` — it is\n * registered directly on the engine, opens its own sampleCount=1 swapchain pass, and\n * must be disposed by the caller. Two patterns:\n *\n * 1. **Standalone** (no scene, or one or more renderers alongside a scene):\n * `registerSpriteRenderer` after `createSpriteRenderer`, `disposeSpriteRenderer`\n * on shutdown. Caller owns the lifetime end-to-end.\n * 2. **HUD-on-3D** (renderer overlaid on a scene): same `register` step,\n * then tie disposal to the scene with\n * `onSceneDispose(scene, () => disposeSpriteRenderer(hud))` —\n * `disposeScene` then cleans it up automatically. Register the renderer\n * *after* `registerScene` so it draws on top.\n *\n * Scene 52 demonstrates pattern (2). For depth-hosted sprites that should\n * sort against 3D meshes, use `addDepthHostedSpriteLayer(scene, layer)` with\n * a depth-enabled `Sprite2DLayer` instead — that route is fully owned by the scene.\n */\nexport interface SpriteRenderer extends RenderingContext {\n /** @internal */\n readonly _kind: typeof KIND;\n /** Renderer-owned layer membership. Use `addSpriteRendererLayer` / `removeSpriteRendererLayer` to mutate. */\n readonly layers: readonly Sprite2DLayer[];\n /** @internal Mutable alias of {@link layers} — same array, used by internal helpers. */\n _layers: Sprite2DLayer[];\n /** @internal */\n _engine: EngineContext;\n /** @internal */\n _indexBuffer: GPUBuffer;\n /** @internal */\n _pipelineCache: SpritePipelineCache;\n /** @internal */\n _layerGpu: Map<Sprite2DLayer, LayerGpu>;\n /** @internal Hooks run at the start of `_update`, before layer uploads. */\n _beforeUpdate: ((deltaMs: number) => void)[];\n /** @internal Cleanup callbacks run by `disposeSpriteRenderer`; optional integrations register here. */\n _disposeCallbacks: (() => void)[];\n /** @internal */\n _visibleBundles: GPURenderBundle[];\n /** @internal Captured each `_update`, read in `_record`. */\n _targetWidth: number;\n /** @internal */\n _targetHeight: number;\n /** @internal */\n _disposed: boolean;\n /** @internal Whether this pass clears the swapchain before drawing. False for HUD overlays. */\n _clear: boolean;\n}\n\n/** @internal Per-layer GPU resources owned by the renderer. */\ninterface LayerGpu {\n layer: Sprite2DLayer;\n instanceBuffer: GPUBuffer;\n instanceBufferCapacity: number;\n uniformBuffer: GPUBuffer;\n /** Built once per layer; the bind group binds the uniform buffer + atlas texture/sampler,\n * none of which change after construction (atlas is `readonly` on the layer; uniform\n * buffer is allocated once in `ensureLayerGpu`). Cleared if we ever recreate either. */\n bindGroup: GPUBindGroup | null;\n uploadedVersion: number;\n /** Opaque fx attachment (`SpriteFx` UBO, scratch, elapsed time); non-null only for `customShader` layers. */\n fx: SpriteLayerFx | null;\n /** Cached pipeline object. Refreshed when target-defining GPU state resolves to a different pipeline. */\n pipeline: GPURenderPipeline | null;\n /** Snapshot of the last UBO bytes written to `uniformBuffer`. We rebuild the UBO into\n * `_scratchUbo` each frame, then `writeBuffer` only if the contents actually changed.\n * For static scenes (steady-state) this skips one `queue.writeBuffer` per layer per frame. */\n lastUbo: Float32Array;\n /** False until the first UBO upload. Forces an unconditional first write so `lastUbo` is real. */\n uboUploaded: boolean;\n /** Pre-recorded GPU command bundle: `setIndexBuffer` + `setPipeline` + `setBindGroup` +\n * `setVertexBuffer` + `drawIndexed`. Collected into a reused bundle array for\n * near-zero per-frame CPU command-recording cost (the big WebGPU win for static scenes —\n * see `scene-core.ts._record` for the same pattern). Invalidated when `layer.count` changes\n * (the `drawIndexed` instance count is baked into the bundle) or when the instance buffer is\n * reallocated by `ensureLayerGpu` (the bundle holds a GPUBuffer reference). The UBO contents\n * may freely change frame-to-frame — the bundle binds the buffer *object*, not its bytes. */\n renderBundle: GPURenderBundle | null;\n /** `layer.count` value the cached `renderBundle` was recorded against. */\n bundleCount: number;\n}\n\n/**\n * Lazy GPU-resource provisioner for one layer. On first sight: allocates the per-instance\n * vertex buffer + the 48 B layer UBO and stashes a `LayerGpu` record in `_layerGpu`. On\n * subsequent calls where the layer's CPU `_capacity` outgrew the GPU buffer (after\n * `growCapacity` doubled the array): destroys + reallocates the instance buffer at the\n * new size and forces a full re-upload via `uploadedVersion = -1`. The bind group is\n * left intact — it doesn't reference the instance buffer (vertex buffers are bound\n * separately at draw time), only the uniform buffer + atlas, neither of which moves.\n */\nfunction ensureLayerGpu(rr: SpriteRenderer, layer: Sprite2DLayer): LayerGpu {\n let lg = rr._layerGpu.get(layer);\n if (!lg) {\n const cap = layer._capacity;\n const instanceBuffer = createSpriteInstanceBuffer(rr._engine._device, layer, \"sprite-layer-instances\");\n const uniformBuffer = createEmptyUniformBuffer(rr._engine, LAYER_UBO_BYTES, \"sprite-layer-ubo\");\n const fx = _getSpriteFxHook()?.createLayerFx(rr._engine, \"sprite-layer-fx-ubo\", layer) ?? null;\n lg = {\n layer,\n instanceBuffer,\n instanceBufferCapacity: cap,\n uniformBuffer,\n bindGroup: null,\n uploadedVersion: -1,\n fx,\n pipeline: null,\n lastUbo: new Float32Array(LAYER_UBO_BYTES / 4),\n uboUploaded: false,\n renderBundle: null,\n bundleCount: -1,\n };\n rr._layerGpu.set(layer, lg);\n }\n const grown = ensureSpriteInstanceBuffer(rr._engine._device, layer, lg.instanceBuffer, lg.instanceBufferCapacity, \"sprite-layer-instances\");\n if (grown.reallocated) {\n lg.instanceBuffer = grown.buffer;\n lg.instanceBufferCapacity = grown.capacity;\n lg.uploadedVersion = -1;\n // Bundle baked a reference to the *old* GPUBuffer; the new buffer needs a re-record.\n lg.renderBundle = null;\n }\n return lg;\n}\n\n/** Sync one layer's GPU state to its CPU state — instance vertex data + per-layer UBO.\n * Both helpers are version-/dirty-gated and skip work in the steady state. */\nfunction uploadLayer(rr: SpriteRenderer, lg: LayerGpu, deltaMs: number): void {\n const layer = lg.layer;\n lg.uploadedVersion = uploadSpriteInstances(rr._engine._device, layer, lg.instanceBuffer, lg.uploadedVersion);\n buildSpriteLayerUbo(layer, rr._targetWidth, rr._targetHeight, _scratchUbo);\n lg.uboUploaded = writeSpriteLayerUboIfDirty(rr._engine._device, lg.uniformBuffer, _scratchUbo, lg.lastUbo, lg.uboUploaded);\n if (lg.fx) {\n _getSpriteFxHook()!.updateFx(lg.fx, layer, deltaMs);\n }\n}\n\nfunction disposeLayerGpu(lg: LayerGpu): void {\n lg.instanceBuffer.destroy();\n lg.uniformBuffer.destroy();\n if (lg.fx) {\n _getSpriteFxHook()!.disposeFx(lg.fx);\n }\n}\n\nconst _scratchUbo = new Float32Array(LAYER_UBO_BYTES / 4);\n\n/**\n * Build (and cache) the bind group that attaches `lg.uniformBuffer` + atlas texture +\n * sampler to the pipeline's sprite `@group(0)` schema. All three resources are immutable for\n * the layer's lifetime, so this runs at most once per layer; subsequent calls return\n * the cached group. The instance buffer is **not** in the bind group — it's a vertex\n * buffer, bound separately at draw time — which is why instance-buffer growth in\n * `ensureLayerGpu` doesn't invalidate this cache.\n */\nfunction ensureBindGroup(rr: SpriteRenderer, lg: LayerGpu, pipeline: GPURenderPipeline): GPUBindGroup {\n if (lg.bindGroup) {\n return lg.bindGroup;\n }\n lg.bindGroup = createSpriteLayerBindGroup(rr._engine, pipeline, 0, lg.layer, lg.uniformBuffer, lg.fx);\n return lg.bindGroup;\n}\n\n/** Sort key for layers within a renderer: ascending `order` (back-to-front draw order). */\nfunction compareLayers(a: Sprite2DLayer, b: Sprite2DLayer): number {\n if (a.order !== b.order) {\n return a.order - b.order;\n }\n return 0;\n}\n\n/** Create a `SpriteRenderer` for `engine`, pre-warming pipelines for the layers' blend modes. */\nexport function createSpriteRenderer(engine: EngineContext, opts: SpriteRendererOptions): SpriteRenderer {\n assertSpriteRendererLayers(opts.layers);\n const indexBuffer = createMappedBuffer(engine, SHARED_SPRITE_INDEX_DATA, GPUBufferUsage.INDEX);\n const targetSize = getRenderTargetSize(engine);\n\n const layers = opts.layers.slice();\n const rr: SpriteRenderer = {\n _kind: KIND,\n _engine: engine,\n _indexBuffer: indexBuffer,\n _pipelineCache: createSpritePipelineCache(),\n _layerGpu: new Map(),\n _visibleBundles: [],\n _targetWidth: targetSize.width,\n _targetHeight: targetSize.height,\n _disposed: false,\n _clear: opts.clear ?? true,\n _beforeUpdate: [],\n _disposeCallbacks: [],\n layers,\n _layers: layers,\n clearColor: opts.clearValue ?? { r: 0, g: 0, b: 0, a: 1 },\n _drawCallsPre: 0,\n _update(): void {\n spriteRendererUpdate(rr);\n },\n _record(): number {\n return spriteRendererRecord(rr);\n },\n };\n\n // Pre-warm pipelines currently in use, so the first frame doesn't pay compile cost.\n for (const layer of rr.layers) {\n getOrCreateSpritePipeline(rr._engine, rr._pipelineCache, rr._engine.format, 1, layer.blendMode, false, false, undefined, undefined, layer);\n }\n\n return rr;\n}\n\nfunction assertSpriteRendererLayers(layers: readonly Sprite2DLayer[]): void {\n for (const layer of layers) {\n assertSpriteRendererLayer(layer);\n }\n}\n\nfunction assertSpriteRendererLayer(layer: Sprite2DLayer): void {\n if (layer.depth !== \"none\") {\n throw new Error('SpriteRenderer only supports Sprite2DLayer with depth: \"none\". Use addDepthHostedSpriteLayer(scene, layer) for depth-hosted sprites.');\n }\n}\n\n/**\n * Per-frame **update** pass (called by the engine before this renderer records its pass).\n * Refreshes target dims (canvas may have resized), sorts `rr.layers` in place by\n * `order` (TimSort is O(n) on already-sorted input — effectively free in steady state),\n * then walks every visible non-empty layer and runs `ensureLayerGpu` + `uploadLayer`.\n * No GPU draw work here — only buffer uploads via `writeBuffer`.\n */\nfunction spriteRendererUpdate(rr: SpriteRenderer): void {\n if (rr._disposed) {\n return;\n }\n const deltaMs = rr._engine._currentDelta ?? 0;\n for (const hook of rr._beforeUpdate) {\n hook(deltaMs);\n }\n assertSpriteRendererLayers(rr.layers);\n const targetSize = getRenderTargetSize(rr._engine);\n rr._targetWidth = targetSize.width;\n rr._targetHeight = targetSize.height;\n\n // Sort layers in place by `order` once per frame. TimSort is O(n) on already-sorted input,\n // so this is effectively free in the steady state. Documented side-effect on `rr.layers`\n // (registration order is not the ground truth — `layer.order` is). Skipped for the common\n // single-layer case to avoid even the comparator-call overhead.\n if (rr.layers.length > 1) {\n rr._layers.sort(compareLayers);\n }\n\n for (const layer of rr.layers) {\n if (!layer.visible || layer.count === 0) {\n continue;\n }\n const lg = ensureLayerGpu(rr, layer);\n uploadLayer(rr, lg, deltaMs);\n }\n}\n\n/**\n * Per-frame **record** pass (called by the engine after `_update`).\n * For each visible non-empty layer: builds (or reuses) a `GPURenderBundle` that bakes\n * `setIndexBuffer` + `setPipeline` + `setBindGroup` + `setVertexBuffer` + `drawIndexed`,\n * then queues it for a single `pass.executeBundles(...)` replay. The bundle is the per-frame\n * fast path — it skips Chromium's per-call WebGPU validation and IPC, which dominates\n * CPU cost for static scenes at multi-kHz framerates. Bundle is rebuilt only when\n * `layer.count` changes or the instance buffer was reallocated.\n * Returns one draw call per visible non-empty layer (1000 sprites in a layer = 1 draw\n * call thanks to instancing).\n */\nfunction spriteRendererRecord(rr: SpriteRenderer): number {\n if (rr._disposed) {\n return 0;\n }\n assertSpriteRendererLayers(rr.layers);\n const eng = rr._engine;\n const encoder = eng._currentEncoder;\n const swapView = eng._swapchainView;\n\n // Open a sampleCount=1 render pass directly on the swapchain. This keeps HUD\n // sprites from resolving a fresh MSAA target over the already-rendered scene.\n const pass = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: swapView,\n clearValue: rr.clearColor,\n loadOp: rr._clear ? \"clear\" : \"load\",\n storeOp: \"store\",\n },\n ],\n });\n let drawCalls = 0;\n const visibleBundles = rr._visibleBundles;\n visibleBundles.length = 0;\n\n for (const layer of rr.layers) {\n if (!layer.visible || layer.count === 0) {\n continue;\n }\n const lg = rr._layerGpu.get(layer);\n if (!lg) {\n continue;\n }\n const sampleCount = 1;\n const pipeline = getOrCreateSpritePipeline(rr._engine, rr._pipelineCache, rr._engine.format, sampleCount, layer.blendMode, false, false, undefined, undefined, layer);\n if (lg.pipeline !== pipeline) {\n lg.pipeline = pipeline;\n lg.bindGroup = null;\n lg.renderBundle = null;\n }\n const bg = ensureBindGroup(rr, lg, pipeline);\n // (Re)record the bundle when count changes (drawIndexed instance count is baked in)\n // or when ensureLayerGpu reallocated the instance buffer (renderBundle was nulled).\n if (lg.renderBundle == null || lg.bundleCount !== layer.count) {\n const be = rr._engine._device.createRenderBundleEncoder({\n colorFormats: [rr._engine.format],\n sampleCount,\n });\n be.setIndexBuffer(rr._indexBuffer, \"uint16\");\n be.setPipeline(pipeline);\n be.setBindGroup(0, bg);\n be.setVertexBuffer(0, lg.instanceBuffer);\n be.drawIndexed(6, layer.count, 0, 0, 0);\n lg.renderBundle = be.finish();\n lg.bundleCount = layer.count;\n }\n visibleBundles.push(lg.renderBundle!);\n drawCalls++;\n }\n\n if (visibleBundles.length > 0) {\n pass.executeBundles(visibleBundles);\n }\n pass.end();\n return drawCalls;\n}\n\n/** Add a pure-2D layer to the renderer. No-op if the layer is already present. */\nexport function addSpriteRendererLayer(sr: SpriteRenderer, layer: Sprite2DLayer): void {\n if (sr._disposed) {\n throw new Error(\"SpriteRenderer has been disposed.\");\n }\n assertSpriteRendererLayer(layer);\n if (sr.layers.includes(layer)) {\n return;\n }\n sr._layers.push(layer);\n getOrCreateSpritePipeline(sr._engine, sr._pipelineCache, sr._engine.format, 1, layer.blendMode, false);\n}\n\n/** Remove a layer from the renderer and destroy any GPU resources cached for it. */\nexport function removeSpriteRendererLayer(sr: SpriteRenderer, layer: Sprite2DLayer): boolean {\n const index = sr.layers.indexOf(layer);\n if (index < 0) {\n return false;\n }\n sr._layers.splice(index, 1);\n const lg = sr._layerGpu.get(layer);\n if (lg) {\n disposeLayerGpu(lg);\n sr._layerGpu.delete(layer);\n }\n return true;\n}\n\n/** Push the renderer onto its engine's `_renderingContexts`. Idempotent — a second call is a no-op. */\nexport function registerSpriteRenderer(sr: SpriteRenderer): void {\n registerRenderingContext(sr._engine, sr);\n}\n\n/** Splice the renderer out of its engine's `_renderingContexts`. No-op if not present. */\nexport function unregisterSpriteRenderer(sr: SpriteRenderer): void {\n unregisterRenderingContext(sr._engine, sr);\n}\n\n/**\n * Destroy all GPU resources owned by the renderer, unregister it from the engine, and clear `layers`.\n * Idempotent. To tie disposal to a scene, call\n * `onSceneDispose(scene, () => disposeSpriteRenderer(sr))` after `registerSpriteRenderer` —\n * see the `SpriteRenderer` doc-comment.\n */\nexport function disposeSpriteRenderer(sr: SpriteRenderer): void {\n if (sr._disposed) {\n return;\n }\n unregisterSpriteRenderer(sr);\n sr._disposed = true;\n const disposeCallbacks = sr._disposeCallbacks.slice();\n sr._disposeCallbacks.length = 0;\n for (const dispose of disposeCallbacks) {\n dispose();\n }\n for (const lg of sr._layerGpu.values()) {\n disposeLayerGpu(lg);\n }\n sr._layerGpu.clear();\n sr._visibleBundles.length = 0;\n sr._beforeUpdate.length = 0;\n sr._indexBuffer.destroy();\n resetSpritePipelineCache(sr._pipelineCache);\n sr._layers.length = 0;\n}\n\n/** @internal Test-only accessor for pipeline-cache size. */\nexport function _spriteRendererPipelineCacheSize(sr: SpriteRenderer): number {\n return getSpritePipelineCacheSize(sr._pipelineCache, sr._engine._device);\n}\n","/**\n * Havok Physics V2 integration for Babylon Lite.\n *\n * Standalone-function API consistent with Lite conventions:\n * ```ts\n * const world = await createHavokWorld(scene);\n * setPhysicsGravity(world, { x: 0, y: -9.81, z: 0 });\n * const agg = createPhysicsAggregate(world, sphere, PhysicsShapeType.SPHERE, { mass: 1 });\n * ```\n *\n * The WASM binary is loaded lazily on first call and cached for subsequent worlds.\n */\n\nimport type { Vec3, Quat } from \"../math/types.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { onBeforeRender } from \"../scene/scene-core.js\";\n\n// ─── Enums ───────────────────────────────────────────────────────────\n\n/** Geometry type of a physics collision shape. */\nexport const enum PhysicsShapeType {\n SPHERE = 0,\n CAPSULE = 1,\n CYLINDER = 2,\n BOX = 3,\n CONVEX_HULL = 4,\n CONTAINER = 5,\n MESH = 6,\n HEIGHTFIELD = 7,\n}\n\n/** How a body moves: `STATIC` (immovable), `ANIMATED` (driven by the node transform), or `DYNAMIC` (simulated). */\nexport const enum PhysicsMotionType {\n STATIC = 0,\n ANIMATED = 1,\n DYNAMIC = 2,\n}\n\n// ─── Option interfaces ───────────────────────────────────────────────\n\n/** Geometry parameters describing a collision shape; which fields apply depends on the shape type. */\nexport interface PhysicsShapeParameters {\n center?: Vec3;\n radius?: number;\n pointA?: Vec3;\n pointB?: Vec3;\n rotation?: Quat;\n extents?: Vec3;\n}\n\n/** Options for `createPhysicsShape`: the shape type plus its geometry parameters. */\nexport interface PhysicsShapeOptions {\n type: PhysicsShapeType;\n parameters?: PhysicsShapeParameters;\n}\n\n/** Options for `createPhysicsAggregate`: mass, material (friction/restitution), and optional shape geometry overrides. */\nexport interface PhysicsAggregateOptions {\n mass: number;\n friction?: number;\n restitution?: number;\n radius?: number;\n pointA?: Vec3;\n pointB?: Vec3;\n extents?: Vec3;\n rotation?: Quat;\n center?: Vec3;\n startAsleep?: boolean;\n isTriggerShape?: boolean;\n}\n\n// ─── Opaque handles (pure state — no methods) ────────────────────────\n\n/** Opaque handle to a Havok rigid body, bound to a scene node and a motion type. */\nexport interface PhysicsBody {\n /** @internal */ readonly _hkBody: any;\n readonly node: SceneNode;\n readonly motionType: PhysicsMotionType;\n}\n\n/** Opaque handle to a Havok collision shape. */\nexport interface PhysicsShape {\n /** @internal */ readonly _hkShape: any;\n}\n\n/** A body and its shape wired together, as produced by `createPhysicsAggregate`. */\nexport interface PhysicsAggregate {\n readonly body: PhysicsBody;\n readonly shape: PhysicsShape;\n}\n\n// ─── PhysicsWorld — pure-state handle ────────────────────────────────\n\n/** Pure-state handle to a Havok physics world: the WASM module, the native world, its bodies, and the timestep. */\nexport interface PhysicsWorld {\n /** @internal */ readonly _hknp: any;\n /** @internal */ readonly _hkWorld: any;\n /** @internal */ readonly _bodies: PhysicsBody[];\n /** @internal */ _timestep: number;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────\n\n/**\n * Create a Havok physics world and register per-frame stepping on the scene.\n *\n * The caller is responsible for loading the WASM binary externally:\n * ```ts\n * import HavokPhysics from \"@babylonjs/havok\";\n * const hknp = await HavokPhysics({ locateFile: () => \"/HavokPhysics.wasm\" });\n * const world = createHavokWorld(scene, hknp);\n * ```\n */\nexport function createHavokWorld(scene: SceneContext, hknp: any, gravity?: Vec3): PhysicsWorld {\n const hkWorld = hknp.HP_World_Create()[1];\n\n const g = gravity ?? { x: 0, y: -9.81, z: 0 };\n hknp.HP_World_SetGravity(hkWorld, [g.x, g.y, g.z]);\n\n const world: PhysicsWorld = {\n _hknp: hknp,\n _hkWorld: hkWorld,\n _bodies: [],\n _timestep: 1 / 60,\n };\n\n // Register per-frame physics step\n onBeforeRender(scene, (deltaMs: number) => {\n _stepWorld(world, deltaMs);\n });\n\n return world;\n}\n\n// ─── Per-frame stepping ──────────────────────────────────────────────\n\nfunction _stepWorld(world: PhysicsWorld, deltaMs: number): void {\n const { _hknp: hknp, _hkWorld: hkWorld, _bodies: bodies } = world;\n const dt = Math.min(deltaMs / 1000, 0.1);\n if (dt <= 0) {\n return;\n }\n\n // Pre-step: sync ANIMATED bodies from node → Havok\n for (let i = 0; i < bodies.length; i++) {\n const b = bodies[i]!;\n if (b.motionType === (PhysicsMotionType.ANIMATED as number)) {\n _syncNodeToBody(hknp, b);\n }\n }\n\n hknp.HP_World_Step(hkWorld, world._timestep);\n\n // Post-step: sync DYNAMIC bodies from Havok → node\n for (let i = 0; i < bodies.length; i++) {\n const b = bodies[i]!;\n if (b.motionType === (PhysicsMotionType.DYNAMIC as number)) {\n _syncBodyToNode(hknp, b);\n }\n }\n}\n\nfunction _syncBodyToNode(hknp: any, body: PhysicsBody): void {\n const t = hknp.HP_Body_GetQTransform(body._hkBody)[1];\n const pos = t[0]; // [x, y, z]\n const rot = t[1]; // [x, y, z, w]\n const node = body.node;\n node.position.set(pos[0], pos[1], pos[2]);\n node.rotationQuaternion.set(rot[0], rot[1], rot[2], rot[3]);\n}\n\nfunction _syncNodeToBody(hknp: any, body: PhysicsBody): void {\n const node = body.node;\n const p = node.position;\n const q = node.rotationQuaternion;\n hknp.HP_Body_SetQTransform(body._hkBody, [\n [p.x, p.y, p.z],\n [q.x, q.y, q.z, q.w],\n ]);\n}\n\n// ─── Gravity ─────────────────────────────────────────────────────────\n\n/**\n * Sets the world's gravity vector.\n * @param world - The physics world.\n * @param gravity - Gravity acceleration in m/s².\n */\nexport function setPhysicsGravity(world: PhysicsWorld, gravity: Vec3): void {\n world._hknp.HP_World_SetGravity(world._hkWorld, [gravity.x, gravity.y, gravity.z]);\n}\n\n/**\n * Returns the world's current gravity vector.\n * @param world - The physics world.\n * @returns Gravity acceleration in m/s².\n */\nexport function getPhysicsGravity(world: PhysicsWorld): Vec3 {\n const g = world._hknp.HP_World_GetGravity(world._hkWorld)[1];\n return { x: g[0], y: g[1], z: g[2] };\n}\n\n// ─── Timestep ────────────────────────────────────────────────────────\n\n/**\n * Sets the fixed simulation timestep used by each world step.\n * @param world - The physics world.\n * @param dt - Timestep in seconds (e.g. `1 / 60`).\n */\nexport function setPhysicsTimestep(world: PhysicsWorld, dt: number): void {\n world._timestep = dt;\n}\n\n/**\n * Returns the world's fixed simulation timestep in seconds.\n * @param world - The physics world.\n * @returns The timestep in seconds.\n */\nexport function getPhysicsTimestep(world: PhysicsWorld): number {\n return world._timestep;\n}\n\n// ─── Velocity limits ─────────────────────────────────────────────────\n\n/**\n * Clamps the maximum linear and angular speeds of bodies in the world.\n * @param world - The physics world.\n * @param maxLinear - Maximum linear speed.\n * @param maxAngular - Maximum angular speed.\n */\nexport function setPhysicsVelocityLimits(world: PhysicsWorld, maxLinear: number, maxAngular: number): void {\n world._hknp.HP_World_SetSpeedLimit(world._hkWorld, maxLinear, maxAngular);\n}\n\n/**\n * Returns the world's current maximum linear and angular speed limits.\n * @param world - The physics world.\n * @returns The `maxLinear` and `maxAngular` speed limits.\n */\nexport function getPhysicsVelocityLimits(world: PhysicsWorld): { maxLinear: number; maxAngular: number } {\n const limits = world._hknp.HP_World_GetSpeedLimit(world._hkWorld);\n return { maxLinear: limits[1], maxAngular: limits[2] };\n}\n\n// ─── Body ────────────────────────────────────────────────────────────\n\n/**\n * Creates a rigid body bound to a scene node, adds it to the world, and seeds it with the node's transform.\n * @param world - The physics world.\n * @param node - The scene node the body follows / drives.\n * @param motionType - Whether the body is static, animated (kinematic), or dynamic.\n * @param startsAsleep - When true, the body is added in a sleeping state.\n * @returns The created physics body handle.\n */\nexport function createPhysicsBody(world: PhysicsWorld, node: SceneNode, motionType: PhysicsMotionType, startsAsleep = false): PhysicsBody {\n const { _hknp: hknp, _hkWorld: hkWorld } = world;\n\n const hkBody = hknp.HP_Body_Create()[1];\n\n // Set motion type\n const hkMotion =\n motionType === PhysicsMotionType.STATIC ? hknp.MotionType.STATIC : motionType === PhysicsMotionType.ANIMATED ? hknp.MotionType.KINEMATIC : hknp.MotionType.DYNAMIC;\n hknp.HP_Body_SetMotionType(hkBody, hkMotion);\n\n // Add to world first, then set transform (Havok resets transform on add)\n hknp.HP_World_AddBody(hkWorld, hkBody, startsAsleep);\n\n const p = node.position;\n const q = node.rotationQuaternion;\n hknp.HP_Body_SetQTransform(hkBody, [\n [p.x, p.y, p.z],\n [q.x, q.y, q.z, q.w],\n ]);\n\n const body: PhysicsBody = {\n _hkBody: hkBody,\n node,\n motionType,\n };\n world._bodies.push(body);\n return body;\n}\n\n// ─── Shape ───────────────────────────────────────────────────────────\n\n/**\n * Creates a collision shape (sphere, box, capsule, or cylinder) from the given options.\n * @param world - The physics world.\n * @param options - The shape type and its geometry parameters.\n * @returns The created shape handle.\n */\nexport function createPhysicsShape(world: PhysicsWorld, options: PhysicsShapeOptions): PhysicsShape {\n const { _hknp: hknp } = world;\n const params = options.parameters ?? {};\n\n let hkShape: any;\n switch (options.type) {\n case PhysicsShapeType.SPHERE: {\n const c = params.center ?? { x: 0, y: 0, z: 0 };\n const r = params.radius ?? 0.5;\n hkShape = hknp.HP_Shape_CreateSphere([c.x, c.y, c.z], r)[1];\n break;\n }\n case PhysicsShapeType.BOX: {\n const c = params.center ?? { x: 0, y: 0, z: 0 };\n const q = params.rotation ?? { x: 0, y: 0, z: 0, w: 1 };\n const e = params.extents ?? { x: 1, y: 1, z: 1 };\n hkShape = hknp.HP_Shape_CreateBox([c.x, c.y, c.z], [q.x, q.y, q.z, q.w], [e.x, e.y, e.z])[1];\n break;\n }\n case PhysicsShapeType.CAPSULE: {\n const a = params.pointA ?? { x: 0, y: 0, z: 0 };\n const b = params.pointB ?? { x: 0, y: 1, z: 0 };\n const r = params.radius ?? 0.5;\n hkShape = hknp.HP_Shape_CreateCapsule([a.x, a.y, a.z], [b.x, b.y, b.z], r)[1];\n break;\n }\n case PhysicsShapeType.CYLINDER: {\n const a = params.pointA ?? { x: 0, y: 0, z: 0 };\n const b = params.pointB ?? { x: 0, y: 1, z: 0 };\n const r = params.radius ?? 0.5;\n hkShape = hknp.HP_Shape_CreateCylinder([a.x, a.y, a.z], [b.x, b.y, b.z], r)[1];\n break;\n }\n default:\n throw new Error(`Unsupported shape type: ${options.type}`);\n }\n\n return { _hkShape: hkShape };\n}\n\n// ─── Shape ↔ Body wiring ─────────────────────────────────────────────\n\n/**\n * Assigns a collision shape to a body.\n * @param world - The physics world.\n * @param body - The body to attach the shape to.\n * @param shape - The collision shape.\n */\nexport function setPhysicsBodyShape(world: PhysicsWorld, body: PhysicsBody, shape: PhysicsShape): void {\n world._hknp.HP_Body_SetShape(body._hkBody, shape._hkShape);\n}\n\n/**\n * Sets a shape's surface material properties.\n * @param world - The physics world.\n * @param shape - The collision shape.\n * @param friction - Friction coefficient (used for both static and dynamic friction).\n * @param restitution - Bounciness in `[0, 1]`.\n */\nexport function setPhysicsShapeMaterial(world: PhysicsWorld, shape: PhysicsShape, friction: number, restitution: number): void {\n // Material array: [staticFriction, dynamicFriction, restitution, frictionCombine, restitutionCombine]\n // Combine modes: 0 = GEOMETRIC_MEAN, 1 = MINIMUM, 2 = MAXIMUM\n const material = [friction, friction, restitution, 0, 2];\n world._hknp.HP_Shape_SetMaterial(shape._hkShape, material);\n}\n\n// ─── Mass ────────────────────────────────────────────────────────────\n\n/**\n * Sets a body's mass and a matching diagonal inertia tensor.\n * @param world - The physics world.\n * @param body - The body to update.\n * @param mass - Mass in kilograms.\n */\nexport function setPhysicsBodyMass(world: PhysicsWorld, body: PhysicsBody, mass: number): void {\n // massProperties: [centerOfMass[3], mass, inertia[3], inertiaOrientation[4]]\n const massProps = [[0, 0, 0], mass, [mass, mass, mass], [0, 0, 0, 1]];\n world._hknp.HP_Body_SetMassProperties(body._hkBody, massProps);\n}\n\n// ─── Aggregate (convenience) ─────────────────────────────────────────\n\n/**\n * Create a physics aggregate: body + shape + material wired together.\n * `mass === 0` → STATIC, `mass > 0` → DYNAMIC.\n * Shape geometry is auto-sized from the mesh bounding box when not specified.\n */\nexport function createPhysicsAggregate(world: PhysicsWorld, node: Mesh, type: PhysicsShapeType, options: PhysicsAggregateOptions): PhysicsAggregate {\n const motionType = options.mass === 0 ? PhysicsMotionType.STATIC : PhysicsMotionType.DYNAMIC;\n\n // Build shape parameters, auto-sizing from bounding box if needed\n const shapeParams = _buildShapeParams(node, type, options);\n const shape = createPhysicsShape(world, { type, parameters: shapeParams });\n\n // Set material (friction + restitution)\n const friction = options.friction ?? 0.5;\n const restitution = options.restitution ?? 0.0;\n setPhysicsShapeMaterial(world, shape, friction, restitution);\n\n // Create body\n const body = createPhysicsBody(world, node, motionType, options.startAsleep);\n setPhysicsBodyShape(world, body, shape);\n\n // Set mass for dynamic bodies\n if (options.mass > 0) {\n setPhysicsBodyMass(world, body, options.mass);\n }\n\n return { body, shape };\n}\n\nfunction _buildShapeParams(node: Mesh, type: PhysicsShapeType, options: PhysicsAggregateOptions): PhysicsShapeParameters {\n const params: PhysicsShapeParameters = {};\n\n if (options.center) {\n params.center = options.center;\n }\n if (options.rotation) {\n params.rotation = options.rotation;\n }\n\n switch (type) {\n case PhysicsShapeType.SPHERE: {\n params.radius = options.radius ?? _boundingRadius(node);\n params.center = params.center ?? _boundingCenter(node);\n break;\n }\n case PhysicsShapeType.BOX: {\n params.extents = options.extents ?? _boundingExtents(node);\n params.center = params.center ?? _boundingCenter(node);\n break;\n }\n case PhysicsShapeType.CAPSULE:\n case PhysicsShapeType.CYLINDER: {\n params.radius = options.radius ?? _boundingRadius(node);\n params.pointA = options.pointA ?? { x: 0, y: 0, z: 0 };\n params.pointB = options.pointB ?? { x: 0, y: 1, z: 0 };\n break;\n }\n }\n return params;\n}\n\nfunction _boundingCenter(mesh: Mesh): Vec3 {\n if (mesh.boundMin && mesh.boundMax) {\n return {\n x: (mesh.boundMin[0] + mesh.boundMax[0]) * 0.5,\n y: (mesh.boundMin[1] + mesh.boundMax[1]) * 0.5,\n z: (mesh.boundMin[2] + mesh.boundMax[2]) * 0.5,\n };\n }\n return { x: 0, y: 0, z: 0 };\n}\n\nfunction _boundingExtents(mesh: Mesh): Vec3 {\n if (mesh.boundMin && mesh.boundMax) {\n return {\n x: mesh.boundMax[0] - mesh.boundMin[0],\n y: mesh.boundMax[1] - mesh.boundMin[1],\n z: mesh.boundMax[2] - mesh.boundMin[2],\n };\n }\n return { x: 1, y: 1, z: 1 };\n}\n\nfunction _boundingRadius(mesh: Mesh): number {\n if (mesh.boundMin && mesh.boundMax) {\n const dx = mesh.boundMax[0]! - mesh.boundMin[0]!;\n const dy = mesh.boundMax[1]! - mesh.boundMin[1]!;\n const dz = mesh.boundMax[2]! - mesh.boundMin[2]!;\n return Math.max(dx, dy, dz) * 0.5;\n }\n return 0.5;\n}\n\n// ─── Dispose ─────────────────────────────────────────────────────────\n\n/**\n * Removes and releases all bodies, then releases the native world. Call once when tearing down physics.\n * @param world - The physics world to dispose.\n */\nexport function disposePhysics(world: PhysicsWorld): void {\n const { _hknp: hknp, _hkWorld: hkWorld, _bodies: bodies } = world;\n\n // Remove and release all bodies\n for (let i = bodies.length - 1; i >= 0; i--) {\n const b = bodies[i]!;\n hknp.HP_World_RemoveBody(hkWorld, b._hkBody);\n hknp.HP_Body_Release(b._hkBody);\n }\n bodies.length = 0;\n\n // Release world\n hknp.HP_World_Release(hkWorld);\n}\n","/**\n * Recast Navigation V2 integration for Babylon Lite.\n *\n * Pure-state interfaces + standalone factory functions, matching Lite conventions.\n * The recast wasm is loaded lazily inside `createNavigationPluginAsync` so scenes\n * that do not use navigation pay zero bundle cost.\n *\n * Usage:\n * ```ts\n * const nav = await createNavigationPluginAsync();\n * createNavMesh(nav, [ground, sphere, box], params);\n * const debug = createDebugNavMeshGeometry(nav);\n * const closest = getClosestPoint(nav, { x, y, z });\n * const crowd = createNavCrowd(nav, 10, 0.1);\n * const idx = addAgent(crowd, spawnPos, agentParams);\n * updateNavCrowd(crowd, 1 / 60);\n * ```\n *\n * For obstacles (tile-cache navmesh):\n * ```ts\n * createNavMesh(nav, [...], { ..., maxObstacles: 32, tileSize: 32 });\n * const ref = addBoxObstacle(nav, { x, y, z }, { x: 1, y: 1, z: 1 }, angle);\n * removeObstacle(nav, ref);\n * ```\n *\n * For off-mesh connections:\n * ```ts\n * createNavMesh(nav, [...], { ..., offMeshConnections: [...] });\n * ```\n *\n * For raycast:\n * ```ts\n * const r = raycast(nav, start, end);\n * if (r.hit) console.log(r.hitPoint);\n * ```\n */\n\nimport type { Vec3 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\n\n// ─── Public types ────────────────────────────────────────────────────\n\n/** NavMesh build parameters (Recast solo / tiled / tile-cache navmesh config). */\nexport interface NavMeshParameters {\n cs?: number;\n ch?: number;\n walkableSlopeAngle?: number;\n walkableHeight?: number;\n walkableClimb?: number;\n walkableRadius?: number;\n maxEdgeLen?: number;\n maxSimplificationError?: number;\n minRegionArea?: number;\n mergeRegionArea?: number;\n maxVertsPerPoly?: number;\n detailSampleDist?: number;\n detailSampleMaxError?: number;\n /** Skip reversing winding when extracting positions (right-handed input). */\n doNotReverseIndices?: boolean;\n /** Tile size for tiled / tile-cache navmesh. Recommended 32-64 for tile cache. */\n tileSize?: number;\n /**\n * Maximum number of obstacles. If `> 0` the navmesh is built with a tile cache\n * so obstacles can be added/removed dynamically.\n */\n maxObstacles?: number;\n /** Expected layers per tile for tile-cache navmesh. Default 1. */\n expectedLayersPerTile?: number;\n /** Off-mesh connection segments (teleports) baked into the navmesh. */\n offMeshConnections?: OffMeshConnection[];\n /** Keep intermediates for debug visualization. */\n keepIntermediates?: boolean;\n}\n\n/** Off-mesh connection (teleport segment) baked into the navmesh. */\nexport interface OffMeshConnection {\n startPosition: Vec3;\n endPosition: Vec3;\n radius: number;\n bidirectional: boolean;\n /** @defaultValue 0 */\n area?: number;\n /** @defaultValue 1 */\n flags?: number;\n userId?: number;\n}\n\n/** Crowd agent parameters. */\nexport interface AgentParameters {\n radius: number;\n height: number;\n maxAcceleration: number;\n maxSpeed: number;\n collisionQueryRange: number;\n pathOptimizationRange: number;\n separationWeight: number;\n updateFlags?: number;\n obstacleAvoidanceType?: number;\n queryFilterType?: number;\n reachRadius?: number;\n}\n\n/** A single mesh source for navmesh construction. */\nexport interface NavMeshSource {\n positions: ArrayLike<number>;\n indices: ArrayLike<number>;\n}\n\n/** Pure-state handle for the navigation plugin. */\nexport interface NavigationPlugin {\n /** @internal */ readonly _recast: any;\n /** @internal */ readonly _generators: any;\n /** @internal */ _navMesh?: any;\n /** @internal */ _navMeshQuery?: any;\n /** @internal */ _tileCache?: any;\n}\n\n/** Opaque handle returned by `addBoxObstacle` / `addCylinderObstacle`. */\nexport interface ObstacleHandle {\n /** @internal */ readonly _obstacle: any;\n}\n\n/** Pure-state handle for a crowd. */\nexport interface NavCrowd {\n /** @internal */ readonly _plugin: NavigationPlugin;\n /** @internal */ readonly _crowd: any;\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────\n\nlet _coreModule: any = null;\nlet _generatorsModule: any = null;\nlet _initPromise: Promise<void> | null = null;\n\nasync function _ensureRecast(locateFile?: (url: string) => string): Promise<{ core: any; gens: any }> {\n if (!_coreModule || !_generatorsModule) {\n if (!_initPromise) {\n _initPromise = (async () => {\n const core = await import(\"@recast-navigation/core\");\n const gens = await import(\"@recast-navigation/generators\");\n if (locateFile) {\n const wasmFactory = (await import(\"@recast-navigation/wasm/wasm\")).default;\n // core.init types impl as typeof Recast but calls it as impl() at runtime;\n // bind pre-fills locateFile and cast to satisfy the declaration.\n await core.init(wasmFactory.bind(null, { locateFile }) as typeof wasmFactory);\n } else {\n await core.init();\n }\n _coreModule = core;\n _generatorsModule = gens;\n })();\n }\n await _initPromise;\n }\n return { core: _coreModule, gens: _generatorsModule };\n}\n\n/**\n * Create a navigation plugin. Loads the Recast wasm internally on first call;\n * subsequent calls reuse the loaded module.\n *\n * Pass `locateFile` to serve the wasm from a public path instead of bundling\n * it inline — same pattern as `HavokPhysics({ locateFile: () => \"/HavokPhysics.wasm\" })`.\n *\n * @example\n * ```ts\n * const nav = await createNavigationPluginAsync({ locateFile: () => \"/recast-navigation.wasm\" });\n * ```\n */\nexport async function createNavigationPluginAsync(options?: { locateFile?: (url: string) => string }): Promise<NavigationPlugin> {\n const { core, gens } = await _ensureRecast(options?.locateFile);\n return {\n _recast: core,\n _generators: gens,\n };\n}\n\n// ─── NavMesh ─────────────────────────────────────────────────────────\n\n/**\n * Build a navmesh from one or more meshes. Each mesh's CPU positions are\n * transformed by its worldMatrix (matching BJS GetPositionsAndIndices), merged\n * into a single stream, and index winding is reversed (left-handed convention)\n * unless `doNotReverseIndices` is set.\n *\n * - Solo navmesh by default.\n * - If `maxObstacles > 0`, builds a tile-cache navmesh so obstacles can be\n * added/removed dynamically.\n * - Off-mesh connections can be supplied for either solo or tile-cache.\n */\nexport function createNavMesh(plugin: NavigationPlugin, meshes: Mesh[], params: NavMeshParameters): void {\n const { positions, indices } = _mergeMeshes(meshes, params.doNotReverseIndices === true);\n\n const cfg: Record<string, unknown> = {};\n if (params.cs !== undefined) {\n cfg.cs = params.cs;\n }\n if (params.ch !== undefined) {\n cfg.ch = params.ch;\n }\n if (params.walkableSlopeAngle !== undefined) {\n cfg.walkableSlopeAngle = params.walkableSlopeAngle;\n }\n if (params.walkableHeight !== undefined) {\n cfg.walkableHeight = params.walkableHeight;\n }\n if (params.walkableClimb !== undefined) {\n cfg.walkableClimb = params.walkableClimb;\n }\n if (params.walkableRadius !== undefined) {\n cfg.walkableRadius = params.walkableRadius;\n }\n if (params.maxEdgeLen !== undefined) {\n cfg.maxEdgeLen = params.maxEdgeLen;\n }\n if (params.maxSimplificationError !== undefined) {\n cfg.maxSimplificationError = params.maxSimplificationError;\n }\n if (params.minRegionArea !== undefined) {\n cfg.minRegionArea = params.minRegionArea;\n }\n if (params.mergeRegionArea !== undefined) {\n cfg.mergeRegionArea = params.mergeRegionArea;\n }\n if (params.maxVertsPerPoly !== undefined) {\n cfg.maxVertsPerPoly = params.maxVertsPerPoly;\n }\n if (params.detailSampleDist !== undefined) {\n cfg.detailSampleDist = params.detailSampleDist;\n }\n if (params.detailSampleMaxError !== undefined) {\n cfg.detailSampleMaxError = params.detailSampleMaxError;\n }\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.offMeshConnections = params.offMeshConnections;\n }\n\n const internal = plugin as { _navMesh: any; _navMeshQuery: any; _tileCache?: any };\n const needsTileCache = (params.maxObstacles ?? 0) > 0;\n const needsTiled = (params.tileSize ?? 0) > 0;\n\n if (needsTileCache) {\n // Tile cache config: requires tileSize, expectedLayersPerTile, maxObstacles,\n // and a tile cache mesh process. Mirrors BJS Addons CreateTileCacheNavMeshConfig.\n cfg.tileSize = params.tileSize ?? 32;\n cfg.expectedLayersPerTile = params.expectedLayersPerTile ?? 1;\n cfg.maxObstacles = params.maxObstacles!;\n\n if (params.offMeshConnections !== undefined && params.offMeshConnections.length > 0) {\n cfg.tileCacheMeshProcess = _createDefaultTileCacheMeshProcess(plugin._recast, params.offMeshConnections);\n }\n\n const result = plugin._generators.generateTileCache(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tile cache) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._tileCache = result.tileCache;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n if (needsTiled) {\n cfg.tileSize = params.tileSize;\n const result = plugin._generators.generateTiledNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh (tiled) failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n return;\n }\n\n const result = plugin._generators.generateSoloNavMesh(positions, indices, cfg, params.keepIntermediates === true);\n if (!result.success) {\n throw new Error(`createNavMesh failed: ${result.error}`);\n }\n internal._navMesh = result.navMesh;\n internal._navMeshQuery = new plugin._recast.NavMeshQuery(result.navMesh);\n}\n\n/**\n * Default tile-cache mesh process that copies area/flags from input polys and\n * appends off-mesh connections. Mirrors BJS Addons CreateDefaultTileCacheMeshProcess.\n */\nfunction _createDefaultTileCacheMeshProcess(recast: any, offMeshConnections: OffMeshConnection[]): any {\n const area = 0;\n const flags = 1;\n return new recast.TileCacheMeshProcess((navMeshCreateParams: any, polyAreas: any, polyFlags: any) => {\n for (let i = 0; i < navMeshCreateParams.polyCount(); ++i) {\n polyAreas.set(i, area);\n polyFlags.set(i, flags);\n }\n if (offMeshConnections.length > 0) {\n navMeshCreateParams.setOffMeshConnections(offMeshConnections);\n }\n });\n}\n\nfunction _mergeMeshes(meshes: Mesh[], doNotReverseIndices: boolean): { positions: Float32Array; indices: Uint32Array } {\n let totalVerts = 0;\n let totalIdx = 0;\n for (const mesh of meshes) {\n if (!mesh._cpuPositions || !mesh._cpuIndices) {\n throw new Error(`Mesh \"${mesh.name}\" missing CPU geometry for navmesh`);\n }\n totalVerts += mesh._cpuPositions.length;\n totalIdx += mesh._cpuIndices.length;\n }\n const positions = new Float32Array(totalVerts);\n const indices = new Uint32Array(totalIdx);\n\n let pOff = 0;\n let iOff = 0;\n let vertBase = 0;\n for (const mesh of meshes) {\n const src = mesh._cpuPositions!;\n const wm = mesh.worldMatrix;\n\n for (let i = 0; i < src.length; i += 3) {\n const x = src[i]!,\n y = src[i + 1]!,\n z = src[i + 2]!;\n positions[pOff++] = x * wm[0]! + y * wm[4]! + z * wm[8]! + wm[12]!;\n positions[pOff++] = x * wm[1]! + y * wm[5]! + z * wm[9]! + wm[13]!;\n positions[pOff++] = x * wm[2]! + y * wm[6]! + z * wm[10]! + wm[14]!;\n }\n\n const meshIdx = mesh._cpuIndices!;\n const n = meshIdx.length;\n if (doNotReverseIndices) {\n for (let i = 0; i < n; i++) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n }\n } else {\n for (let i = 0; i < n; i += 3) {\n indices[iOff++] = meshIdx[i]! + vertBase;\n indices[iOff++] = meshIdx[i + 2]! + vertBase;\n indices[iOff++] = meshIdx[i + 1]! + vertBase;\n }\n }\n vertBase += src.length / 3;\n }\n\n return { positions, indices };\n}\n\n// ─── Debug navmesh geometry ──────────────────────────────────────────\n\n/**\n * Extract debug visualization geometry from the generated navmesh.\n * Faces are detached (each triangle gets its own 3 vertices) and per-vertex\n * normals are set to the face normal — yielding flat shading without the need\n * for a separate normal-computation pass in callers.\n * Returns positions, normals, indices, and a hash of the positions for\n * cross-engine parity checks.\n */\nexport function createDebugNavMeshGeometry(plugin: NavigationPlugin): { positions: Float32Array; normals: Float32Array; indices: Uint32Array; positionsHash: number } {\n if (!plugin._navMesh) {\n throw new Error(\"No navmesh generated. Call createNavMesh first.\");\n }\n const [positionsArr, indicesArr] = plugin._recast.getNavMeshPositionsAndIndices(plugin._navMesh);\n const triCount = (indicesArr.length / 3) | 0;\n const vertCount = triCount * 3;\n const positions = new Float32Array(vertCount * 3);\n const normals = new Float32Array(vertCount * 3);\n const indices = new Uint32Array(vertCount);\n\n for (let t = 0; t < triCount; t++) {\n // Recast outputs triangles with original winding such that the face\n // normal computed from (i0,i1,i2) order points UP. We reverse the\n // stored winding to match BJS CreateDebugNavMesh for back-face culling\n // parity (stored as i0,i2,i1) — but compute the face normal from the\n // ORIGINAL winding so it still points UP.\n const i0 = indicesArr[t * 3]! * 3;\n const i1Orig = indicesArr[t * 3 + 1]! * 3;\n const i2Orig = indicesArr[t * 3 + 2]! * 3;\n\n const ax = positionsArr[i0]!,\n ay = positionsArr[i0 + 1]!,\n az = positionsArr[i0 + 2]!;\n const b1x = positionsArr[i1Orig]!,\n b1y = positionsArr[i1Orig + 1]!,\n b1z = positionsArr[i1Orig + 2]!;\n const c1x = positionsArr[i2Orig]!,\n c1y = positionsArr[i2Orig + 1]!,\n c1z = positionsArr[i2Orig + 2]!;\n\n const e1x = b1x - ax,\n e1y = b1y - ay,\n e1z = b1z - az;\n const e2x = c1x - ax,\n e2y = c1y - ay,\n e2z = c1z - az;\n let nx = e1y * e2z - e1z * e2y;\n let ny = e1z * e2x - e1x * e2z;\n let nz = e1x * e2y - e1y * e2x;\n const len = Math.hypot(nx, ny, nz);\n if (len > 0) {\n nx /= len;\n ny /= len;\n nz /= len;\n }\n\n // Store positions in reversed winding (i0, i2, i1) for back-face parity.\n const v = t * 9;\n positions[v] = ax;\n positions[v + 1] = ay;\n positions[v + 2] = az;\n positions[v + 3] = c1x;\n positions[v + 4] = c1y;\n positions[v + 5] = c1z;\n positions[v + 6] = b1x;\n positions[v + 7] = b1y;\n positions[v + 8] = b1z;\n\n normals[v] = nx;\n normals[v + 1] = ny;\n normals[v + 2] = nz;\n normals[v + 3] = nx;\n normals[v + 4] = ny;\n normals[v + 5] = nz;\n normals[v + 6] = nx;\n normals[v + 7] = ny;\n normals[v + 8] = nz;\n\n const idx = t * 3;\n indices[idx] = idx;\n indices[idx + 1] = idx + 1;\n indices[idx + 2] = idx + 2;\n }\n\n let hash = 0x811c9dc5;\n for (let i = 0; i < positions.length; i++) {\n hash ^= Math.round(positions[i]! * 100000);\n hash = Math.imul(hash, 0x01000193);\n }\n\n return { positions, normals, indices, positionsHash: hash };\n}\n\n// ─── Queries ─────────────────────────────────────────────────────────\n\nconst _tmpHalfExtents = { x: 1, y: 1, z: 1 };\n\n/** Snap a position to the closest point on the navmesh. */\nexport function getClosestPoint(plugin: NavigationPlugin, position: Vec3): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findClosestPoint(position, { halfExtents: _tmpHalfExtents });\n return { x: res.point.x, y: res.point.y, z: res.point.z };\n}\n\n/** Compute a path between two world positions, snapped to the navmesh. */\nexport function computePath(plugin: NavigationPlugin, start: Vec3, end: Vec3): Vec3[] {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const startSnap = q.findClosestPoint(start, { halfExtents: _tmpHalfExtents });\n const endSnap = q.findClosestPoint(end, { halfExtents: _tmpHalfExtents });\n const res = q.computePath(startSnap.point, endSnap.point);\n if (!res.success) {\n return [];\n }\n const out: Vec3[] = [];\n for (const p of res.path) {\n out.push({ x: p.x, y: p.y, z: p.z });\n }\n return out;\n}\n\nfunction _assertReady(plugin: NavigationPlugin): void {\n if (!plugin._navMesh || !plugin._navMeshQuery) {\n throw new Error(\"Navmesh not ready. Call createNavMesh first.\");\n }\n}\n\n// ─── Crowd ───────────────────────────────────────────────────────────\n\n/**\n * Create a crowd attached to the navmesh. The crowd is NOT auto-updated;\n * call `updateNavCrowd(crowd, dt)` each frame for full determinism.\n */\nexport function createNavCrowd(plugin: NavigationPlugin, maxAgents: number, maxAgentRadius: number): NavCrowd {\n _assertReady(plugin);\n const Crowd = plugin._recast.Crowd;\n const crowd = new Crowd(plugin._navMesh, { maxAgents, maxAgentRadius });\n return { _plugin: plugin, _crowd: crowd };\n}\n\n/** Add an agent to the crowd. Returns the agent index. */\nexport function addAgent(crowd: NavCrowd, position: Vec3, params: AgentParameters): number {\n const agentParams = {\n radius: params.radius,\n height: params.height,\n maxAcceleration: params.maxAcceleration,\n maxSpeed: params.maxSpeed,\n collisionQueryRange: params.collisionQueryRange,\n pathOptimizationRange: params.pathOptimizationRange,\n separationWeight: params.separationWeight,\n updateFlags: params.updateFlags ?? 7,\n obstacleAvoidanceType: params.obstacleAvoidanceType ?? 0,\n queryFilterType: params.queryFilterType ?? 0,\n userData: 0,\n };\n const agent = crowd._crowd.addAgent({ x: position.x, y: position.y, z: position.z }, agentParams);\n return agent.agentIndex;\n}\n\n/** Get the current world position of an agent. */\nexport function getAgentPosition(crowd: NavCrowd, index: number): Vec3 {\n const p = crowd._crowd.getAgent(index)?.position();\n return p ? { x: p.x, y: p.y, z: p.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Get the current world-space velocity of an agent. */\nexport function getAgentVelocity(crowd: NavCrowd, index: number): Vec3 {\n const v = crowd._crowd.getAgent(index)?.velocity();\n return v ? { x: v.x, y: v.y, z: v.z } : { x: 0, y: 0, z: 0 };\n}\n\n/** Request the agent to move toward a world target (constrained by navmesh). */\nexport function agentGoto(crowd: NavCrowd, index: number, destination: Vec3): void {\n crowd._crowd.getAgent(index)?.requestMoveTarget(destination);\n}\n\n/** Advance the crowd simulation by `dt` seconds. */\nexport function updateNavCrowd(crowd: NavCrowd, dt: number): void {\n crowd._crowd.update(dt);\n}\n\n// ─── Random queries ──────────────────────────────────────────────────\n\n/**\n * Return a random point on the navmesh inside a circle of `radius` around `position`.\n * Determinism: seeded by Recast's internal RNG; call `setNavigationRandomSeed`\n * to make results reproducible across runs.\n */\nexport function findRandomPointAroundCircle(plugin: NavigationPlugin, position: Vec3, radius: number): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPointAroundCircle(position, radius, { halfExtents: _tmpHalfExtents });\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Return any random point on the navmesh. */\nexport function findRandomPoint(plugin: NavigationPlugin): Vec3 {\n _assertReady(plugin);\n const res = plugin._navMeshQuery.findRandomPoint();\n return { x: res.randomPoint.x, y: res.randomPoint.y, z: res.randomPoint.z };\n}\n\n/** Set the seed used by Recast's randomized queries (e.g. `findRandomPointAroundCircle`). */\nexport function setNavigationRandomSeed(plugin: NavigationPlugin, seed: number): void {\n plugin._recast.setRandomSeed(seed);\n}\n\n/** Get the current seed used by Recast's randomized queries. */\nexport function getNavigationRandomSeed(plugin: NavigationPlugin): number {\n return plugin._recast.getRandomSeed();\n}\n\n// ─── Raycast ────────────────────────────────────────────────────────\n\n/**\n * Cast a 'walkability' ray on the navmesh from `start` to `end`.\n * Matches BJS Addons semantics: `hit` is true only when `0 < t < 1` and\n * `hitPoint` is the linear interpolation between start and end at parameter t.\n *\n * Recast's raycast ignores the y component of the end position (2D check).\n */\nexport function raycast(plugin: NavigationPlugin, start: Vec3, end: Vec3): { hit: boolean; hitPoint?: Vec3 } {\n _assertReady(plugin);\n const q = plugin._navMeshQuery;\n const nearest = q.findNearestPoly(start, { halfExtents: _tmpHalfExtents });\n if (!nearest.success || nearest.nearestRef === 0) {\n return { hit: false };\n }\n const r = q.raycast(nearest.nearestRef, start, end);\n const t = r?.t ?? 0;\n if (!(t > 0 && t < 1)) {\n return { hit: false };\n }\n return {\n hit: true,\n hitPoint: {\n x: start.x + (end.x - start.x) * t,\n y: start.y + (end.y - start.y) * t,\n z: start.z + (end.z - start.z) * t,\n },\n };\n}\n\n// ─── Obstacles (tile-cache navmeshes only) ───────────────────────────\n\n/**\n * Add a box obstacle to a tile-cache navmesh. The navmesh must have been\n * built with `maxObstacles > 0`. The tile cache is fully updated before\n * returning (matching BJS Addons default behavior).\n *\n * @param halfExtents - box half-size on each axis\n * @param angle - rotation around the Y axis, in radians\n */\nexport function addBoxObstacle(plugin: NavigationPlugin, position: Vec3, halfExtents: Vec3, angle: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addBoxObstacle(position, halfExtents, angle);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/**\n * Add a cylinder obstacle to a tile-cache navmesh.\n *\n * @param radius - cylinder radius\n * @param height - cylinder height\n */\nexport function addCylinderObstacle(plugin: NavigationPlugin, position: Vec3, radius: number, height: number): ObstacleHandle | null {\n _assertTileCache(plugin);\n const r = plugin._tileCache.addCylinderObstacle(position, radius, height);\n if (!r.success) {\n return null;\n }\n _waitForFullTileCacheUpdate(plugin);\n return { _obstacle: r.obstacle };\n}\n\n/** Remove an obstacle previously added by `addBoxObstacle` / `addCylinderObstacle`. */\nexport function removeObstacle(plugin: NavigationPlugin, obstacle: ObstacleHandle): void {\n _assertTileCache(plugin);\n plugin._tileCache.removeObstacle(obstacle._obstacle);\n _waitForFullTileCacheUpdate(plugin);\n}\n\n/** Run `tileCache.update()` until all pending obstacle requests are resolved. */\nexport function updateNavMeshObstacles(plugin: NavigationPlugin): void {\n _assertTileCache(plugin);\n _waitForFullTileCacheUpdate(plugin);\n}\n\nfunction _waitForFullTileCacheUpdate(plugin: NavigationPlugin): void {\n let upToDate = false;\n while (!upToDate) {\n const r = plugin._tileCache.update(plugin._navMesh);\n upToDate = r.upToDate;\n }\n}\n\nfunction _assertTileCache(plugin: NavigationPlugin): void {\n _assertReady(plugin);\n if (!plugin._tileCache) {\n throw new Error(\"Navmesh has no tile cache. Build with `maxObstacles > 0` to enable obstacles.\");\n }\n}\n"],"names":["_cachedDevice","createUniformBuffer","createShadowTask","texture","DEFAULT_VERTEX_WGSL","applyColorAttachmentState","align4","getPipelineLayout","getShaderModule","getBindGroupLayout","toBytes","alphaModeToBlend","nearestBestKernel","gaussianWeight","wgslFloat","rq","len","createGroundFromHeightMap","p","normalizeVec3","EPSILON","rodrigues","createGroundCPU","transformPoint","transformNormal","requireCpuGeometry","blob","mipLevelCount","generateMipmaps","createStandardNoColorMaterialView","createPbrNoColorMaterialView","source","WGSL","_cache","existing","_meshBGL","shaderModule","_pipeline","createNodeNoColorMaterialView","i","json","binChunk","_a","tex","loadCubeTexture","createPointLight","sub","computeSceneSize","SH_C0","ROW_LENGTH","SplatSortWorker","clamp255","_computeDirectionalLightMatrix","updateShadowCamera","engine","_boneTmp","RH_TO_LH","TRS_STRIDE","T_OFF","R_OFF","S_OFF","computeTopoOrder","DEFAULT_FRAME_RATE","scratchByManager","getScratch","duration","record","deformedGeometry","i0","i1","i2","flip","DEFAULT_CAPACITY","markDirty","growCapacity","writeInstance","bindGroupLayout","MAX_HANDLE_ID","getOrCreateState","ensureIndexCapacity","onRemoveIndex","getState","allocateId","lookupIndex","requireIndex","uploadLayer","assertNoActiveBinding","PhysicsShapeType","PhysicsMotionType","result"],"mappings":"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"}