@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 +1 @@
1
- {"version":3,"file":"cubemap-skybox-material-DvXMVc4k.js","sources":["../src/material/pbr/cubemap-skybox-material.ts"],"sourcesContent":["/** Shared cubemap skybox material factory — used by DDS and HDR skyboxes.\n * BGL: binding 0 = uniform buffer, binding 1 = cube texture, binding 2 = sampler. */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { createDefaultPipelineDescriptor, getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\n\nconst SKYBOX_POS_BUFFER: GPUVertexBufferLayout[] = [{ arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x3\" as GPUVertexFormat }] }];\n\nexport interface CubemapSkyboxMaterial {\n getPipeline(engine: EngineContext, sig: RenderTargetSignature): GPURenderPipeline;\n createBindGroup(engine: EngineContext, meshUBO: GPUBuffer, cubeView: GPUTextureView, cubeSampler: GPUSampler): GPUBindGroup;\n}\n\n/** Module-global pipeline + layout caches shared across all cubemap-skybox instances.\n * Keyed by `${label}|${sigKey}` so HDR and DDS variants don't collide. */\nconst _cmPipelines = new Map<string, GPURenderPipeline>();\nconst _cmLayouts = new Map<string, GPUBindGroupLayout>();\nlet _cmCachedDevice: GPUDevice | null = null;\n\nexport function createCubemapSkyboxMaterial(label: string, vertCode: string, fragCode: string): CubemapSkyboxMaterial {\n function getLayout(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n if (_cmCachedDevice !== device) {\n _cmPipelines.clear();\n _cmLayouts.clear();\n _cmCachedDevice = device;\n }\n const cached = _cmLayouts.get(label);\n if (cached) {\n return cached;\n }\n const layout = device.createBindGroupLayout({\n label: `${label}-material`,\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\", viewDimension: \"cube\" } },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n _cmLayouts.set(label, layout);\n return layout;\n }\n\n return {\n getPipeline(_engine, sig) {\n const device = _engine._device;\n if (_cmCachedDevice !== device) {\n _cmPipelines.clear();\n _cmLayouts.clear();\n _cmCachedDevice = device;\n }\n const key = `${label}|${targetSignatureKey(sig)}`;\n const cached = _cmPipelines.get(key);\n if (cached) {\n return cached;\n }\n const _vertModule = device.createShaderModule({ code: vertCode, label: `${label}-vert` });\n const _fragModule = device.createShaderModule({ code: fragCode, label: `${label}-frag` });\n\n const pipeline = device.createRenderPipeline(\n createDefaultPipelineDescriptor({\n _label: `${label}-pipeline`,\n _engine,\n _bgls: [getSceneBindGroupLayout(_engine), getLayout(_engine)],\n _vertModule,\n _fragModule,\n _vertexBuffers: SKYBOX_POS_BUFFER,\n _format: sig._colorFormat!,\n _depthStencilFormat: sig._depthStencilFormat,\n _depthCompare: sig._depthCompare,\n _msaaSamples: sig._sampleCount,\n _depthWriteEnabled: false,\n _flipY: sig._flipY,\n })\n );\n _cmPipelines.set(key, pipeline);\n return pipeline;\n },\n\n createBindGroup(engine, meshUBO, cubeView, cubeSampler) {\n const device = engine._device;\n return device.createBindGroup({\n layout: getLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: meshUBO } },\n { binding: 1, resource: cubeView },\n { binding: 2, resource: cubeSampler },\n ],\n });\n },\n };\n}\n"],"names":[],"mappings":";AAQA,MAAM,oBAA6C,CAAC,EAAE,aAAa,IAAI,YAAY,CAAC,EAAE,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,YAAA,CAAgC,GAAG;AAS/J,MAAM,mCAAmB,IAAA;AACzB,MAAM,iCAAiB,IAAA;AACvB,IAAI,kBAAoC;AAEjC,SAAS,4BAA4B,OAAe,UAAkB,UAAyC;AAClH,WAAS,UAAU,QAA2C;AAC1D,UAAM,SAAS,OAAO;AACtB,QAAI,oBAAoB,QAAQ;AAC5B,mBAAa,MAAA;AACb,iBAAW,MAAA;AACX,wBAAkB;AAAA,IACtB;AACA,UAAM,SAAS,WAAW,IAAI,KAAK;AACnC,QAAI,QAAQ;AACR,aAAO;AAAA,IACX;AACA,UAAM,SAAS,OAAO,sBAAsB;AAAA,MACxC,OAAO,GAAG,KAAK;AAAA,MACf,SAAS;AAAA,QACL,EAAE,SAAS,GAAG,YAAY,eAAe,SAAS,eAAe,UAAU,QAAQ,EAAE,MAAM,UAAA,EAAU;AAAA,QACrG,EAAE,SAAS,GAAG,YAAY,eAAe,UAAU,SAAS,EAAE,YAAY,SAAS,eAAe,OAAA,EAAO;AAAA,QACzG,EAAE,SAAS,GAAG,YAAY,eAAe,UAAU,SAAS,EAAE,MAAM,YAAA,EAAY;AAAA,MAAE;AAAA,IACtF,CACH;AACD,eAAW,IAAI,OAAO,MAAM;AAC5B,WAAO;AAAA,EACX;AAEA,SAAO;AAAA,IACH,YAAY,SAAS,KAAK;AACtB,YAAM,SAAS,QAAQ;AACvB,UAAI,oBAAoB,QAAQ;AAC5B,qBAAa,MAAA;AACb,mBAAW,MAAA;AACX,0BAAkB;AAAA,MACtB;AACA,YAAM,MAAM,GAAG,KAAK,IAAI,mBAAmB,GAAG,CAAC;AAC/C,YAAM,SAAS,aAAa,IAAI,GAAG;AACnC,UAAI,QAAQ;AACR,eAAO;AAAA,MACX;AACA,YAAM,cAAc,OAAO,mBAAmB,EAAE,MAAM,UAAU,OAAO,GAAG,KAAK,QAAA,CAAS;AACxF,YAAM,cAAc,OAAO,mBAAmB,EAAE,MAAM,UAAU,OAAO,GAAG,KAAK,QAAA,CAAS;AAExF,YAAM,WAAW,OAAO;AAAA,QACpB,gCAAgC;AAAA,UAC5B,QAAQ,GAAG,KAAK;AAAA,UAChB;AAAA,UACA,OAAO,CAAC,wBAAwB,OAAO,GAAG,UAAU,OAAO,CAAC;AAAA,UAC5D;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,IAAI;AAAA,UACb,qBAAqB,IAAI;AAAA,UACzB,eAAe,IAAI;AAAA,UACnB,cAAc,IAAI;AAAA,UAClB,oBAAoB;AAAA,UACpB,QAAQ,IAAI;AAAA,QAAA,CACf;AAAA,MAAA;AAEL,mBAAa,IAAI,KAAK,QAAQ;AAC9B,aAAO;AAAA,IACX;AAAA,IAEA,gBAAgB,QAAQ,SAAS,UAAU,aAAa;AACpD,YAAM,SAAS,OAAO;AACtB,aAAO,OAAO,gBAAgB;AAAA,QAC1B,QAAQ,UAAU,MAAM;AAAA,QACxB,SAAS;AAAA,UACL,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,UAAQ;AAAA,UAC1C,EAAE,SAAS,GAAG,UAAU,SAAA;AAAA,UACxB,EAAE,SAAS,GAAG,UAAU,YAAA;AAAA,QAAY;AAAA,MACxC,CACH;AAAA,IACL;AAAA,EAAA;AAER;"}
1
+ {"version":3,"file":"cubemap-skybox-material-DvW81drX.js","sources":["../src/material/pbr/cubemap-skybox-material.ts"],"sourcesContent":["/** Shared cubemap skybox material factory — used by DDS and HDR skyboxes.\n * BGL: binding 0 = uniform buffer, binding 1 = cube texture, binding 2 = sampler. */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { createDefaultPipelineDescriptor, getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\n\nconst SKYBOX_POS_BUFFER: GPUVertexBufferLayout[] = [{ arrayStride: 12, attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x3\" as GPUVertexFormat }] }];\n\nexport interface CubemapSkyboxMaterial {\n getPipeline(engine: EngineContext, sig: RenderTargetSignature): GPURenderPipeline;\n createBindGroup(engine: EngineContext, meshUBO: GPUBuffer, cubeView: GPUTextureView, cubeSampler: GPUSampler): GPUBindGroup;\n}\n\n/** Module-global pipeline + layout caches shared across all cubemap-skybox instances.\n * Keyed by `${label}|${sigKey}` so HDR and DDS variants don't collide. */\nconst _cmPipelines = new Map<string, GPURenderPipeline>();\nconst _cmLayouts = new Map<string, GPUBindGroupLayout>();\nlet _cmCachedDevice: GPUDevice | null = null;\n\nexport function createCubemapSkyboxMaterial(label: string, vertCode: string, fragCode: string): CubemapSkyboxMaterial {\n function getLayout(engine: EngineContext): GPUBindGroupLayout {\n const device = engine._device;\n if (_cmCachedDevice !== device) {\n _cmPipelines.clear();\n _cmLayouts.clear();\n _cmCachedDevice = device;\n }\n const cached = _cmLayouts.get(label);\n if (cached) {\n return cached;\n }\n const layout = device.createBindGroupLayout({\n label: `${label}-material`,\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: \"float\", viewDimension: \"cube\" } },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n _cmLayouts.set(label, layout);\n return layout;\n }\n\n return {\n getPipeline(_engine, sig) {\n const device = _engine._device;\n if (_cmCachedDevice !== device) {\n _cmPipelines.clear();\n _cmLayouts.clear();\n _cmCachedDevice = device;\n }\n const key = `${label}|${targetSignatureKey(sig)}`;\n const cached = _cmPipelines.get(key);\n if (cached) {\n return cached;\n }\n const _vertModule = device.createShaderModule({ code: vertCode, label: `${label}-vert` });\n const _fragModule = device.createShaderModule({ code: fragCode, label: `${label}-frag` });\n\n const pipeline = device.createRenderPipeline(\n createDefaultPipelineDescriptor({\n _label: `${label}-pipeline`,\n _engine,\n _bgls: [getSceneBindGroupLayout(_engine), getLayout(_engine)],\n _vertModule,\n _fragModule,\n _vertexBuffers: SKYBOX_POS_BUFFER,\n _format: sig._colorFormat!,\n _depthStencilFormat: sig._depthStencilFormat,\n _depthCompare: sig._depthCompare,\n _msaaSamples: sig._sampleCount,\n _depthWriteEnabled: false,\n _flipY: sig._flipY,\n })\n );\n _cmPipelines.set(key, pipeline);\n return pipeline;\n },\n\n createBindGroup(engine, meshUBO, cubeView, cubeSampler) {\n const device = engine._device;\n return device.createBindGroup({\n layout: getLayout(engine),\n entries: [\n { binding: 0, resource: { buffer: meshUBO } },\n { binding: 1, resource: cubeView },\n { binding: 2, resource: cubeSampler },\n ],\n });\n },\n };\n}\n"],"names":[],"mappings":";AAQA,MAAM,oBAA6C,CAAC,EAAE,aAAa,IAAI,YAAY,CAAC,EAAE,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,YAAA,CAAgC,GAAG;AAS/J,MAAM,mCAAmB,IAAA;AACzB,MAAM,iCAAiB,IAAA;AACvB,IAAI,kBAAoC;AAEjC,SAAS,4BAA4B,OAAe,UAAkB,UAAyC;AAClH,WAAS,UAAU,QAA2C;AAC1D,UAAM,SAAS,OAAO;AACtB,QAAI,oBAAoB,QAAQ;AAC5B,mBAAa,MAAA;AACb,iBAAW,MAAA;AACX,wBAAkB;AAAA,IACtB;AACA,UAAM,SAAS,WAAW,IAAI,KAAK;AACnC,QAAI,QAAQ;AACR,aAAO;AAAA,IACX;AACA,UAAM,SAAS,OAAO,sBAAsB;AAAA,MACxC,OAAO,GAAG,KAAK;AAAA,MACf,SAAS;AAAA,QACL,EAAE,SAAS,GAAG,YAAY,eAAe,SAAS,eAAe,UAAU,QAAQ,EAAE,MAAM,UAAA,EAAU;AAAA,QACrG,EAAE,SAAS,GAAG,YAAY,eAAe,UAAU,SAAS,EAAE,YAAY,SAAS,eAAe,OAAA,EAAO;AAAA,QACzG,EAAE,SAAS,GAAG,YAAY,eAAe,UAAU,SAAS,EAAE,MAAM,YAAA,EAAY;AAAA,MAAE;AAAA,IACtF,CACH;AACD,eAAW,IAAI,OAAO,MAAM;AAC5B,WAAO;AAAA,EACX;AAEA,SAAO;AAAA,IACH,YAAY,SAAS,KAAK;AACtB,YAAM,SAAS,QAAQ;AACvB,UAAI,oBAAoB,QAAQ;AAC5B,qBAAa,MAAA;AACb,mBAAW,MAAA;AACX,0BAAkB;AAAA,MACtB;AACA,YAAM,MAAM,GAAG,KAAK,IAAI,mBAAmB,GAAG,CAAC;AAC/C,YAAM,SAAS,aAAa,IAAI,GAAG;AACnC,UAAI,QAAQ;AACR,eAAO;AAAA,MACX;AACA,YAAM,cAAc,OAAO,mBAAmB,EAAE,MAAM,UAAU,OAAO,GAAG,KAAK,QAAA,CAAS;AACxF,YAAM,cAAc,OAAO,mBAAmB,EAAE,MAAM,UAAU,OAAO,GAAG,KAAK,QAAA,CAAS;AAExF,YAAM,WAAW,OAAO;AAAA,QACpB,gCAAgC;AAAA,UAC5B,QAAQ,GAAG,KAAK;AAAA,UAChB;AAAA,UACA,OAAO,CAAC,wBAAwB,OAAO,GAAG,UAAU,OAAO,CAAC;AAAA,UAC5D;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,IAAI;AAAA,UACb,qBAAqB,IAAI;AAAA,UACzB,eAAe,IAAI;AAAA,UACnB,cAAc,IAAI;AAAA,UAClB,oBAAoB;AAAA,UACpB,QAAQ,IAAI;AAAA,QAAA,CACf;AAAA,MAAA;AAEL,mBAAa,IAAI,KAAK,QAAQ;AAC9B,aAAO;AAAA,IACX;AAAA,IAEA,gBAAgB,QAAQ,SAAS,UAAU,aAAa;AACpD,YAAM,SAAS,OAAO;AACtB,aAAO,OAAO,gBAAgB;AAAA,QAC1B,QAAQ,UAAU,MAAM;AAAA,QACxB,SAAS;AAAA,UACL,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,UAAQ;AAAA,UAC1C,EAAE,SAAS,GAAG,UAAU,SAAA;AAAA,UACxB,EAAE,SAAS,GAAG,UAAU,YAAA;AAAA,QAAY;AAAA,MACxC,CACH;AAAA,IACL;AAAA,EAAA;AAER;"}
@@ -1,4 +1,4 @@
1
- import { aS as WGSL } from "./index-C8HOR2sB.js";
1
+ import { aU as WGSL } from "./index-B7Qhw0xL.js";
2
2
  function curveScalar(type, v) {
3
3
  switch (type) {
4
4
  case 0:
@@ -86,4 +86,4 @@ const emitter = {
86
86
  export {
87
87
  emitter
88
88
  };
89
- //# sourceMappingURL=curve-block-BlJpXVYv.js.map
89
+ //# sourceMappingURL=curve-block-Dh_xdUj-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"curve-block-BlJpXVYv.js","sources":["../src/material/node/blocks/curve-block.ts"],"sourcesContent":["import type { BlockEmitter, NodeValueType } from \"../node-types.js\";\nimport { WGSL } from \"../node-types.js\";\n\nfunction curveScalar(type: number, v: string): string {\n switch (type) {\n case 0:\n return `(1.0 - cos((${v} * 3.1415) / 2.0))`;\n case 1:\n return `sin((${v} * 3.1415) / 2.0)`;\n case 2:\n return `(-((cos(${v} * 3.1415) - 1.0)) / 2.0)`;\n case 3:\n return `(${v} * ${v})`;\n case 4:\n return `((1.0 - ${v}) * (1.0 - ${v}))`;\n case 5:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 2.0) / 2.0, 2.0 * ${v} * ${v}, ${v} < 0.5)`;\n case 6:\n return `(${v} * ${v} * ${v})`;\n case 7:\n return `(1.0 - pow(1.0 - ${v}, 3.0))`;\n case 8:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 3.0) / 2.0, 4.0 * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 9:\n return `(${v} * ${v} * ${v} * ${v})`;\n case 10:\n return `(1.0 - pow(1.0 - ${v}, 4.0))`;\n case 11:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 4.0) / 2.0, 8.0 * ${v} * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 12:\n return `(${v} * ${v} * ${v} * ${v} * ${v})`;\n case 13:\n return `(1.0 - pow(1.0 - ${v}, 5.0))`;\n case 14:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 5.0) / 2.0, 16.0 * ${v} * ${v} * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 15:\n return `select(pow(2.0, 10.0 * ${v} - 10.0), 0.0, ${v} == 0.0)`;\n case 16:\n return `select(1.0 - pow(2.0, -10.0 * ${v}), 1.0, ${v} == 1.0)`;\n case 17:\n return `select(select(select((2.0 - pow(2.0, -20.0 * ${v} + 10.0)) / 2.0, pow(2.0, 20.0 * ${v} - 10.0) / 2.0, ${v} < 0.5), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 18:\n return `(1.0 - sqrt(1.0 - pow(${v}, 2.0)))`;\n case 19:\n return `sqrt(1.0 - pow(${v} - 1.0, 2.0))`;\n case 20:\n return `select((sqrt(1.0 - pow(-2.0 * ${v} + 2.0, 2.0)) + 1.0) / 2.0, (1.0 - sqrt(1.0 - pow(2.0 * ${v}, 2.0))) / 2.0, ${v} < 0.5)`;\n case 21:\n return `(2.70158 * ${v} * ${v} * ${v} - 1.70158 * ${v} * ${v})`;\n case 22:\n return `(2.70158 * pow(${v} - 1.0, 3.0) + 1.70158 * pow(${v} - 1.0, 2.0))`;\n case 23:\n return `select((pow(2.0 * ${v} - 2.0, 2.0) * (3.5949095 * (${v} * 2.0 - 2.0) + 3.5949095) + 2.0) / 2.0, (pow(2.0 * ${v}, 2.0) * (3.5949095 * 2.0 * ${v} - 2.5949095)) / 2.0, ${v} < 0.5)`;\n case 24:\n return `select(select(-pow(2.0, 10.0 * ${v} - 10.0) * sin((${v} * 10.0 - 10.75) * ((2.0 * 3.1415) / 3.0)), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 25:\n return `select(select(pow(2.0, -10.0 * ${v}) * sin((${v} * 10.0 - 0.75) * ((2.0 * 3.1415) / 3.0)) + 1.0, 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 26:\n return `select(select(select((pow(2.0, -20.0 * ${v} + 10.0) * sin((20.0 * ${v} - 11.125) * ((2.0 * 3.1415) / 4.5))) / 2.0 + 1.0, -(pow(2.0, 20.0 * ${v} - 10.0) * sin((20.0 * ${v} - 11.125) * ((2.0 * 3.1415) / 4.5))) / 2.0, ${v} < 0.5), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n default:\n throw new Error(`NodeMaterial: unknown CurveBlock curveType ${type}`);\n }\n}\n\nfunction curveExpr(type: number, input: string, inputType: NodeValueType): string {\n if (inputType === \"f32\") {\n return curveScalar(type, input);\n }\n if (inputType === \"vec2f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)})`;\n }\n if (inputType === \"vec3f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)}, ${curveScalar(type, `(${input}).z`)})`;\n }\n if (inputType === \"vec4f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)}, ${curveScalar(type, `(${input}).z`)}, ${curveScalar(type, `(${input}).w`)})`;\n }\n throw new Error(`NodeMaterial: CurveBlock does not support ${inputType}`);\n}\n\nexport const emitter: BlockEmitter = {\n className: \"CurveBlock\",\n emit(block, _outputName, stage, state, ctx) {\n const input = ctx.resolve(block, \"input\", stage, state);\n const rawCurveType = block.serialized.curveType;\n const curveType = typeof rawCurveType === \"number\" ? rawCurveType : 2;\n return { expr: curveExpr(curveType, input.expr, input.type), type: input.type };\n },\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"curve-block-Dh_xdUj-.js","sources":["../src/material/node/blocks/curve-block.ts"],"sourcesContent":["import type { BlockEmitter, NodeValueType } from \"../node-types.js\";\nimport { WGSL } from \"../node-types.js\";\n\nfunction curveScalar(type: number, v: string): string {\n switch (type) {\n case 0:\n return `(1.0 - cos((${v} * 3.1415) / 2.0))`;\n case 1:\n return `sin((${v} * 3.1415) / 2.0)`;\n case 2:\n return `(-((cos(${v} * 3.1415) - 1.0)) / 2.0)`;\n case 3:\n return `(${v} * ${v})`;\n case 4:\n return `((1.0 - ${v}) * (1.0 - ${v}))`;\n case 5:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 2.0) / 2.0, 2.0 * ${v} * ${v}, ${v} < 0.5)`;\n case 6:\n return `(${v} * ${v} * ${v})`;\n case 7:\n return `(1.0 - pow(1.0 - ${v}, 3.0))`;\n case 8:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 3.0) / 2.0, 4.0 * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 9:\n return `(${v} * ${v} * ${v} * ${v})`;\n case 10:\n return `(1.0 - pow(1.0 - ${v}, 4.0))`;\n case 11:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 4.0) / 2.0, 8.0 * ${v} * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 12:\n return `(${v} * ${v} * ${v} * ${v} * ${v})`;\n case 13:\n return `(1.0 - pow(1.0 - ${v}, 5.0))`;\n case 14:\n return `select(1.0 - pow(-2.0 * ${v} + 2.0, 5.0) / 2.0, 16.0 * ${v} * ${v} * ${v} * ${v} * ${v}, ${v} < 0.5)`;\n case 15:\n return `select(pow(2.0, 10.0 * ${v} - 10.0), 0.0, ${v} == 0.0)`;\n case 16:\n return `select(1.0 - pow(2.0, -10.0 * ${v}), 1.0, ${v} == 1.0)`;\n case 17:\n return `select(select(select((2.0 - pow(2.0, -20.0 * ${v} + 10.0)) / 2.0, pow(2.0, 20.0 * ${v} - 10.0) / 2.0, ${v} < 0.5), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 18:\n return `(1.0 - sqrt(1.0 - pow(${v}, 2.0)))`;\n case 19:\n return `sqrt(1.0 - pow(${v} - 1.0, 2.0))`;\n case 20:\n return `select((sqrt(1.0 - pow(-2.0 * ${v} + 2.0, 2.0)) + 1.0) / 2.0, (1.0 - sqrt(1.0 - pow(2.0 * ${v}, 2.0))) / 2.0, ${v} < 0.5)`;\n case 21:\n return `(2.70158 * ${v} * ${v} * ${v} - 1.70158 * ${v} * ${v})`;\n case 22:\n return `(2.70158 * pow(${v} - 1.0, 3.0) + 1.70158 * pow(${v} - 1.0, 2.0))`;\n case 23:\n return `select((pow(2.0 * ${v} - 2.0, 2.0) * (3.5949095 * (${v} * 2.0 - 2.0) + 3.5949095) + 2.0) / 2.0, (pow(2.0 * ${v}, 2.0) * (3.5949095 * 2.0 * ${v} - 2.5949095)) / 2.0, ${v} < 0.5)`;\n case 24:\n return `select(select(-pow(2.0, 10.0 * ${v} - 10.0) * sin((${v} * 10.0 - 10.75) * ((2.0 * 3.1415) / 3.0)), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 25:\n return `select(select(pow(2.0, -10.0 * ${v}) * sin((${v} * 10.0 - 0.75) * ((2.0 * 3.1415) / 3.0)) + 1.0, 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n case 26:\n return `select(select(select((pow(2.0, -20.0 * ${v} + 10.0) * sin((20.0 * ${v} - 11.125) * ((2.0 * 3.1415) / 4.5))) / 2.0 + 1.0, -(pow(2.0, 20.0 * ${v} - 10.0) * sin((20.0 * ${v} - 11.125) * ((2.0 * 3.1415) / 4.5))) / 2.0, ${v} < 0.5), 1.0, ${v} == 1.0), 0.0, ${v} == 0.0)`;\n default:\n throw new Error(`NodeMaterial: unknown CurveBlock curveType ${type}`);\n }\n}\n\nfunction curveExpr(type: number, input: string, inputType: NodeValueType): string {\n if (inputType === \"f32\") {\n return curveScalar(type, input);\n }\n if (inputType === \"vec2f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)})`;\n }\n if (inputType === \"vec3f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)}, ${curveScalar(type, `(${input}).z`)})`;\n }\n if (inputType === \"vec4f\") {\n return `${WGSL[inputType]}(${curveScalar(type, `(${input}).x`)}, ${curveScalar(type, `(${input}).y`)}, ${curveScalar(type, `(${input}).z`)}, ${curveScalar(type, `(${input}).w`)})`;\n }\n throw new Error(`NodeMaterial: CurveBlock does not support ${inputType}`);\n}\n\nexport const emitter: BlockEmitter = {\n className: \"CurveBlock\",\n emit(block, _outputName, stage, state, ctx) {\n const input = ctx.resolve(block, \"input\", stage, state);\n const rawCurveType = block.serialized.curveType;\n const curveType = typeof rawCurveType === \"number\" ? rawCurveType : 2;\n return { expr: curveExpr(curveType, input.expr, input.type), type: input.type };\n },\n};\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { aK as PBR_HAS_EMISSIVE_COLOR, aL as PBR_HAS_EMISSIVE } from "./index-C8HOR2sB.js";
1
+ import { ay as PBR_HAS_EMISSIVE_COLOR, az as PBR_HAS_EMISSIVE } from "./index-B7Qhw0xL.js";
2
2
  function createEmissiveColorFragment(hasEmissiveTexture) {
3
3
  return {
4
4
  _id: "emissive-color",
@@ -36,4 +36,4 @@ export {
36
36
  pbrExt,
37
37
  writeEmissiveUBO
38
38
  };
39
- //# sourceMappingURL=emissive-fragment-BnNvbBCw.js.map
39
+ //# sourceMappingURL=emissive-fragment-DD8cvHyx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"emissive-fragment-BnNvbBCw.js","sources":["../src/material/pbr/fragments/emissive-fragment.ts"],"sourcesContent":["/**\n * Emissive Color Fragment\n *\n * Adds an emissiveColor vec3 uniform to MeshUniforms and uses it\n * in the fragment shader's emissive computation.\n *\n * Zero bytes in bundles for scenes that don't use emissive color.\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_EMISSIVE_COLOR, PBR_HAS_EMISSIVE } from \"../pbr-flag-bits.js\";\n\n/**\n * Create an emissive-color fragment.\n * @param hasEmissiveTexture - Whether the material also has an emissive texture.\n */\nexport function createEmissiveColorFragment(hasEmissiveTexture: boolean): ShaderFragment {\n return {\n _id: \"emissive-color\",\n\n _uboFields: [\n { _name: \"emissiveColor\", _type: \"vec3<f32>\" },\n { _name: \"_emissiveColorPad\", _type: \"f32\" },\n ],\n\n _fragmentSlots: {\n AT: hasEmissiveTexture\n ? `let emissive = material.emissiveColor * textureSample(emissiveTexture, emissiveSampler, input.uv).rgb;`\n : `let emissive = material.emissiveColor;`,\n },\n };\n}\n\n/** Write the emissive-color material-UBO slice. */\nexport function writeEmissiveUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n if (!material.emissiveColor || !offsets.has(\"emissiveColor\")) {\n return;\n }\n const off = offsets.get(\"emissiveColor\")! / 4;\n data[off] = material.emissiveColor[0]!;\n data[off + 1] = material.emissiveColor[1]!;\n data[off + 2] = material.emissiveColor[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"emissive-color\",\n phase: \"fragment\",\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_EMISSIVE_COLOR)) {\n return null;\n }\n return createEmissiveColorFragment((ctx._features & PBR_HAS_EMISSIVE) !== 0);\n },\n writeUbo: writeEmissiveUBO as PbrExt[\"writeUbo\"],\n};\n"],"names":[],"mappings":";AAkBO,SAAS,4BAA4B,oBAA6C;AACrF,SAAO;AAAA,IACH,KAAK;AAAA,IAEL,YAAY;AAAA,MACR,EAAE,OAAO,iBAAiB,OAAO,YAAA;AAAA,MACjC,EAAE,OAAO,qBAAqB,OAAO,MAAA;AAAA,IAAM;AAAA,IAG/C,gBAAgB;AAAA,MACZ,IAAI,qBACE,2GACA;AAAA,IAAA;AAAA,EACV;AAER;AAGO,SAAS,iBAAiB,MAAoB,UAA4B,SAA4C;AACzH,MAAI,CAAC,SAAS,iBAAiB,CAAC,QAAQ,IAAI,eAAe,GAAG;AAC1D;AAAA,EACJ;AACA,QAAM,MAAM,QAAQ,IAAI,eAAe,IAAK;AAC5C,OAAK,GAAG,IAAI,SAAS,cAAc,CAAC;AACpC,OAAK,MAAM,CAAC,IAAI,SAAS,cAAc,CAAC;AACxC,OAAK,MAAM,CAAC,IAAI,SAAS,cAAc,CAAC;AAC5C;AAEO,MAAM,SAAiB;AAAA,EAC1B,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,KAAK,KAAK;AACN,QAAI,EAAE,IAAI,YAAY,yBAAyB;AAC3C,aAAO;AAAA,IACX;AACA,WAAO,6BAA6B,IAAI,YAAY,sBAAsB,CAAC;AAAA,EAC/E;AAAA,EACA,UAAU;AACd;"}
1
+ {"version":3,"file":"emissive-fragment-DD8cvHyx.js","sources":["../src/material/pbr/fragments/emissive-fragment.ts"],"sourcesContent":["/**\n * Emissive Color Fragment\n *\n * Adds an emissiveColor vec3 uniform to MeshUniforms and uses it\n * in the fragment shader's emissive computation.\n *\n * Zero bytes in bundles for scenes that don't use emissive color.\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_EMISSIVE_COLOR, PBR_HAS_EMISSIVE } from \"../pbr-flag-bits.js\";\n\n/**\n * Create an emissive-color fragment.\n * @param hasEmissiveTexture - Whether the material also has an emissive texture.\n */\nexport function createEmissiveColorFragment(hasEmissiveTexture: boolean): ShaderFragment {\n return {\n _id: \"emissive-color\",\n\n _uboFields: [\n { _name: \"emissiveColor\", _type: \"vec3<f32>\" },\n { _name: \"_emissiveColorPad\", _type: \"f32\" },\n ],\n\n _fragmentSlots: {\n AT: hasEmissiveTexture\n ? `let emissive = material.emissiveColor * textureSample(emissiveTexture, emissiveSampler, input.uv).rgb;`\n : `let emissive = material.emissiveColor;`,\n },\n };\n}\n\n/** Write the emissive-color material-UBO slice. */\nexport function writeEmissiveUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n if (!material.emissiveColor || !offsets.has(\"emissiveColor\")) {\n return;\n }\n const off = offsets.get(\"emissiveColor\")! / 4;\n data[off] = material.emissiveColor[0]!;\n data[off + 1] = material.emissiveColor[1]!;\n data[off + 2] = material.emissiveColor[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"emissive-color\",\n phase: \"fragment\",\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_EMISSIVE_COLOR)) {\n return null;\n }\n return createEmissiveColorFragment((ctx._features & PBR_HAS_EMISSIVE) !== 0);\n },\n writeUbo: writeEmissiveUBO as PbrExt[\"writeUbo\"],\n};\n"],"names":[],"mappings":";AAkBO,SAAS,4BAA4B,oBAA6C;AACrF,SAAO;AAAA,IACH,KAAK;AAAA,IAEL,YAAY;AAAA,MACR,EAAE,OAAO,iBAAiB,OAAO,YAAA;AAAA,MACjC,EAAE,OAAO,qBAAqB,OAAO,MAAA;AAAA,IAAM;AAAA,IAG/C,gBAAgB;AAAA,MACZ,IAAI,qBACE,2GACA;AAAA,IAAA;AAAA,EACV;AAER;AAGO,SAAS,iBAAiB,MAAoB,UAA4B,SAA4C;AACzH,MAAI,CAAC,SAAS,iBAAiB,CAAC,QAAQ,IAAI,eAAe,GAAG;AAC1D;AAAA,EACJ;AACA,QAAM,MAAM,QAAQ,IAAI,eAAe,IAAK;AAC5C,OAAK,GAAG,IAAI,SAAS,cAAc,CAAC;AACpC,OAAK,MAAM,CAAC,IAAI,SAAS,cAAc,CAAC;AACxC,OAAK,MAAM,CAAC,IAAI,SAAS,cAAc,CAAC;AAC5C;AAEO,MAAM,SAAiB;AAAA,EAC1B,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,KAAK,KAAK;AACN,QAAI,EAAE,IAAI,YAAY,yBAAyB;AAC3C,aAAO;AAAA,IACX;AACA,WAAO,6BAA6B,IAAI,YAAY,sBAAsB,CAAC;AAAA,EAC/E;AAAA,EACA,UAAU;AACd;"}
@@ -1,4 +1,4 @@
1
- import { Q as createMaterialView, U as PBR2_ESM_SHADOW_OUTPUT, V as PBR_HAS_ALPHA_BLEND } from "./index-C8HOR2sB.js";
1
+ import { A as createMaterialView, P as PBR2_ESM_SHADOW_OUTPUT, C as PBR_HAS_ALPHA_BLEND } from "./index-B7Qhw0xL.js";
2
2
  const PBR_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;
3
3
  let depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);
4
4
  return vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;
@@ -15,4 +15,4 @@ function createPbrEsmShadowMaterialView(source, shadowParamsUBO) {
15
15
  export {
16
16
  createPbrEsmShadowMaterialView
17
17
  };
18
- //# sourceMappingURL=esm-shadow-view-DGKdF1NI.js.map
18
+ //# sourceMappingURL=esm-shadow-view-15S4JK6p.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"esm-shadow-view-DGKdF1NI.js","sources":["../src/material/pbr/esm-shadow-view.ts"],"sourcesContent":["/** PBR material view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { PBR_HAS_ALPHA_BLEND, PBR2_ESM_SHADOW_OUTPUT } from \"./pbr-flags.js\";\nimport type { PbrMaterialProps } from \"./pbr-material.js\";\n\nexport interface PbrEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst PBR_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createPbrEsmShadowMaterialView(source: PbrMaterialProps, shadowParamsUBO: GPUBuffer): PbrEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0, features2: 0 };\n const view = createMaterialView(source, {\n features: features.features & ~PBR_HAS_ALPHA_BLEND,\n features2: (features.features2 ?? 0) | PBR2_ESM_SHADOW_OUTPUT,\n }) as PbrEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: PBR_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,4BAA4B;AAAA;AAAA;AAI3B,SAAS,+BAA+B,QAA0B,iBAAsD;AAC3H,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,GAAG,WAAW,EAAA;AACrE,QAAM,OAAO,mBAAmB,QAAQ;AAAA,IACpC,UAAU,SAAS,WAAW,CAAC;AAAA,IAC/B,YAAY,SAAS,aAAa,KAAK;AAAA,EAAA,CAC1C;AACD,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,2BAA2B,YAAY,OAAO;AAC1G,SAAO;AACX;"}
1
+ {"version":3,"file":"esm-shadow-view-15S4JK6p.js","sources":["../src/material/pbr/esm-shadow-view.ts"],"sourcesContent":["/** PBR material view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { PBR_HAS_ALPHA_BLEND, PBR2_ESM_SHADOW_OUTPUT } from \"./pbr-flags.js\";\nimport type { PbrMaterialProps } from \"./pbr-material.js\";\n\nexport interface PbrEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst PBR_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createPbrEsmShadowMaterialView(source: PbrMaterialProps, shadowParamsUBO: GPUBuffer): PbrEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0, features2: 0 };\n const view = createMaterialView(source, {\n features: features.features & ~PBR_HAS_ALPHA_BLEND,\n features2: (features.features2 ?? 0) | PBR2_ESM_SHADOW_OUTPUT,\n }) as PbrEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: PBR_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,4BAA4B;AAAA;AAAA;AAI3B,SAAS,+BAA+B,QAA0B,iBAAsD;AAC3H,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,GAAG,WAAW,EAAA;AACrE,QAAM,OAAO,mBAAmB,QAAQ;AAAA,IACpC,UAAU,SAAS,WAAW,CAAC;AAAA,IAC/B,YAAY,SAAS,aAAa,KAAK;AAAA,EAAA,CAC1C;AACD,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,2BAA2B,YAAY,OAAO;AAC1G,SAAO;AACX;"}
@@ -1,4 +1,4 @@
1
- import { Q as createMaterialView, R as ESM_SHADOW_OUTPUT, S as MATERIAL_ALPHA_BLEND } from "./index-C8HOR2sB.js";
1
+ import { A as createMaterialView, E as ESM_SHADOW_OUTPUT, B as MATERIAL_ALPHA_BLEND } from "./index-B7Qhw0xL.js";
2
2
  const STANDARD_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;
3
3
  let depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);
4
4
  return vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;
@@ -12,4 +12,4 @@ function createStandardEsmShadowMaterialView(source, shadowParamsUBO) {
12
12
  export {
13
13
  createStandardEsmShadowMaterialView
14
14
  };
15
- //# sourceMappingURL=esm-shadow-view-Dk9NFtLq.js.map
15
+ //# sourceMappingURL=esm-shadow-view-DHVS9r7H.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"esm-shadow-view-Dk9NFtLq.js","sources":["../src/material/standard/esm-shadow-view.ts"],"sourcesContent":["/** Standard material view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { ESM_SHADOW_OUTPUT, MATERIAL_ALPHA_BLEND } from \"./standard-flags.js\";\nimport type { StandardMaterialProps } from \"./standard-material.js\";\n\nexport interface StandardEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst STANDARD_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createStandardEsmShadowMaterialView(source: StandardMaterialProps, shadowParamsUBO: GPUBuffer): StandardEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n const view = createMaterialView(source, { features: (features.features & ~MATERIAL_ALPHA_BLEND) | ESM_SHADOW_OUTPUT }) as StandardEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: STANDARD_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,iCAAiC;AAAA;AAAA;AAIhC,SAAS,oCAAoC,QAA+B,iBAA2D;AAC1I,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,EAAA;AACvD,QAAM,OAAO,mBAAmB,QAAQ,EAAE,UAAW,SAAS,WAAW,CAAC,uBAAwB,mBAAmB;AACrH,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,gCAAgC,YAAY,OAAO;AAC/G,SAAO;AACX;"}
1
+ {"version":3,"file":"esm-shadow-view-DHVS9r7H.js","sources":["../src/material/standard/esm-shadow-view.ts"],"sourcesContent":["/** Standard material view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { ESM_SHADOW_OUTPUT, MATERIAL_ALPHA_BLEND } from \"./standard-flags.js\";\nimport type { StandardMaterialProps } from \"./standard-material.js\";\n\nexport interface StandardEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst STANDARD_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (input.clipPos.z + shadowParams.depthValues.x) / shadowParams.depthValues.y + shadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, shadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createStandardEsmShadowMaterialView(source: StandardMaterialProps, shadowParamsUBO: GPUBuffer): StandardEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n const view = createMaterialView(source, { features: (features.features & ~MATERIAL_ALPHA_BLEND) | ESM_SHADOW_OUTPUT }) as StandardEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: STANDARD_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,iCAAiC;AAAA;AAAA;AAIhC,SAAS,oCAAoC,QAA+B,iBAA2D;AAC1I,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,EAAA;AACvD,QAAM,OAAO,mBAAmB,QAAQ,EAAE,UAAW,SAAS,WAAW,CAAC,uBAAwB,mBAAmB;AACrH,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,gCAAgC,YAAY,OAAO;AAC/G,SAAO;AACX;"}
@@ -1,4 +1,4 @@
1
- import { Q as createMaterialView, N as NODE_ESM_SHADOW_OUTPUT } from "./index-C8HOR2sB.js";
1
+ import { A as createMaterialView, N as NODE_ESM_SHADOW_OUTPUT } from "./index-B7Qhw0xL.js";
2
2
  const NODE_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (in.position.z + nmeShadowParams.depthValues.x) / nmeShadowParams.depthValues.y + nmeShadowParams.biasAndScale.x;
3
3
  let depthSM = clamp(exp(-min(87.0, nmeShadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);
4
4
  return vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;
@@ -12,4 +12,4 @@ function createNodeEsmShadowMaterialView(source, shadowParamsUBO) {
12
12
  export {
13
13
  createNodeEsmShadowMaterialView
14
14
  };
15
- //# sourceMappingURL=esm-shadow-view-DN9HIaM4.js.map
15
+ //# sourceMappingURL=esm-shadow-view-DYAc62Kl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"esm-shadow-view-DN9HIaM4.js","sources":["../src/material/node/esm-shadow-view.ts"],"sourcesContent":["/** NodeMaterial view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { NODE_ESM_SHADOW_OUTPUT } from \"./node-flags.js\";\nimport type { NodeMaterial } from \"./node-material.js\";\n\nexport interface NodeEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst NODE_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (in.position.z + nmeShadowParams.depthValues.x) / nmeShadowParams.depthValues.y + nmeShadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, nmeShadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createNodeEsmShadowMaterialView(source: NodeMaterial, shadowParamsUBO: GPUBuffer): NodeEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n const view = createMaterialView(source, { features: features.features | NODE_ESM_SHADOW_OUTPUT }) as NodeEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: NODE_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,6BAA6B;AAAA;AAAA;AAI5B,SAAS,gCAAgC,QAAsB,iBAAuD;AACzH,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,EAAA;AACvD,QAAM,OAAO,mBAAmB,QAAQ,EAAE,UAAU,SAAS,WAAW,wBAAwB;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,4BAA4B,YAAY,OAAO;AAC3G,SAAO;AACX;"}
1
+ {"version":3,"file":"esm-shadow-view-DYAc62Kl.js","sources":["../src/material/node/esm-shadow-view.ts"],"sourcesContent":["/** NodeMaterial view helper that writes ESM shadow color. */\n\nimport { createMaterialView } from \"../material-view.js\";\nimport type { MaterialView } from \"../material.js\";\nimport { NODE_ESM_SHADOW_OUTPUT } from \"./node-flags.js\";\nimport type { NodeMaterial } from \"./node-material.js\";\n\nexport interface NodeEsmShadowMaterialView extends MaterialView {\n /** @internal */\n readonly _esmShadowParamsUBO: GPUBuffer;\n /** @internal */\n readonly _esmShadowDepthCode: string;\n}\n\nconst NODE_ESM_SHADOW_DEPTH_CODE = `let depthMetricSM = (in.position.z + nmeShadowParams.depthValues.x) / nmeShadowParams.depthValues.y + nmeShadowParams.biasAndScale.x;\nlet depthSM = clamp(exp(-min(87.0, nmeShadowParams.biasAndScale.z * depthMetricSM)), 0.0, 1.0);\nreturn vec4<f32>(depthSM, 1.0, 1.0, 1.0);`;\n\nexport function createNodeEsmShadowMaterialView(source: NodeMaterial, shadowParamsUBO: GPUBuffer): NodeEsmShadowMaterialView {\n const features = source._renderFeatures ?? { features: 0 };\n const view = createMaterialView(source, { features: features.features | NODE_ESM_SHADOW_OUTPUT }) as NodeEsmShadowMaterialView;\n Object.defineProperty(view, \"_esmShadowParamsUBO\", { value: shadowParamsUBO, enumerable: false });\n Object.defineProperty(view, \"_esmShadowDepthCode\", { value: NODE_ESM_SHADOW_DEPTH_CODE, enumerable: false });\n return view;\n}\n"],"names":[],"mappings":";AAcA,MAAM,6BAA6B;AAAA;AAAA;AAI5B,SAAS,gCAAgC,QAAsB,iBAAuD;AACzH,QAAM,WAAW,OAAO,mBAAmB,EAAE,UAAU,EAAA;AACvD,QAAM,OAAO,mBAAmB,QAAQ,EAAE,UAAU,SAAS,WAAW,wBAAwB;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,iBAAiB,YAAY,OAAO;AAChG,SAAO,eAAe,MAAM,uBAAuB,EAAE,OAAO,4BAA4B,YAAY,OAAO;AAC3G,SAAO;AACX;"}
@@ -1,4 +1,4 @@
1
- import { G as disposeGaussianSplattingMesh, H as applyGsFragments, D as targetSignatureKey, F as getSceneBindGroupLayout, J as getRenderTargetSize, K as getViewMatrix, L as getProjectionMatrix, O as getCameraPosition } from "./index-C8HOR2sB.js";
1
+ import { q as disposeGaussianSplattingMesh, s as applyGsFragments, t as targetSignatureKey, j as getSceneBindGroupLayout, v as getRenderTargetSize, x as getViewMatrix, y as getProjectionMatrix, z as getCameraPosition } from "./index-B7Qhw0xL.js";
2
2
  const SH_TEXTURE_COUNT = [0, 1, 2, 3, 5];
3
3
  let _cache = null;
4
4
  function buildShShaderSource(shDegree) {
@@ -497,4 +497,4 @@ export {
497
497
  attachGaussianSplattingMeshSH,
498
498
  buildGaussianSplattingRenderableSH
499
499
  };
500
- //# sourceMappingURL=gaussian-splatting-pipeline-sh-DgJl7l56.js.map
500
+ //# sourceMappingURL=gaussian-splatting-pipeline-sh-BvkUhA9V.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gaussian-splatting-pipeline-sh-DgJl7l56.js","sources":["../src/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.ts"],"sourcesContent":["/** Gaussian-Splatting SH render pipeline + Renderable.\n *\n * Variant of `gaussian-splatting-pipeline.ts` that adds view-dependent SH\n * shading. Loaded *only* by `loadSplat` (and the SOG / SPZ loaders) via a\n * dynamic `import(...)` when the parsed splat asset includes SH coefficients\n * (`mesh.shDegree > 0`), so plain `.ply` / `.splat` scenes (e.g. scene 120)\n * never pull this module's WGSL or runtime cost into their bundle.\n *\n * WGSL source is generated per-shDegree by `buildShShaderSource`: SH textures,\n * byte-to-vec3 unpacking, and the polynomial evaluation in\n * `computeColorFromSHDegree` all expand to the right size — mirrors the\n * `#if SH_DEGREE > N` blocks in BJS `gaussianSplatting.fx`. Pipeline cache is\n * keyed by `(targetSignatureKey, shDegree)`.\n *\n * The UBO grows by 16 bytes vs the base pipeline to carry `eyePosition`\n * (world-space camera position; see `computeSH(dir)` below).\n *\n * ── Why the Y-flip on the SH direction? ─────────────────────────────────\n * BJS sets `mesh.scaling.y *= -1` to fix coordinate-system handedness; Lite\n * pre-flips Y in `splat-data.ts` at parse time so the runtime mesh transform\n * is identity. World-space splat positions agree across both engines, but\n * the BJS world rotation absorbs an extra `diag(1,-1,1)` factor — i.e.\n * worldRot_bjs = worldRot_user · diag(1,-1,1)\n * which means\n * inverse(worldRot_bjs) · v = diag(1,-1,1) · inverse(worldRot_user) · v\n * so Lite reproduces the BJS SH direction by computing\n * `inverseMat3(worldRot) · (worldPos − eye)` and then negating `.y`. */\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 { applyGsFragments } from \"./gaussian-splatting-pipeline.js\";\n\ninterface PipelineEntry {\n pipeline: GPURenderPipeline;\n meshBindGroupLayout: GPUBindGroupLayout;\n shTextureCount: number;\n}\n\n// shDegree → number of rgba32uint SH textures: 1→1, 2→2, 3→3, 4→5.\nconst SH_TEXTURE_COUNT = [0, 1, 2, 3, 5];\n\nlet _cache: { device: GPUDevice; modules: Map<string, GPUShaderModule>; entries: Map<string, PipelineEntry> } | null = null;\n\n/** Build the WGSL source for a given SH degree (1..4). Mirrors the BJS\n * preprocessor-driven shader structure: declares only the SH textures used\n * by the degree, emits exactly the byte-stream unpacking for that degree,\n * and inlines only the SH polynomial terms up to that degree. */\nfunction buildShShaderSource(shDegree: number): string {\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\n const shCoefficientCount = shVectorCount * 3;\n const textureCount = Math.ceil(shCoefficientCount / 16);\n\n // ── SH texture bindings (6, 7, …) ───────────────────────────────\n let textureBindings = \"\";\n for (let i = 0; i < textureCount; i++) {\n textureBindings += `@group(1) @binding(${6 + i}) var shTexture${i}: texture_2d<u32>;\\n`;\n }\n\n // ── textureLoad calls inside readSplat ──────────────────────────\n let textureLoads = \"\";\n for (let i = 0; i < textureCount; i++) {\n textureLoads += ` let sh${i}_u32 = textureLoad(shTexture${i}, splatUVi32, 0);\\n`;\n }\n\n // ── Unpack the byte stream into sh[1..shVectorCount] vec3 values.\n //\n // Each rgba32uint texel carries 16 bytes (4 u32s × 4 bytes). The bytes\n // are stored in BJS-coefficient order: byte j of splat i is the j-th\n // component of the [R0,G0,B0, R1,G1,B1, …, R(N-1),G(N-1),B(N-1)] sequence.\n // sh[k+1] (k = 0..shVectorCount-1) reads bytes [3k, 3k+1, 3k+2]. `decompose`\n // returns `(byte * 2/255) - 1`, matching BJS exactly.\n let shUnpack = ` var sh: array<vec3<f32>, ${shVectorCount + 1}>;\\n sh[0] = vec3<f32>(0.0);\\n`;\n const byteRef = (j: number): string => {\n // texture index, u32 index within texel (0..3), byte index within u32 (0..3 == x/y/z/w).\n const tex = (j / 16) | 0;\n const u32Idx = ((j % 16) / 4) | 0;\n const byteIdx = j % 4;\n const u32Field = [\"x\", \"y\", \"z\", \"w\"][u32Idx]!;\n const byteField = [\"x\", \"y\", \"z\", \"w\"][byteIdx]!;\n return `decompose(sh${tex}_u32.${u32Field}).${byteField}`;\n };\n for (let k = 0; k < shVectorCount; k++) {\n const j = k * 3;\n shUnpack += ` sh[${k + 1}] = vec3<f32>(${byteRef(j)}, ${byteRef(j + 1)}, ${byteRef(j + 2)});\\n`;\n }\n\n // ── Polynomial evaluation, conditional on shDegree ──────────────\n let shPoly = \" result = sh[0];\\n\";\n if (shDegree >= 1) {\n shPoly += ` result += -SH_C1 * y * sh[1] + SH_C1 * z * sh[2] - SH_C1 * x * sh[3];\\n`;\n }\n if (shDegree >= 2) {\n shPoly += ` result +=\\n SH_C2[0] * xy * sh[4] +\\n SH_C2[1] * yz * sh[5] +\\n SH_C2[2] * (2.0 * zz - xx - yy) * sh[6] +\\n SH_C2[3] * xz * sh[7] +\\n SH_C2[4] * (xx - yy) * sh[8];\\n`;\n }\n if (shDegree >= 3) {\n shPoly += ` result +=\\n SH_C3[0] * y * (3.0 * xx - yy) * sh[9] +\\n SH_C3[1] * xy * z * sh[10] +\\n SH_C3[2] * y * (4.0 * zz - xx - yy) * sh[11] +\\n SH_C3[3] * z * (2.0 * zz - 3.0 * xx - 3.0 * yy) * sh[12] +\\n SH_C3[4] * x * (4.0 * zz - xx - yy) * sh[13] +\\n SH_C3[5] * z * (xx - yy) * sh[14] +\\n SH_C3[6] * x * (xx - 3.0 * yy) * sh[15];\\n`;\n }\n if (shDegree >= 4) {\n shPoly += ` result +=\\n SH_C4[0] * x * y * (xx - yy) * sh[16] +\\n SH_C4[1] * y * z * (3.0 * xx - yy) * sh[17] +\\n SH_C4[2] * x * y * (7.0 * zz - 1.0) * sh[18] +\\n SH_C4[3] * y * z * (7.0 * zz - 3.0) * sh[19] +\\n SH_C4[4] * (zz * (35.0 * zz - 30.0) + 3.0) * sh[20] +\\n SH_C4[5] * x * z * (7.0 * zz - 3.0) * sh[21] +\\n SH_C4[6] * (xx - yy) * (7.0 * zz - 1.0) * sh[22] +\\n SH_C4[7] * x * z * (xx - 3.0 * yy) * sh[23] +\\n SH_C4[8] * (xx * (xx - 3.0 * yy) - yy * (3.0 * xx - yy)) * sh[24];\\n`;\n }\n\n // SH_C2..SH_C4 constants — only declare what's referenced (silences\n // WGSL \"unused array\" warnings on lower degrees).\n let constantsBlock = `const SH_C1: f32 = 0.48860251;\\n`;\n if (shDegree >= 2) {\n constantsBlock += `const SH_C2: array<f32, 5> = array<f32, 5>(1.092548430, -1.09254843, 0.315391565, -1.09254843, 0.546274215);\\n`;\n }\n if (shDegree >= 3) {\n constantsBlock += `const SH_C3: array<f32, 7> = array<f32, 7>(-0.59004358, 2.890611442, -0.45704579, 0.373176332, -0.45704579, 1.445305721, -0.59004358);\\n`;\n }\n if (shDegree >= 4) {\n constantsBlock += `const SH_C4: array<f32, 9> = array<f32, 9>(2.5033429418, -1.7701307698, 0.9461746958, -0.6690465436, 0.1057855469, -0.6690465436, 0.4730873479, -1.7701307698, 0.6258357354);\\n`;\n }\n\n return `// Gaussian Splatting — vertex + fragment WGSL (SH degree ${shDegree}).\n// Generated by buildShShaderSource. Mirrors BJS gaussianSplatting.vertex.fx +\n// gaussianSplatting.fx (SH_DEGREE = ${shDegree}, no compound parts).\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 _pad0: f32,\n eyePosition: vec3<f32>,\n _pad1: 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${textureBindings}\n\nstruct VOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) vColor: vec4<f32>,\n @location(1) vPos: vec2<f32>,\n};\n\n${constantsBlock}\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\nfn dataUvI(idx: f32) -> vec2<i32> {\n let y = floor(idx / u.dataSize.x);\n let x = idx - y * u.dataSize.x;\n return vec2<i32>(i32(x), i32(y));\n}\n\n// Unpack a u32 of 4 packed bytes into (b0 b1 b2 b3) * 2/255 - 1.\nfn decompose(value: u32) -> vec4<f32> {\n let v = vec4<f32>(\n f32((value >> 0u) & 255u),\n f32((value >> 8u) & 255u),\n f32((value >> 16u) & 255u),\n f32((value >> 24u) & 255u));\n return v * vec4<f32>(2.0 / 255.0) - vec4<f32>(1.0);\n}\n\nfn inverseMat3(m: mat3x3<f32>) -> mat3x3<f32> {\n let a00 = m[0][0]; let a01 = m[0][1]; let a02 = m[0][2];\n let a10 = m[1][0]; let a11 = m[1][1]; let a12 = m[1][2];\n let a20 = m[2][0]; let a21 = m[2][1]; let a22 = m[2][2];\n let b01 = a22 * a11 - a12 * a21;\n let b11 = -a22 * a10 + a12 * a20;\n let b21 = a21 * a10 - a11 * a20;\n let det = a00 * b01 + a01 * b11 + a02 * b21;\n return mat3x3<f32>(\n vec3<f32>(b01 / det, (-a22 * a01 + a02 * a21) / det, (a12 * a01 - a02 * a11) / det),\n vec3<f32>(b11 / det, (a22 * a00 - a02 * a20) / det, (-a12 * a00 + a02 * a10) / det),\n vec3<f32>(b21 / det, (-a21 * a00 + a01 * a20) / det, (a11 * a00 - a01 * a10) / det));\n}\n\nfn computeSH(dir: vec3<f32>, splatUVi32: vec2<i32>) -> vec3<f32> {\n${textureLoads}${shUnpack} let x = dir.x;\n let y = dir.y;\n let z = dir.z;\n let xx = x * x; let yy = y * y; let zz = z * z;\n let xy = x * y; let yz = y * z; let xz = x * z;\n var result: vec3<f32>;\n${shPoly} return result;\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 splatUVi32 = dataUvI(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 // ── View-dependent SH evaluation ───────────────────────────────────\n let worldRot = mat3x3<f32>(u.world[0].xyz, u.world[1].xyz, u.world[2].xyz);\n let normWorldRot = inverseMat3(worldRot);\n var dir = normalize(normWorldRot * (worldPos.xyz - u.eyePosition));\n // Lite-side Y-flip: compensates for our data-path Y pre-flip vs BJS's\n // mesh.scaling.y *= -1 (see file header for derivation).\n dir.y = -dir.y;\n let shColor = computeSH(dir, splatUVi32);\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 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 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 + shColor, 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 if (A < -4.0) { discard; }\n let B = exp(A) * in.vColor.a;\n var finalColor = vec4<f32>(in.vColor.rgb, B);\n /*GS_FRAGMENT_BEFORE_FRAGCOLOR*/\n /*GS_FRAGMENT_MAIN_END*/\n return finalColor;\n}\n`;\n}\n\nfunction getOrCreateShPipeline(engine: EngineContext, sig: RenderTargetSignature, shDegree: number, 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 let module = _cache.modules.get(shDegree + fragKey);\n if (!module) {\n module = device.createShaderModule({\n code: fragments && fragments.length > 0 ? applyGsFragments(buildShShaderSource(shDegree), fragments) : buildShShaderSource(shDegree),\n });\n _cache.modules.set(shDegree + fragKey, module);\n }\n const key = `${targetSignatureKey(sig)}|sh${shDegree}${fragKey}`;\n let entry = _cache.entries.get(key);\n if (entry) {\n return entry;\n }\n const shTextureCount = SH_TEXTURE_COUNT[shDegree]!;\n const layoutEntries: GPUBindGroupLayoutEntry[] = [\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 for (let i = 0; i < shTextureCount; i++) {\n layoutEntries.push({ binding: 6 + i, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"uint\" } });\n }\n const meshBindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });\n const pipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), meshBindGroupLayout] }),\n vertex: {\n module,\n entryPoint: \"vs\",\n buffers: [\n { arrayStride: 8, stepMode: \"vertex\", attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x2\" }] },\n { arrayStride: 4, stepMode: \"instance\", attributes: [{ shaderLocation: 1, offset: 0, format: \"float32\" }] },\n ],\n },\n fragment: {\n module,\n entryPoint: \"fs\",\n targets: [\n {\n format: sig._colorFormat!,\n blend: {\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, shTextureCount };\n _cache.entries.set(key, entry);\n return entry;\n}\n\n/** Build the Renderable for a GaussianSplattingMesh with SH coefficients.\n * Mirrors `buildGaussianSplattingRenderable` but adds eyePosition to the UBO\n * and binds the SH textures. */\nexport function buildGaussianSplattingRenderableSH(scene: SceneContext, mesh: GaussianSplattingMesh, fragments?: readonly GsShaderFragment[]): Renderable {\n const engine = scene.engine;\n const device = engine._device;\n\n // 3 mat4 + 8 floats (viewport,focal,dataSize,alpha,pad) + 4 floats (eyePosition + pad) = 240 bytes.\n const UBO_BYTES = 16 * 4 * 3 + 8 * 4 + 4 * 4;\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 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 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 const shViews = mesh._gs._shViews ?? [];\n const entries: GPUBindGroupEntry[] = [\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 for (let i = 0; i < entry.shTextureCount; i++) {\n entries.push({ binding: 6 + i, resource: shViews[i]! });\n }\n bg = device.createBindGroup({ layout: entry.meshBindGroupLayout, entries });\n bindGroups.set(entry.pipeline, bg);\n return bg;\n };\n\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 const camPos = getCameraPosition(cam);\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 cpu[56] = camPos.x;\n cpu[57] = camPos.y;\n cpu[58] = camPos.z;\n cpu[59] = 0;\n device.queue.writeBuffer(ubo, 0, cpu.buffer, 0, UBO_BYTES);\n\n if (!mesh._canPostToWorker) {\n return;\n }\n\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 = getOrCreateShPipeline(eng as EngineContext, sig, mesh.shDegree, 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/** SH-aware variant of `attachGaussianSplattingMesh`. Dynamic-imported by\n * `attachParsedSplat` (in `load-splat.ts`) when the parsed asset carries SH\n * coefficients. Reads `mesh.shDegree` (set at mesh construction), creates\n * the `rgba32uint` SH textures (1..5 depending on degree), patches\n * `mesh._gs` in place, and installs the SH renderable. */\nexport function attachGaussianSplattingMeshSH(scene: SceneContext, mesh: GaussianSplattingMesh, shFlat: Uint8Array, fragments?: readonly GsShaderFragment[]): void {\n const engine = scene.engine;\n const device = engine._device;\n const shDegree = mesh.shDegree;\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\n const shCoefficientCount = shVectorCount * 3;\n const textureCount = Math.ceil(shCoefficientCount / 16);\n const width = mesh.textureWidth;\n const height = mesh.textureHeight;\n\n // Pack the flat SH byte stream into N textures of 16 bytes per splat each.\n // splat i's bytes [i*shCC .. i*shCC + shCC] are split across textures\n // [t=0..textureCount-1], each carrying up to 16 bytes at offset i*16.\n const textures: GPUTexture[] = [];\n const views: GPUTextureView[] = [];\n const vertexCount = mesh.vertexCount;\n for (let t = 0; t < textureCount; t++) {\n const dst = new Uint8Array(width * height * 16);\n const tBase = t * 16;\n const bytesThisTex = Math.min(16, shCoefficientCount - tBase);\n for (let i = 0; i < vertexCount; i++) {\n const srcOff = i * shCoefficientCount + tBase;\n const dstOff = i * 16;\n for (let b = 0; b < bytesThisTex; b++) {\n dst[dstOff + b] = shFlat[srcOff + b]!;\n }\n }\n const tex = device.createTexture({\n size: [width, height],\n format: \"rgba32uint\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture({ texture: tex }, dst.buffer, { bytesPerRow: width * 16 }, { width, height });\n textures.push(tex);\n views.push(tex.createView());\n }\n mesh._gs._shTextures = textures;\n mesh._gs._shViews = views;\n\n const ctx = scene as unknown as { _renderables: Renderable[]; _disposables: (() => void)[]; _gsMeshes: GaussianSplattingMesh[] };\n ctx._renderables.push(buildGaussianSplattingRenderableSH(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"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gaussian-splatting-pipeline-sh-BvkUhA9V.js","sources":["../src/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.ts"],"sourcesContent":["/** Gaussian-Splatting SH render pipeline + Renderable.\n *\n * Variant of `gaussian-splatting-pipeline.ts` that adds view-dependent SH\n * shading. Loaded *only* by `loadSplat` (and the SOG / SPZ loaders) via a\n * dynamic `import(...)` when the parsed splat asset includes SH coefficients\n * (`mesh.shDegree > 0`), so plain `.ply` / `.splat` scenes (e.g. scene 120)\n * never pull this module's WGSL or runtime cost into their bundle.\n *\n * WGSL source is generated per-shDegree by `buildShShaderSource`: SH textures,\n * byte-to-vec3 unpacking, and the polynomial evaluation in\n * `computeColorFromSHDegree` all expand to the right size — mirrors the\n * `#if SH_DEGREE > N` blocks in BJS `gaussianSplatting.fx`. Pipeline cache is\n * keyed by `(targetSignatureKey, shDegree)`.\n *\n * The UBO grows by 16 bytes vs the base pipeline to carry `eyePosition`\n * (world-space camera position; see `computeSH(dir)` below).\n *\n * ── Why the Y-flip on the SH direction? ─────────────────────────────────\n * BJS sets `mesh.scaling.y *= -1` to fix coordinate-system handedness; Lite\n * pre-flips Y in `splat-data.ts` at parse time so the runtime mesh transform\n * is identity. World-space splat positions agree across both engines, but\n * the BJS world rotation absorbs an extra `diag(1,-1,1)` factor — i.e.\n * worldRot_bjs = worldRot_user · diag(1,-1,1)\n * which means\n * inverse(worldRot_bjs) · v = diag(1,-1,1) · inverse(worldRot_user) · v\n * so Lite reproduces the BJS SH direction by computing\n * `inverseMat3(worldRot) · (worldPos − eye)` and then negating `.y`. */\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 { applyGsFragments } from \"./gaussian-splatting-pipeline.js\";\n\ninterface PipelineEntry {\n pipeline: GPURenderPipeline;\n meshBindGroupLayout: GPUBindGroupLayout;\n shTextureCount: number;\n}\n\n// shDegree → number of rgba32uint SH textures: 1→1, 2→2, 3→3, 4→5.\nconst SH_TEXTURE_COUNT = [0, 1, 2, 3, 5];\n\nlet _cache: { device: GPUDevice; modules: Map<string, GPUShaderModule>; entries: Map<string, PipelineEntry> } | null = null;\n\n/** Build the WGSL source for a given SH degree (1..4). Mirrors the BJS\n * preprocessor-driven shader structure: declares only the SH textures used\n * by the degree, emits exactly the byte-stream unpacking for that degree,\n * and inlines only the SH polynomial terms up to that degree. */\nfunction buildShShaderSource(shDegree: number): string {\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\n const shCoefficientCount = shVectorCount * 3;\n const textureCount = Math.ceil(shCoefficientCount / 16);\n\n // ── SH texture bindings (6, 7, …) ───────────────────────────────\n let textureBindings = \"\";\n for (let i = 0; i < textureCount; i++) {\n textureBindings += `@group(1) @binding(${6 + i}) var shTexture${i}: texture_2d<u32>;\\n`;\n }\n\n // ── textureLoad calls inside readSplat ──────────────────────────\n let textureLoads = \"\";\n for (let i = 0; i < textureCount; i++) {\n textureLoads += ` let sh${i}_u32 = textureLoad(shTexture${i}, splatUVi32, 0);\\n`;\n }\n\n // ── Unpack the byte stream into sh[1..shVectorCount] vec3 values.\n //\n // Each rgba32uint texel carries 16 bytes (4 u32s × 4 bytes). The bytes\n // are stored in BJS-coefficient order: byte j of splat i is the j-th\n // component of the [R0,G0,B0, R1,G1,B1, …, R(N-1),G(N-1),B(N-1)] sequence.\n // sh[k+1] (k = 0..shVectorCount-1) reads bytes [3k, 3k+1, 3k+2]. `decompose`\n // returns `(byte * 2/255) - 1`, matching BJS exactly.\n let shUnpack = ` var sh: array<vec3<f32>, ${shVectorCount + 1}>;\\n sh[0] = vec3<f32>(0.0);\\n`;\n const byteRef = (j: number): string => {\n // texture index, u32 index within texel (0..3), byte index within u32 (0..3 == x/y/z/w).\n const tex = (j / 16) | 0;\n const u32Idx = ((j % 16) / 4) | 0;\n const byteIdx = j % 4;\n const u32Field = [\"x\", \"y\", \"z\", \"w\"][u32Idx]!;\n const byteField = [\"x\", \"y\", \"z\", \"w\"][byteIdx]!;\n return `decompose(sh${tex}_u32.${u32Field}).${byteField}`;\n };\n for (let k = 0; k < shVectorCount; k++) {\n const j = k * 3;\n shUnpack += ` sh[${k + 1}] = vec3<f32>(${byteRef(j)}, ${byteRef(j + 1)}, ${byteRef(j + 2)});\\n`;\n }\n\n // ── Polynomial evaluation, conditional on shDegree ──────────────\n let shPoly = \" result = sh[0];\\n\";\n if (shDegree >= 1) {\n shPoly += ` result += -SH_C1 * y * sh[1] + SH_C1 * z * sh[2] - SH_C1 * x * sh[3];\\n`;\n }\n if (shDegree >= 2) {\n shPoly += ` result +=\\n SH_C2[0] * xy * sh[4] +\\n SH_C2[1] * yz * sh[5] +\\n SH_C2[2] * (2.0 * zz - xx - yy) * sh[6] +\\n SH_C2[3] * xz * sh[7] +\\n SH_C2[4] * (xx - yy) * sh[8];\\n`;\n }\n if (shDegree >= 3) {\n shPoly += ` result +=\\n SH_C3[0] * y * (3.0 * xx - yy) * sh[9] +\\n SH_C3[1] * xy * z * sh[10] +\\n SH_C3[2] * y * (4.0 * zz - xx - yy) * sh[11] +\\n SH_C3[3] * z * (2.0 * zz - 3.0 * xx - 3.0 * yy) * sh[12] +\\n SH_C3[4] * x * (4.0 * zz - xx - yy) * sh[13] +\\n SH_C3[5] * z * (xx - yy) * sh[14] +\\n SH_C3[6] * x * (xx - 3.0 * yy) * sh[15];\\n`;\n }\n if (shDegree >= 4) {\n shPoly += ` result +=\\n SH_C4[0] * x * y * (xx - yy) * sh[16] +\\n SH_C4[1] * y * z * (3.0 * xx - yy) * sh[17] +\\n SH_C4[2] * x * y * (7.0 * zz - 1.0) * sh[18] +\\n SH_C4[3] * y * z * (7.0 * zz - 3.0) * sh[19] +\\n SH_C4[4] * (zz * (35.0 * zz - 30.0) + 3.0) * sh[20] +\\n SH_C4[5] * x * z * (7.0 * zz - 3.0) * sh[21] +\\n SH_C4[6] * (xx - yy) * (7.0 * zz - 1.0) * sh[22] +\\n SH_C4[7] * x * z * (xx - 3.0 * yy) * sh[23] +\\n SH_C4[8] * (xx * (xx - 3.0 * yy) - yy * (3.0 * xx - yy)) * sh[24];\\n`;\n }\n\n // SH_C2..SH_C4 constants — only declare what's referenced (silences\n // WGSL \"unused array\" warnings on lower degrees).\n let constantsBlock = `const SH_C1: f32 = 0.48860251;\\n`;\n if (shDegree >= 2) {\n constantsBlock += `const SH_C2: array<f32, 5> = array<f32, 5>(1.092548430, -1.09254843, 0.315391565, -1.09254843, 0.546274215);\\n`;\n }\n if (shDegree >= 3) {\n constantsBlock += `const SH_C3: array<f32, 7> = array<f32, 7>(-0.59004358, 2.890611442, -0.45704579, 0.373176332, -0.45704579, 1.445305721, -0.59004358);\\n`;\n }\n if (shDegree >= 4) {\n constantsBlock += `const SH_C4: array<f32, 9> = array<f32, 9>(2.5033429418, -1.7701307698, 0.9461746958, -0.6690465436, 0.1057855469, -0.6690465436, 0.4730873479, -1.7701307698, 0.6258357354);\\n`;\n }\n\n return `// Gaussian Splatting — vertex + fragment WGSL (SH degree ${shDegree}).\n// Generated by buildShShaderSource. Mirrors BJS gaussianSplatting.vertex.fx +\n// gaussianSplatting.fx (SH_DEGREE = ${shDegree}, no compound parts).\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 _pad0: f32,\n eyePosition: vec3<f32>,\n _pad1: 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${textureBindings}\n\nstruct VOut {\n @builtin(position) pos: vec4<f32>,\n @location(0) vColor: vec4<f32>,\n @location(1) vPos: vec2<f32>,\n};\n\n${constantsBlock}\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\nfn dataUvI(idx: f32) -> vec2<i32> {\n let y = floor(idx / u.dataSize.x);\n let x = idx - y * u.dataSize.x;\n return vec2<i32>(i32(x), i32(y));\n}\n\n// Unpack a u32 of 4 packed bytes into (b0 b1 b2 b3) * 2/255 - 1.\nfn decompose(value: u32) -> vec4<f32> {\n let v = vec4<f32>(\n f32((value >> 0u) & 255u),\n f32((value >> 8u) & 255u),\n f32((value >> 16u) & 255u),\n f32((value >> 24u) & 255u));\n return v * vec4<f32>(2.0 / 255.0) - vec4<f32>(1.0);\n}\n\nfn inverseMat3(m: mat3x3<f32>) -> mat3x3<f32> {\n let a00 = m[0][0]; let a01 = m[0][1]; let a02 = m[0][2];\n let a10 = m[1][0]; let a11 = m[1][1]; let a12 = m[1][2];\n let a20 = m[2][0]; let a21 = m[2][1]; let a22 = m[2][2];\n let b01 = a22 * a11 - a12 * a21;\n let b11 = -a22 * a10 + a12 * a20;\n let b21 = a21 * a10 - a11 * a20;\n let det = a00 * b01 + a01 * b11 + a02 * b21;\n return mat3x3<f32>(\n vec3<f32>(b01 / det, (-a22 * a01 + a02 * a21) / det, (a12 * a01 - a02 * a11) / det),\n vec3<f32>(b11 / det, (a22 * a00 - a02 * a20) / det, (-a12 * a00 + a02 * a10) / det),\n vec3<f32>(b21 / det, (-a21 * a00 + a01 * a20) / det, (a11 * a00 - a01 * a10) / det));\n}\n\nfn computeSH(dir: vec3<f32>, splatUVi32: vec2<i32>) -> vec3<f32> {\n${textureLoads}${shUnpack} let x = dir.x;\n let y = dir.y;\n let z = dir.z;\n let xx = x * x; let yy = y * y; let zz = z * z;\n let xy = x * y; let yz = y * z; let xz = x * z;\n var result: vec3<f32>;\n${shPoly} return result;\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 splatUVi32 = dataUvI(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 // ── View-dependent SH evaluation ───────────────────────────────────\n let worldRot = mat3x3<f32>(u.world[0].xyz, u.world[1].xyz, u.world[2].xyz);\n let normWorldRot = inverseMat3(worldRot);\n var dir = normalize(normWorldRot * (worldPos.xyz - u.eyePosition));\n // Lite-side Y-flip: compensates for our data-path Y pre-flip vs BJS's\n // mesh.scaling.y *= -1 (see file header for derivation).\n dir.y = -dir.y;\n let shColor = computeSH(dir, splatUVi32);\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 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 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 + shColor, 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 if (A < -4.0) { discard; }\n let B = exp(A) * in.vColor.a;\n var finalColor = vec4<f32>(in.vColor.rgb, B);\n /*GS_FRAGMENT_BEFORE_FRAGCOLOR*/\n /*GS_FRAGMENT_MAIN_END*/\n return finalColor;\n}\n`;\n}\n\nfunction getOrCreateShPipeline(engine: EngineContext, sig: RenderTargetSignature, shDegree: number, 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 let module = _cache.modules.get(shDegree + fragKey);\n if (!module) {\n module = device.createShaderModule({\n code: fragments && fragments.length > 0 ? applyGsFragments(buildShShaderSource(shDegree), fragments) : buildShShaderSource(shDegree),\n });\n _cache.modules.set(shDegree + fragKey, module);\n }\n const key = `${targetSignatureKey(sig)}|sh${shDegree}${fragKey}`;\n let entry = _cache.entries.get(key);\n if (entry) {\n return entry;\n }\n const shTextureCount = SH_TEXTURE_COUNT[shDegree]!;\n const layoutEntries: GPUBindGroupLayoutEntry[] = [\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 for (let i = 0; i < shTextureCount; i++) {\n layoutEntries.push({ binding: 6 + i, visibility: GPUShaderStage.VERTEX, texture: { sampleType: \"uint\" } });\n }\n const meshBindGroupLayout = device.createBindGroupLayout({ entries: layoutEntries });\n const pipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), meshBindGroupLayout] }),\n vertex: {\n module,\n entryPoint: \"vs\",\n buffers: [\n { arrayStride: 8, stepMode: \"vertex\", attributes: [{ shaderLocation: 0, offset: 0, format: \"float32x2\" }] },\n { arrayStride: 4, stepMode: \"instance\", attributes: [{ shaderLocation: 1, offset: 0, format: \"float32\" }] },\n ],\n },\n fragment: {\n module,\n entryPoint: \"fs\",\n targets: [\n {\n format: sig._colorFormat!,\n blend: {\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, shTextureCount };\n _cache.entries.set(key, entry);\n return entry;\n}\n\n/** Build the Renderable for a GaussianSplattingMesh with SH coefficients.\n * Mirrors `buildGaussianSplattingRenderable` but adds eyePosition to the UBO\n * and binds the SH textures. */\nexport function buildGaussianSplattingRenderableSH(scene: SceneContext, mesh: GaussianSplattingMesh, fragments?: readonly GsShaderFragment[]): Renderable {\n const engine = scene.engine;\n const device = engine._device;\n\n // 3 mat4 + 8 floats (viewport,focal,dataSize,alpha,pad) + 4 floats (eyePosition + pad) = 240 bytes.\n const UBO_BYTES = 16 * 4 * 3 + 8 * 4 + 4 * 4;\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 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 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 const shViews = mesh._gs._shViews ?? [];\n const entries: GPUBindGroupEntry[] = [\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 for (let i = 0; i < entry.shTextureCount; i++) {\n entries.push({ binding: 6 + i, resource: shViews[i]! });\n }\n bg = device.createBindGroup({ layout: entry.meshBindGroupLayout, entries });\n bindGroups.set(entry.pipeline, bg);\n return bg;\n };\n\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 const camPos = getCameraPosition(cam);\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 cpu[56] = camPos.x;\n cpu[57] = camPos.y;\n cpu[58] = camPos.z;\n cpu[59] = 0;\n device.queue.writeBuffer(ubo, 0, cpu.buffer, 0, UBO_BYTES);\n\n if (!mesh._canPostToWorker) {\n return;\n }\n\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 = getOrCreateShPipeline(eng as EngineContext, sig, mesh.shDegree, 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/** SH-aware variant of `attachGaussianSplattingMesh`. Dynamic-imported by\n * `attachParsedSplat` (in `load-splat.ts`) when the parsed asset carries SH\n * coefficients. Reads `mesh.shDegree` (set at mesh construction), creates\n * the `rgba32uint` SH textures (1..5 depending on degree), patches\n * `mesh._gs` in place, and installs the SH renderable. */\nexport function attachGaussianSplattingMeshSH(scene: SceneContext, mesh: GaussianSplattingMesh, shFlat: Uint8Array, fragments?: readonly GsShaderFragment[]): void {\n const engine = scene.engine;\n const device = engine._device;\n const shDegree = mesh.shDegree;\n const shVectorCount = (shDegree + 1) * (shDegree + 1) - 1;\n const shCoefficientCount = shVectorCount * 3;\n const textureCount = Math.ceil(shCoefficientCount / 16);\n const width = mesh.textureWidth;\n const height = mesh.textureHeight;\n\n // Pack the flat SH byte stream into N textures of 16 bytes per splat each.\n // splat i's bytes [i*shCC .. i*shCC + shCC] are split across textures\n // [t=0..textureCount-1], each carrying up to 16 bytes at offset i*16.\n const textures: GPUTexture[] = [];\n const views: GPUTextureView[] = [];\n const vertexCount = mesh.vertexCount;\n for (let t = 0; t < textureCount; t++) {\n const dst = new Uint8Array(width * height * 16);\n const tBase = t * 16;\n const bytesThisTex = Math.min(16, shCoefficientCount - tBase);\n for (let i = 0; i < vertexCount; i++) {\n const srcOff = i * shCoefficientCount + tBase;\n const dstOff = i * 16;\n for (let b = 0; b < bytesThisTex; b++) {\n dst[dstOff + b] = shFlat[srcOff + b]!;\n }\n }\n const tex = device.createTexture({\n size: [width, height],\n format: \"rgba32uint\",\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n });\n device.queue.writeTexture({ texture: tex }, dst.buffer, { bytesPerRow: width * 16 }, { width, height });\n textures.push(tex);\n views.push(tex.createView());\n }\n mesh._gs._shTextures = textures;\n mesh._gs._shViews = views;\n\n const ctx = scene as unknown as { _renderables: Renderable[]; _disposables: (() => void)[]; _gsMeshes: GaussianSplattingMesh[] };\n ctx._renderables.push(buildGaussianSplattingRenderableSH(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"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { j as mat4Invert, k as mat4Identity, l as mat4MultiplyInto, g as computeNodeWorldMatrix, r as resolveAccessor, I as INTERP_CUBICSPLINE, n as INTERP_STEP, o as INTERP_LINEAR, P as PATH_WEIGHTS, p as PATH_SCALE, q as PATH_ROTATION, t as PATH_TRANSLATION, u as findParent } from "./index-C8HOR2sB.js";
1
+ import { aE as mat4Invert, aF as mat4Identity, aG as getLoaderTmpAnim, aH as mat4MultiplyInto, aC as computeNodeWorldMatrix, r as resolveAccessor, aI as INTERP_CUBICSPLINE, aJ as INTERP_STEP, aK as INTERP_LINEAR, aL as PATH_WEIGHTS, aM as PATH_SCALE, aN as PATH_ROTATION, aO as PATH_TRANSLATION, aP as findParent } from "./index-B7Qhw0xL.js";
2
2
  let _parsePointerChannel = null;
3
3
  let _convertSampler = null;
4
4
  function _installPointerHandlers(parser, converter) {
@@ -35,7 +35,7 @@ function computeBoneTextureData(skin) {
35
35
  const numBones = skin.jointNodes.length;
36
36
  const data = new Float32Array(numBones * 16);
37
37
  const invMeshWorld = mat4Invert(skin.meshWorldMatrix) ?? mat4Identity();
38
- const tmp = new Float32Array(16);
38
+ const tmp = getLoaderTmpAnim();
39
39
  for (let i = 0; i < numBones; i++) {
40
40
  mat4MultiplyInto(tmp, 0, invMeshWorld, 0, skin.jointWorldMatrices[i], 0);
41
41
  mat4MultiplyInto(data, i * 16, tmp, 0, skin.inverseBindMatrices, i * 16);
@@ -242,4 +242,4 @@ export {
242
242
  extractSkin,
243
243
  parseAnimationData
244
244
  };
245
- //# sourceMappingURL=gltf-animation-D7uyTyO3.js.map
245
+ //# sourceMappingURL=gltf-animation-KnPzeOIY.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gltf-animation-D7uyTyO3.js","sources":["../src/loader-gltf/gltf-animation.ts"],"sourcesContent":["/**\n * Lazy-loaded animation/skin parsing for glTF.\n * Dynamically imported by load-gltf.ts only when a glTF contains animations or skins.\n *\n * This module is pointer-feature agnostic: KHR_animation_pointer (and the\n * non-Float32 sampler conversion that CubeVisibility-style assets need) are\n * installed via the registration seam below, so scenes that don't declare\n * the extension pay zero bytes for it.\n */\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { GltfAnimationData, AnimationClip, AnimationSampler, AnimationChannel, NodeRest, SkeletonBinding, MorphBinding, AnimatedNodeTarget } from \"../animation/types.js\";\nimport { INTERP_LINEAR, INTERP_STEP, INTERP_CUBICSPLINE, PATH_TRANSLATION, PATH_ROTATION, PATH_SCALE, PATH_WEIGHTS } from \"../animation/types.js\";\nimport { mat4Identity } from \"../math/mat4-identity.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\nimport { resolveAccessor, computeNodeWorldMatrix, findParent } from \"./gltf-parser.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\n\n/** Registration seam for KHR_animation_pointer. The pointer feature module\n * calls `_installPointerHandlers` on side-effect import; if never called,\n * pointer channels are skipped and non-Float32 samplers fall back to the\n * aliasing fast path (which throws on misaligned/short accessors). */\nexport type PointerChannelParser = (ptr: string, channel: any, nodeMap: readonly (SceneNode | undefined)[] | undefined) => AnimationChannel | null;\nexport type SamplerConverter = (src: ArrayBufferView, length: number, normalized: boolean) => Float32Array;\nlet _parsePointerChannel: PointerChannelParser | null = null;\nlet _convertSampler: SamplerConverter | null = null;\nexport function _installPointerHandlers(parser: PointerChannelParser, converter: SamplerConverter): void {\n _parsePointerChannel = parser;\n _convertSampler = converter;\n}\n\n/** Convert sampler input/output to Float32Array. Default: reinterpret existing\n * Float32 accessor as Float32Array (legacy behaviour; fast but requires\n * aligned Float32 data). KHR_animation_pointer installs a converter that\n * additionally handles non-Float32 / normalized accessors. */\nfunction toSamplerFloat32(src: ArrayBufferView, length: number, normalized: boolean): Float32Array {\n if (_convertSampler) {\n return _convertSampler(src, length, normalized);\n }\n return new Float32Array(src.buffer, src.byteOffset, length);\n}\n\n/** Parsed skin/skeleton data. */\nexport interface GltfSkinData {\n /** Node indices of joints in this skin. */\n jointNodes: number[];\n /** Inverse bind matrices — one 4×4 per joint (column-major Float32Array). */\n inverseBindMatrices: Float32Array;\n /** World matrices of each joint at rest pose. */\n jointWorldMatrices: Mat4[];\n /** World matrix of the mesh node that owns this skin. */\n meshWorldMatrix: Mat4;\n}\n\n// ─── Skin / Skeleton Extraction ─────────────────────────────────────\n\n/** Resolve a skin's inverse-bind matrices, filling with identities when absent. */\nfunction resolveIBMs(json: any, binChunk: DataView, skin: any): Float32Array {\n const jointCount = skin.joints.length;\n if (skin.inverseBindMatrices !== undefined) {\n const ibmData = resolveAccessor(json, binChunk, skin.inverseBindMatrices);\n return new Float32Array(ibmData._data.buffer, ibmData._data.byteOffset, jointCount * 16);\n }\n const out = new Float32Array(jointCount * 16);\n for (let i = 0; i < jointCount; i++) {\n const o = i * 16;\n out[o] = out[o + 5] = out[o + 10] = out[o + 15] = 1;\n }\n return out;\n}\n\nexport function extractSkin(\n json: any,\n binChunk: DataView,\n skinIdx: number,\n meshWorldMatrix: Mat4,\n parentMap: Map<number, number>,\n worldMatrixCache: Map<number, Mat4>\n): GltfSkinData {\n const skin = json.skins[skinIdx];\n const jointNodes: number[] = skin.joints;\n const inverseBindMatrices = resolveIBMs(json, binChunk, skin);\n const jointWorldMatrices: Mat4[] = jointNodes.map((nodeIdx) => computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache));\n return { jointNodes, inverseBindMatrices, jointWorldMatrices, meshWorldMatrix };\n}\n\n/** Compute rest-pose bone texture data. Each bone gets 4 vec4 (one 4×4 matrix).\n * Formula: boneMatrix[i] = inverse(meshWorld) * jointWorld[i] * IBM[i]\n * At rest pose this simplifies to identity for each bone. */\nexport function computeBoneTextureData(skin: GltfSkinData): Float32Array {\n const numBones = skin.jointNodes.length;\n const data = new Float32Array(numBones * 16);\n const invMeshWorld = mat4Invert(skin.meshWorldMatrix) ?? mat4Identity();\n const tmp = new Float32Array(16);\n for (let i = 0; i < numBones; i++) {\n mat4MultiplyInto(tmp, 0, invMeshWorld, 0, skin.jointWorldMatrices[i]!, 0);\n mat4MultiplyInto(data, i * 16, tmp, 0, skin.inverseBindMatrices, i * 16);\n }\n return data;\n}\n\n// ─── Animation Parsing ──────────────────────────────────────────────\n\nconst INTERP_MAP: Record<string, 0 | 1 | 2> = {\n LINEAR: INTERP_LINEAR,\n STEP: INTERP_STEP,\n CUBICSPLINE: INTERP_CUBICSPLINE,\n};\n\nconst PATH_MAP: Record<string, 0 | 1 | 2 | 3> = {\n translation: PATH_TRANSLATION,\n rotation: PATH_ROTATION,\n scale: PATH_SCALE,\n weights: PATH_WEIGHTS,\n};\n\n/**\n * Parse glTF animation data: clips, node hierarchy, and skeleton bindings.\n * Returns null if no animations, or no drivable state at all (no skeletons,\n * no morphs, no pointer channels).\n *\n * `nodeMap` (optional) maps glTF node index → SceneNode. It's required to\n * resolve KHR_animation_pointer targets that write to node properties.\n */\nexport function parseAnimationData(\n json: any,\n binChunk: DataView,\n meshes: Mesh[],\n parentMap: Map<number, number>,\n worldMatrixCache: Map<number, Mat4>,\n nodeMap?: readonly (SceneNode | undefined)[]\n): GltfAnimationData | null {\n if (!json.animations || json.animations.length === 0) {\n return null;\n }\n\n let pointerChannelCount = 0;\n\n // Parse animation clips\n const clips: AnimationClip[] = [];\n for (const anim of json.animations) {\n const samplers: AnimationSampler[] = [];\n for (const s of anim.samplers) {\n const inputAcc = resolveAccessor(json, binChunk, s.input);\n const outputAcc = resolveAccessor(json, binChunk, s.output);\n const inNorm = json.accessors[s.input]?.normalized === true;\n const outNorm = json.accessors[s.output]?.normalized === true;\n samplers.push({\n input: toSamplerFloat32(inputAcc._data, inputAcc._count, inNorm),\n output: toSamplerFloat32(outputAcc._data, outputAcc._count * outputAcc._componentCount, outNorm),\n interpolation: INTERP_MAP[s.interpolation ?? \"LINEAR\"] ?? INTERP_LINEAR,\n });\n }\n\n const channels: AnimationChannel[] = [];\n for (const c of anim.channels) {\n // KHR_animation_pointer: delegated to the registered pointer parser\n // (installed by gltf-feature-animation-pointer on side-effect import).\n const ptr = c.target?.extensions?.KHR_animation_pointer?.pointer;\n if (ptr) {\n if (!_parsePointerChannel) {\n continue;\n }\n const ch = _parsePointerChannel(ptr, c, nodeMap);\n if (ch) {\n channels.push(ch);\n pointerChannelCount++;\n }\n continue;\n }\n if (c.target.node === undefined) {\n continue;\n }\n const path = PATH_MAP[c.target.path];\n if (path === undefined) {\n continue;\n }\n channels.push({ samplerIdx: c.sampler, nodeIdx: c.target.node, path });\n }\n\n let duration = 0;\n for (const s of samplers) {\n if (s.input.length > 0) {\n const last = s.input[s.input.length - 1]!;\n if (last > duration) {\n duration = last;\n }\n }\n }\n\n clips.push({ name: anim.name ?? \"\", channels, samplers, duration });\n }\n\n // Build node hierarchy (rest-pose TRS + parent indices)\n const nodeCount = json.nodes?.length ?? 0;\n const nodes: NodeRest[] = [];\n for (let i = 0; i < nodeCount; i++) {\n const n = json.nodes[i];\n const t = n.translation ?? [0, 0, 0];\n const r = n.rotation ?? [0, 0, 0, 1];\n const s = n.scale ?? [1, 1, 1];\n nodes.push({\n parentIdx: findParent(parentMap, i),\n _matrix: n.matrix as Mat4 | undefined,\n tx: t[0],\n ty: t[1],\n tz: t[2],\n rx: r[0],\n ry: r[1],\n rz: r[2],\n rw: r[3],\n sx: s[0],\n sy: s[1],\n sz: s[2],\n });\n }\n\n // Build skeleton bindings (connect skin data to GPU bone textures)\n // First, build node→gpuMesh mapping by replaying extraction order\n const nodeToMeshIndices = new Map<number, number[]>();\n let gpuIdx = 0;\n for (let ni = 0; ni < nodeCount; ni++) {\n const node = json.nodes[ni];\n if (node.mesh === undefined) {\n continue;\n }\n const mesh = json.meshes[node.mesh];\n const indices: number[] = [];\n for (let p = 0; p < mesh.primitives.length; p++) {\n indices.push(gpuIdx++);\n }\n nodeToMeshIndices.set(ni, indices);\n }\n\n const skeletons: SkeletonBinding[] = [];\n for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) {\n const node = json.nodes[nodeIdx];\n if (node.skin === undefined || !json.skins) {\n continue;\n }\n\n const meshIndices = nodeToMeshIndices.get(nodeIdx);\n if (!meshIndices) {\n continue;\n }\n\n const skin = json.skins[node.skin];\n const jointNodes: number[] = skin.joints;\n const inverseBindMatrices = resolveIBMs(json, binChunk, skin);\n\n const meshWorldMatrix = computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache);\n const invMeshWorld = mat4Invert(meshWorldMatrix) ?? mat4Identity();\n\n // Create a binding for EACH mesh primitive of this skinned node\n for (const mi of meshIndices) {\n const mesh = meshes[mi];\n const skeleton = mesh?.skeleton;\n if (!skeleton) {\n continue;\n }\n skeletons.push({\n jointNodes,\n inverseBindMatrices,\n invMeshWorld,\n boneTexture: skeleton.boneTexture,\n boneCount: jointNodes.length,\n boneMatrices: skeleton.boneMatrices,\n runtimeSkeleton: skeleton,\n });\n }\n }\n\n // Build morph bindings (connect morph-target meshes to GPU weight buffers)\n const morphBindings: MorphBinding[] = [];\n for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) {\n const node = json.nodes[nodeIdx];\n if (node.mesh === undefined) {\n continue;\n }\n const gltfMesh = json.meshes[node.mesh];\n if (!gltfMesh.primitives?.[0]?.targets?.length) {\n continue;\n }\n\n const meshIndices = nodeToMeshIndices.get(nodeIdx);\n if (!meshIndices) {\n continue;\n }\n\n for (const mi of meshIndices) {\n const mesh = meshes[mi];\n const morphTargets = mesh?.morphTargets;\n if (!morphTargets) {\n continue;\n }\n morphBindings.push({\n nodeIdx,\n weightsBuffer: morphTargets.weightsBuffer,\n weights: morphTargets.weights,\n targetCount: morphTargets.count,\n runtimeMorphTargets: morphTargets,\n });\n }\n }\n\n // Build the node-TRS writeback inputs. `nodeTargets` exposes each glTF node's\n // live scene node (via the structural AnimatedNodeTarget view) so the controller\n // can push evaluated local TRS back onto the scene graph, moving non-skinned\n // node-animated meshes and their descendants. `excludedNodeIndices` lists nodes\n // that MUST NOT be written: skin joints (driven by the skeleton path) plus\n // skinned-mesh nodes and all their ancestors — their bone matrices bake an\n // `invMeshWorld` captured at load, so moving them at runtime would\n // double-transform the skinned vertices.\n const nodeTargets: readonly (AnimatedNodeTarget | undefined)[] = (nodeMap as readonly (AnimatedNodeTarget | undefined)[] | undefined) ?? [];\n const excludedNodeIndices = new Set<number>();\n for (const skin of json.skins ?? []) {\n for (const ji of skin.joints ?? []) {\n excludedNodeIndices.add(ji);\n }\n }\n for (let ni = 0; ni < nodeCount; ni++) {\n if (json.nodes[ni]?.skin === undefined) {\n continue;\n }\n let p = ni;\n while (p >= 0 && !excludedNodeIndices.has(p)) {\n excludedNodeIndices.add(p);\n p = findParent(parentMap, p);\n }\n }\n\n if (\n clips.length === 0 ||\n (skeletons.length === 0 && morphBindings.length === 0 && pointerChannelCount === 0 && !hasWritableNodeChannel(clips, nodeTargets, excludedNodeIndices))\n ) {\n return null;\n }\n return { clips, nodes, skeletons, morphBindings, nodeTargets, excludedNodeIndices };\n}\n\n/** True if any clip animates a non-excluded node that has a live scene target —\n * i.e. there is at least one plain node-TRS channel the controller can write\n * back. Lets purely-skinned/morph/pointer assets short-circuit unchanged. */\nfunction hasWritableNodeChannel(clips: readonly AnimationClip[], nodeTargets: readonly (AnimatedNodeTarget | undefined)[], excludedNodeIndices: ReadonlySet<number>): boolean {\n for (const clip of clips) {\n for (const ch of clip.channels) {\n if (\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 return true;\n }\n }\n }\n return false;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gltf-animation-KnPzeOIY.js","sources":["../src/loader-gltf/gltf-animation.ts"],"sourcesContent":["/**\n * Lazy-loaded animation/skin parsing for glTF.\n * Dynamically imported by load-gltf.ts only when a glTF contains animations or skins.\n *\n * This module is pointer-feature agnostic: KHR_animation_pointer (and the\n * non-Float32 sampler conversion that CubeVisibility-style assets need) are\n * installed via the registration seam below, so scenes that don't declare\n * the extension pay zero bytes for it.\n */\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { GltfAnimationData, AnimationClip, AnimationSampler, AnimationChannel, NodeRest, SkeletonBinding, MorphBinding, AnimatedNodeTarget } from \"../animation/types.js\";\nimport { INTERP_LINEAR, INTERP_STEP, INTERP_CUBICSPLINE, PATH_TRANSLATION, PATH_ROTATION, PATH_SCALE, PATH_WEIGHTS } from \"../animation/types.js\";\nimport { mat4Identity } from \"../math/mat4-identity.js\";\nimport { mat4Invert } from \"../math/mat4-invert.js\";\nimport { mat4MultiplyInto } from \"../math/mat4-multiply-into.js\";\nimport type { Mat4Storage } from \"../math/types.js\";\nimport { resolveAccessor, computeNodeWorldMatrix, findParent } from \"./gltf-parser.js\";\nimport { getLoaderTmpAnim } from \"./_loader-scratch.js\";\nimport type { SceneNode } from \"../scene/scene-node.js\";\n\n/** Registration seam for KHR_animation_pointer. The pointer feature module\n * calls `_installPointerHandlers` on side-effect import; if never called,\n * pointer channels are skipped and non-Float32 samplers fall back to the\n * aliasing fast path (which throws on misaligned/short accessors). */\nexport type PointerChannelParser = (ptr: string, channel: any, nodeMap: readonly (SceneNode | undefined)[] | undefined) => AnimationChannel | null;\nexport type SamplerConverter = (src: ArrayBufferView, length: number, normalized: boolean) => Float32Array;\nlet _parsePointerChannel: PointerChannelParser | null = null;\nlet _convertSampler: SamplerConverter | null = null;\nexport function _installPointerHandlers(parser: PointerChannelParser, converter: SamplerConverter): void {\n _parsePointerChannel = parser;\n _convertSampler = converter;\n}\n\n/** Convert sampler input/output to Float32Array. Default: reinterpret existing\n * Float32 accessor as Float32Array (legacy behaviour; fast but requires\n * aligned Float32 data). KHR_animation_pointer installs a converter that\n * additionally handles non-Float32 / normalized accessors. */\nfunction toSamplerFloat32(src: ArrayBufferView, length: number, normalized: boolean): Float32Array {\n if (_convertSampler) {\n return _convertSampler(src, length, normalized);\n }\n return new Float32Array(src.buffer, src.byteOffset, length);\n}\n\n/** Parsed skin/skeleton data. */\nexport interface GltfSkinData {\n /** Node indices of joints in this skin. */\n jointNodes: number[];\n /** Inverse bind matrices — one 4×4 per joint (column-major Float32Array). */\n inverseBindMatrices: Float32Array;\n /** World matrices of each joint at rest pose. */\n jointWorldMatrices: Mat4[];\n /** World matrix of the mesh node that owns this skin. */\n meshWorldMatrix: Mat4;\n}\n\n// ─── Skin / Skeleton Extraction ─────────────────────────────────────\n\n/** Resolve a skin's inverse-bind matrices, filling with identities when absent. */\nfunction resolveIBMs(json: any, binChunk: DataView, skin: any): Float32Array {\n const jointCount = skin.joints.length;\n if (skin.inverseBindMatrices !== undefined) {\n const ibmData = resolveAccessor(json, binChunk, skin.inverseBindMatrices);\n return new Float32Array(ibmData._data.buffer, ibmData._data.byteOffset, jointCount * 16);\n }\n const out = new Float32Array(jointCount * 16);\n for (let i = 0; i < jointCount; i++) {\n const o = i * 16;\n out[o] = out[o + 5] = out[o + 10] = out[o + 15] = 1;\n }\n return out;\n}\n\nexport function extractSkin(\n json: any,\n binChunk: DataView,\n skinIdx: number,\n meshWorldMatrix: Mat4,\n parentMap: Map<number, number>,\n worldMatrixCache: Map<number, Mat4>\n): GltfSkinData {\n const skin = json.skins[skinIdx];\n const jointNodes: number[] = skin.joints;\n const inverseBindMatrices = resolveIBMs(json, binChunk, skin);\n const jointWorldMatrices: Mat4[] = jointNodes.map((nodeIdx) => computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache));\n return { jointNodes, inverseBindMatrices, jointWorldMatrices, meshWorldMatrix };\n}\n\n/** Compute rest-pose bone texture data. Each bone gets 4 vec4 (one 4×4 matrix).\n * Formula: boneMatrix[i] = inverse(meshWorld) * jointWorld[i] * IBM[i]\n * At rest pose this simplifies to identity for each bone. */\nexport function computeBoneTextureData(skin: GltfSkinData): Float32Array {\n const numBones = skin.jointNodes.length;\n const data = new Float32Array(numBones * 16);\n const invMeshWorld = mat4Invert(skin.meshWorldMatrix) ?? mat4Identity();\n const tmp = getLoaderTmpAnim() as unknown as Mat4Storage;\n for (let i = 0; i < numBones; i++) {\n mat4MultiplyInto(tmp, 0, invMeshWorld as unknown as Mat4Storage, 0, skin.jointWorldMatrices[i]! as unknown as Mat4Storage, 0);\n mat4MultiplyInto(data, i * 16, tmp, 0, skin.inverseBindMatrices, i * 16);\n }\n return data;\n}\n\n// ─── Animation Parsing ──────────────────────────────────────────────\n\nconst INTERP_MAP: Record<string, 0 | 1 | 2> = {\n LINEAR: INTERP_LINEAR,\n STEP: INTERP_STEP,\n CUBICSPLINE: INTERP_CUBICSPLINE,\n};\n\nconst PATH_MAP: Record<string, 0 | 1 | 2 | 3> = {\n translation: PATH_TRANSLATION,\n rotation: PATH_ROTATION,\n scale: PATH_SCALE,\n weights: PATH_WEIGHTS,\n};\n\n/**\n * Parse glTF animation data: clips, node hierarchy, and skeleton bindings.\n * Returns null if no animations, or no drivable state at all (no skeletons,\n * no morphs, no pointer channels).\n *\n * `nodeMap` (optional) maps glTF node index → SceneNode. It's required to\n * resolve KHR_animation_pointer targets that write to node properties.\n */\nexport function parseAnimationData(\n json: any,\n binChunk: DataView,\n meshes: Mesh[],\n parentMap: Map<number, number>,\n worldMatrixCache: Map<number, Mat4>,\n nodeMap?: readonly (SceneNode | undefined)[]\n): GltfAnimationData | null {\n if (!json.animations || json.animations.length === 0) {\n return null;\n }\n\n let pointerChannelCount = 0;\n\n // Parse animation clips\n const clips: AnimationClip[] = [];\n for (const anim of json.animations) {\n const samplers: AnimationSampler[] = [];\n for (const s of anim.samplers) {\n const inputAcc = resolveAccessor(json, binChunk, s.input);\n const outputAcc = resolveAccessor(json, binChunk, s.output);\n const inNorm = json.accessors[s.input]?.normalized === true;\n const outNorm = json.accessors[s.output]?.normalized === true;\n samplers.push({\n input: toSamplerFloat32(inputAcc._data, inputAcc._count, inNorm),\n output: toSamplerFloat32(outputAcc._data, outputAcc._count * outputAcc._componentCount, outNorm),\n interpolation: INTERP_MAP[s.interpolation ?? \"LINEAR\"] ?? INTERP_LINEAR,\n });\n }\n\n const channels: AnimationChannel[] = [];\n for (const c of anim.channels) {\n // KHR_animation_pointer: delegated to the registered pointer parser\n // (installed by gltf-feature-animation-pointer on side-effect import).\n const ptr = c.target?.extensions?.KHR_animation_pointer?.pointer;\n if (ptr) {\n if (!_parsePointerChannel) {\n continue;\n }\n const ch = _parsePointerChannel(ptr, c, nodeMap);\n if (ch) {\n channels.push(ch);\n pointerChannelCount++;\n }\n continue;\n }\n if (c.target.node === undefined) {\n continue;\n }\n const path = PATH_MAP[c.target.path];\n if (path === undefined) {\n continue;\n }\n channels.push({ samplerIdx: c.sampler, nodeIdx: c.target.node, path });\n }\n\n let duration = 0;\n for (const s of samplers) {\n if (s.input.length > 0) {\n const last = s.input[s.input.length - 1]!;\n if (last > duration) {\n duration = last;\n }\n }\n }\n\n clips.push({ name: anim.name ?? \"\", channels, samplers, duration });\n }\n\n // Build node hierarchy (rest-pose TRS + parent indices)\n const nodeCount = json.nodes?.length ?? 0;\n const nodes: NodeRest[] = [];\n for (let i = 0; i < nodeCount; i++) {\n const n = json.nodes[i];\n const t = n.translation ?? [0, 0, 0];\n const r = n.rotation ?? [0, 0, 0, 1];\n const s = n.scale ?? [1, 1, 1];\n nodes.push({\n parentIdx: findParent(parentMap, i),\n _matrix: n.matrix as Mat4 | undefined,\n tx: t[0],\n ty: t[1],\n tz: t[2],\n rx: r[0],\n ry: r[1],\n rz: r[2],\n rw: r[3],\n sx: s[0],\n sy: s[1],\n sz: s[2],\n });\n }\n\n // Build skeleton bindings (connect skin data to GPU bone textures)\n // First, build node→gpuMesh mapping by replaying extraction order\n const nodeToMeshIndices = new Map<number, number[]>();\n let gpuIdx = 0;\n for (let ni = 0; ni < nodeCount; ni++) {\n const node = json.nodes[ni];\n if (node.mesh === undefined) {\n continue;\n }\n const mesh = json.meshes[node.mesh];\n const indices: number[] = [];\n for (let p = 0; p < mesh.primitives.length; p++) {\n indices.push(gpuIdx++);\n }\n nodeToMeshIndices.set(ni, indices);\n }\n\n const skeletons: SkeletonBinding[] = [];\n for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) {\n const node = json.nodes[nodeIdx];\n if (node.skin === undefined || !json.skins) {\n continue;\n }\n\n const meshIndices = nodeToMeshIndices.get(nodeIdx);\n if (!meshIndices) {\n continue;\n }\n\n const skin = json.skins[node.skin];\n const jointNodes: number[] = skin.joints;\n const inverseBindMatrices = resolveIBMs(json, binChunk, skin);\n\n const meshWorldMatrix = computeNodeWorldMatrix(json, nodeIdx, parentMap, worldMatrixCache);\n const invMeshWorld = mat4Invert(meshWorldMatrix) ?? mat4Identity();\n\n // Create a binding for EACH mesh primitive of this skinned node\n for (const mi of meshIndices) {\n const mesh = meshes[mi];\n const skeleton = mesh?.skeleton;\n if (!skeleton) {\n continue;\n }\n skeletons.push({\n jointNodes,\n inverseBindMatrices,\n invMeshWorld,\n boneTexture: skeleton.boneTexture,\n boneCount: jointNodes.length,\n boneMatrices: skeleton.boneMatrices,\n runtimeSkeleton: skeleton,\n });\n }\n }\n\n // Build morph bindings (connect morph-target meshes to GPU weight buffers)\n const morphBindings: MorphBinding[] = [];\n for (let nodeIdx = 0; nodeIdx < nodeCount; nodeIdx++) {\n const node = json.nodes[nodeIdx];\n if (node.mesh === undefined) {\n continue;\n }\n const gltfMesh = json.meshes[node.mesh];\n if (!gltfMesh.primitives?.[0]?.targets?.length) {\n continue;\n }\n\n const meshIndices = nodeToMeshIndices.get(nodeIdx);\n if (!meshIndices) {\n continue;\n }\n\n for (const mi of meshIndices) {\n const mesh = meshes[mi];\n const morphTargets = mesh?.morphTargets;\n if (!morphTargets) {\n continue;\n }\n morphBindings.push({\n nodeIdx,\n weightsBuffer: morphTargets.weightsBuffer,\n weights: morphTargets.weights,\n targetCount: morphTargets.count,\n runtimeMorphTargets: morphTargets,\n });\n }\n }\n\n // Build the node-TRS writeback inputs. `nodeTargets` exposes each glTF node's\n // live scene node (via the structural AnimatedNodeTarget view) so the controller\n // can push evaluated local TRS back onto the scene graph, moving non-skinned\n // node-animated meshes and their descendants. `excludedNodeIndices` lists nodes\n // that MUST NOT be written: skin joints (driven by the skeleton path) plus\n // skinned-mesh nodes and all their ancestors — their bone matrices bake an\n // `invMeshWorld` captured at load, so moving them at runtime would\n // double-transform the skinned vertices.\n const nodeTargets: readonly (AnimatedNodeTarget | undefined)[] = (nodeMap as readonly (AnimatedNodeTarget | undefined)[] | undefined) ?? [];\n const excludedNodeIndices = new Set<number>();\n for (const skin of json.skins ?? []) {\n for (const ji of skin.joints ?? []) {\n excludedNodeIndices.add(ji);\n }\n }\n for (let ni = 0; ni < nodeCount; ni++) {\n if (json.nodes[ni]?.skin === undefined) {\n continue;\n }\n let p = ni;\n while (p >= 0 && !excludedNodeIndices.has(p)) {\n excludedNodeIndices.add(p);\n p = findParent(parentMap, p);\n }\n }\n\n if (\n clips.length === 0 ||\n (skeletons.length === 0 && morphBindings.length === 0 && pointerChannelCount === 0 && !hasWritableNodeChannel(clips, nodeTargets, excludedNodeIndices))\n ) {\n return null;\n }\n return { clips, nodes, skeletons, morphBindings, nodeTargets, excludedNodeIndices };\n}\n\n/** True if any clip animates a non-excluded node that has a live scene target —\n * i.e. there is at least one plain node-TRS channel the controller can write\n * back. Lets purely-skinned/morph/pointer assets short-circuit unchanged. */\nfunction hasWritableNodeChannel(clips: readonly AnimationClip[], nodeTargets: readonly (AnimatedNodeTarget | undefined)[], excludedNodeIndices: ReadonlySet<number>): boolean {\n for (const clip of clips) {\n for (const ch of clip.channels) {\n if (\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 return true;\n }\n }\n }\n return false;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ function normalizeColorToVec3(data, count, comps) {
2
+ const out = new Float32Array(count * 3);
3
+ if (data instanceof Float32Array) {
4
+ for (let v = 0; v < count; v++) {
5
+ out[v * 3] = data[v * comps];
6
+ out[v * 3 + 1] = data[v * comps + 1];
7
+ out[v * 3 + 2] = data[v * comps + 2];
8
+ }
9
+ } else if (data instanceof Uint16Array) {
10
+ const inv = 1 / 65535;
11
+ for (let v = 0; v < count; v++) {
12
+ out[v * 3] = data[v * comps] * inv;
13
+ out[v * 3 + 1] = data[v * comps + 1] * inv;
14
+ out[v * 3 + 2] = data[v * comps + 2] * inv;
15
+ }
16
+ } else if (data instanceof Uint8Array) {
17
+ const inv = 1 / 255;
18
+ for (let v = 0; v < count; v++) {
19
+ out[v * 3] = data[v * comps] * inv;
20
+ out[v * 3 + 1] = data[v * comps + 1] * inv;
21
+ out[v * 3 + 2] = data[v * comps + 2] * inv;
22
+ }
23
+ }
24
+ return out;
25
+ }
26
+ export {
27
+ normalizeColorToVec3
28
+ };
29
+ //# sourceMappingURL=gltf-color-normalize-Qxl-9C48.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-color-normalize-Qxl-9C48.js","sources":["../src/loader-gltf/gltf-color-normalize.ts"],"sourcesContent":["/** glTF COLOR_0 vertex-color normalization — dynamically imported.\n *\n * Isolated from the core loader so scenes whose assets have no COLOR_0 attribute\n * (the common case) never bundle or fetch this code. Loaded lazily by\n * `load-gltf.ts` only when a primitive actually provides COLOR_0.\n *\n * Zero module-level side effects — safe for tree-shaking.\n */\n\n/** Normalize a glTF COLOR_0 attribute to a tight float32 VEC3 (RGB) buffer.\n *\n * The PBR/standard vertex pipelines bind vertex color as a single format: `float32x3`\n * (stride 12). glTF COLOR_0 is far more permissive — it may be VEC3 or VEC4, and its\n * component type may be float OR normalized unsigned byte/short. Binding any other layout\n * to the stride-12 float pipeline misaligns every vertex (garbage / black colors). So we\n * always convert here: integer types are normalized to [0,1] (per the glTF spec, integer\n * COLOR_0 is always normalized), VEC4 alpha is dropped (Lite shading multiplies only the\n * rgb of vertex color into the base color), and the result is a tight Float32Array RGB.\n *\n * `data` is the resolved accessor view (Float32Array | Uint8Array | Uint16Array), `count`\n * the vertex count, and `comps` the component count (3 or 4). */\nexport function normalizeColorToVec3(data: ArrayBufferView, count: number, comps: number): Float32Array {\n const out = new Float32Array(count * 3);\n if (data instanceof Float32Array) {\n for (let v = 0; v < count; v++) {\n out[v * 3] = data[v * comps]!;\n out[v * 3 + 1] = data[v * comps + 1]!;\n out[v * 3 + 2] = data[v * comps + 2]!;\n }\n } else if (data instanceof Uint16Array) {\n const inv = 1 / 65535;\n for (let v = 0; v < count; v++) {\n out[v * 3] = data[v * comps]! * inv;\n out[v * 3 + 1] = data[v * comps + 1]! * inv;\n out[v * 3 + 2] = data[v * comps + 2]! * inv;\n }\n } else if (data instanceof Uint8Array) {\n const inv = 1 / 255;\n for (let v = 0; v < count; v++) {\n out[v * 3] = data[v * comps]! * inv;\n out[v * 3 + 1] = data[v * comps + 1]! * inv;\n out[v * 3 + 2] = data[v * comps + 2]! * inv;\n }\n }\n return out;\n}\n"],"names":[],"mappings":"AAqBO,SAAS,qBAAqB,MAAuB,OAAe,OAA6B;AACpG,QAAM,MAAM,IAAI,aAAa,QAAQ,CAAC;AACtC,MAAI,gBAAgB,cAAc;AAC9B,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,UAAI,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK;AAC3B,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC;AACnC,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC;AAAA,IACvC;AAAA,EACJ,WAAW,gBAAgB,aAAa;AACpC,UAAM,MAAM,IAAI;AAChB,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,UAAI,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAK;AAChC,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,IAAK;AACxC,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,IAAK;AAAA,IAC5C;AAAA,EACJ,WAAW,gBAAgB,YAAY;AACnC,UAAM,MAAM,IAAI;AAChB,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC5B,UAAI,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAK;AAChC,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,IAAK;AACxC,UAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,QAAQ,CAAC,IAAK;AAAA,IAC5C;AAAA,EACJ;AACA,SAAO;AACX;"}
@@ -1,4 +1,4 @@
1
- import { aT as getCompressedFormat, aU as acquireTexture, aO as getOrCreateSampler, r as resolveAccessor } from "./index-C8HOR2sB.js";
1
+ import { b7 as getCompressedFormat, b4 as acquireTexture, aW as getOrCreateSampler, r as resolveAccessor } from "./index-B7Qhw0xL.js";
2
2
  const KTX2_DECODER_URL = "https://cdn.babylonjs.com/babylon.ktx2Decoder.js";
3
3
  let _ktx2DecoderPromise = null;
4
4
  const GL_RGBA8 = 32856;
@@ -138,8 +138,11 @@ function uploadCompressed(engine, mips, format, sRGB) {
138
138
  });
139
139
  for (let level = 0; level < mips.length; level++) {
140
140
  const mip = mips[level];
141
- const rowBytes = Math.ceil(mip.width / format.blockW) * format.blockBytes;
142
- engine._device.queue.writeTexture({ texture, mipLevel: level }, mip.data, { bytesPerRow: rowBytes }, { width: mip.width, height: mip.height });
141
+ const blocksPerRow = Math.ceil(mip.width / format.blockW);
142
+ const rowBytes = blocksPerRow * format.blockBytes;
143
+ const copyW = blocksPerRow * format.blockW;
144
+ const copyH = Math.ceil(mip.height / format.blockH) * format.blockH;
145
+ engine._device.queue.writeTexture({ texture, mipLevel: level }, mip.data, { bytesPerRow: rowBytes }, { width: copyW, height: copyH });
143
146
  }
144
147
  const tex2d = { texture, view: texture.createView(), sampler: makeSampler(engine, mips.length), width, height, invertY: true };
145
148
  acquireTexture(tex2d);
@@ -449,4 +452,4 @@ const ext = {
449
452
  export {
450
453
  ext as default
451
454
  };
452
- //# sourceMappingURL=gltf-ext-basisu-CPg5kPrx.js.map
455
+ //# sourceMappingURL=gltf-ext-basisu-kmth3UWX.js.map