@babylonjs/lite 1.0.1 → 1.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 (212) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +51 -0
  3. package/THIRD_PARTY_NOTICES.txt +318 -0
  4. package/{_mat4-storage-f64-BW9sTaVh.js → _mat4-storage-f64-WeexU-hd.js} +2 -2
  5. package/{_mat4-storage-f64-BW9sTaVh.js.map → _mat4-storage-f64-WeexU-hd.js.map} +1 -1
  6. package/{alpha-test-fragment-eUG971h3.js → alpha-test-fragment-x2mnjLgC.js} +2 -2
  7. package/{alpha-test-fragment-eUG971h3.js.map → alpha-test-fragment-x2mnjLgC.js.map} +1 -1
  8. package/{background-dds-skybox-BwG0kYQP.js → background-dds-skybox-BpcDr-9c.js} +3 -3
  9. package/{background-dds-skybox-BwG0kYQP.js.map → background-dds-skybox-BpcDr-9c.js.map} +1 -1
  10. package/{background-ground-DiFpKJzF.js → background-ground-Bm6gjWqx.js} +2 -2
  11. package/{background-ground-DiFpKJzF.js.map → background-ground-Bm6gjWqx.js.map} +1 -1
  12. package/{background-hdr-skybox-DIgJhvfj.js → background-hdr-skybox-CSFo8RX6.js} +3 -3
  13. package/{background-hdr-skybox-DIgJhvfj.js.map → background-hdr-skybox-CSFo8RX6.js.map} +1 -1
  14. package/{background-solid-skybox--fqHdan_.js → background-solid-skybox-DOOBeDIz.js} +2 -2
  15. package/{background-solid-skybox--fqHdan_.js.map → background-solid-skybox-DOOBeDIz.js.map} +1 -1
  16. package/{billboard-renderable-HY2XCd52.js → billboard-renderable-IJfCpeDS.js} +2 -2
  17. package/{billboard-renderable-HY2XCd52.js.map → billboard-renderable-IJfCpeDS.js.map} +1 -1
  18. package/{clamp-block-XHdUk2Va.js → clamp-block-BD_t8I89.js} +2 -2
  19. package/{clamp-block-XHdUk2Va.js.map → clamp-block-BD_t8I89.js.map} +1 -1
  20. package/{clearcoat-fragment-CHYw8MPB.js → clearcoat-fragment-Dj7vGX2u.js} +2 -2
  21. package/{clearcoat-fragment-CHYw8MPB.js.map → clearcoat-fragment-Dj7vGX2u.js.map} +1 -1
  22. package/{create-skeleton-9tdiUjRP.js → create-skeleton-s0hjrC3A.js} +2 -2
  23. package/{create-skeleton-9tdiUjRP.js.map → create-skeleton-s0hjrC3A.js.map} +1 -1
  24. package/{cubemap-skybox-material-DqQ0dyz8.js → cubemap-skybox-material-8lzbgi7K.js} +2 -2
  25. package/{cubemap-skybox-material-DqQ0dyz8.js.map → cubemap-skybox-material-8lzbgi7K.js.map} +1 -1
  26. package/{curve-block-S27sXrJQ.js → curve-block-Ditr4R7V.js} +2 -2
  27. package/{curve-block-S27sXrJQ.js.map → curve-block-Ditr4R7V.js.map} +1 -1
  28. package/{emissive-fragment-CZMQ0_bF.js → emissive-fragment-BOAezkfk.js} +2 -2
  29. package/{emissive-fragment-CZMQ0_bF.js.map → emissive-fragment-BOAezkfk.js.map} +1 -1
  30. package/{esm-shadow-view-Cl36rOrK.js → esm-shadow-view-DRpyRAfa.js} +2 -2
  31. package/{esm-shadow-view-Cl36rOrK.js.map → esm-shadow-view-DRpyRAfa.js.map} +1 -1
  32. package/{esm-shadow-view-CUwxbnMR.js → esm-shadow-view-DmIORQGZ.js} +2 -2
  33. package/{esm-shadow-view-CUwxbnMR.js.map → esm-shadow-view-DmIORQGZ.js.map} +1 -1
  34. package/{esm-shadow-view-DKQ-FSoV.js → esm-shadow-view-JCPaOOi7.js} +2 -2
  35. package/{esm-shadow-view-DKQ-FSoV.js.map → esm-shadow-view-JCPaOOi7.js.map} +1 -1
  36. package/{gaussian-splatting-pipeline-sh-DDo7QQ8l.js → gaussian-splatting-pipeline-sh-B30Mu56i.js} +2 -2
  37. package/{gaussian-splatting-pipeline-sh-DDo7QQ8l.js.map → gaussian-splatting-pipeline-sh-B30Mu56i.js.map} +1 -1
  38. package/{geometry-texture-output-BmuAquio.js → geometry-texture-output-DURiaJ_n.js} +2 -2
  39. package/{geometry-texture-output-BmuAquio.js.map → geometry-texture-output-DURiaJ_n.js.map} +1 -1
  40. package/{geometry-view-xWZmq799.js → geometry-view-DRrscyWU.js} +4 -4
  41. package/{geometry-view-xWZmq799.js.map → geometry-view-DRrscyWU.js.map} +1 -1
  42. package/{gltf-animation-Bq7k_5HA.js → gltf-animation-BjnXkop6.js} +2 -2
  43. package/{gltf-animation-Bq7k_5HA.js.map → gltf-animation-BjnXkop6.js.map} +1 -1
  44. package/{gltf-ext-basisu-C5teqxzQ.js → gltf-ext-basisu-DtzVV1Xx.js} +2 -2
  45. package/{gltf-ext-basisu-C5teqxzQ.js.map → gltf-ext-basisu-DtzVV1Xx.js.map} +1 -1
  46. package/{gltf-ext-node-visibility-DnGTKkMf.js → gltf-ext-node-visibility-BhX0DmiP.js} +2 -2
  47. package/{gltf-ext-node-visibility-DnGTKkMf.js.map → gltf-ext-node-visibility-BhX0DmiP.js.map} +1 -1
  48. package/{gltf-ext-quantization-DheC7FhB.js → gltf-ext-quantization-DaymajCR.js} +2 -2
  49. package/{gltf-ext-quantization-DheC7FhB.js.map → gltf-ext-quantization-DaymajCR.js.map} +1 -1
  50. package/{gltf-ext-uv-transform-DljdVllE.js → gltf-ext-uv-transform-DFmNJ8kA.js} +2 -2
  51. package/{gltf-ext-uv-transform-DljdVllE.js.map → gltf-ext-uv-transform-DFmNJ8kA.js.map} +1 -1
  52. package/{gltf-feature-animation-pointer-DVhymFLK.js → gltf-feature-animation-pointer-C40tqOhL.js} +3 -3
  53. package/{gltf-feature-animation-pointer-DVhymFLK.js.map → gltf-feature-animation-pointer-C40tqOhL.js.map} +1 -1
  54. package/{gltf-feature-animations-hxC3y3bJ.js → gltf-feature-animations-v0S_yb4T.js} +2 -2
  55. package/{gltf-feature-animations-hxC3y3bJ.js.map → gltf-feature-animations-v0S_yb4T.js.map} +1 -1
  56. package/{gltf-feature-draco-B7Q_cMUv.js → gltf-feature-draco-CljWrsna.js} +2 -2
  57. package/{gltf-feature-draco-B7Q_cMUv.js.map → gltf-feature-draco-CljWrsna.js.map} +1 -1
  58. package/{gltf-feature-gpu-instancing-C7sRzWv7.js → gltf-feature-gpu-instancing-BoeSm6Tn.js} +2 -2
  59. package/{gltf-feature-gpu-instancing-C7sRzWv7.js.map → gltf-feature-gpu-instancing-BoeSm6Tn.js.map} +1 -1
  60. package/{gltf-feature-lights-punctual-DF7kya14.js → gltf-feature-lights-punctual-BCTwgyi_.js} +5 -5
  61. package/{gltf-feature-lights-punctual-DF7kya14.js.map → gltf-feature-lights-punctual-BCTwgyi_.js.map} +1 -1
  62. package/{gltf-feature-meshopt-DRG9hEqT.js → gltf-feature-meshopt-DItMkOMt.js} +2 -2
  63. package/{gltf-feature-meshopt-DRG9hEqT.js.map → gltf-feature-meshopt-DItMkOMt.js.map} +1 -1
  64. package/{gltf-feature-morph-DZydYgWp.js → gltf-feature-morph-Cv0mEYIq.js} +3 -3
  65. package/{gltf-feature-morph-DZydYgWp.js.map → gltf-feature-morph-Cv0mEYIq.js.map} +1 -1
  66. package/{gltf-feature-registry-DeYdy3DV.js → gltf-feature-registry-wNbt6UC-.js} +15 -15
  67. package/{gltf-feature-registry-DeYdy3DV.js.map → gltf-feature-registry-wNbt6UC-.js.map} +1 -1
  68. package/{gltf-feature-skeleton-B9och1W0.js → gltf-feature-skeleton-Deh2UBAn.js} +3 -3
  69. package/{gltf-feature-skeleton-B9och1W0.js.map → gltf-feature-skeleton-Deh2UBAn.js.map} +1 -1
  70. package/{gltf-feature-variants-CY_Qft7f.js → gltf-feature-variants-DGSdFNJq.js} +2 -2
  71. package/{gltf-feature-variants-CY_Qft7f.js.map → gltf-feature-variants-DGSdFNJq.js.map} +1 -1
  72. package/{gltf-glb-parser-CqOeXFOz.js → gltf-glb-parser-DSQWsT4r.js} +2 -2
  73. package/{gltf-glb-parser-CqOeXFOz.js.map → gltf-glb-parser-DSQWsT4r.js.map} +1 -1
  74. package/{gltf-interleave-DWf27t-h.js → gltf-interleave-OBqmlu-h.js} +11 -4
  75. package/gltf-interleave-OBqmlu-h.js.map +1 -0
  76. package/{gltf-normals-b2h74380.js → gltf-normals-D_P0KA4b.js} +10 -2
  77. package/gltf-normals-D_P0KA4b.js.map +1 -0
  78. package/{gltf-pbr-builder-ext-DvFxuOqN.js → gltf-pbr-builder-ext-3imk8Tev.js} +2 -2
  79. package/{gltf-pbr-builder-ext-DvFxuOqN.js.map → gltf-pbr-builder-ext-3imk8Tev.js.map} +1 -1
  80. package/{gltf-variants-CUvzYGYX.js → gltf-variants-Dyr54wwg.js} +4 -4
  81. package/{gltf-variants-CUvzYGYX.js.map → gltf-variants-Dyr54wwg.js.map} +1 -1
  82. package/{gpu-task-timer-Dgkff80h.js → gpu-task-timer-DVBNZfq5.js} +2 -2
  83. package/{gpu-task-timer-Dgkff80h.js.map → gpu-task-timer-DVBNZfq5.js.map} +1 -1
  84. package/{gs-picking-pipeline-55sM5LzV.js → gs-picking-pipeline-CERN-Trj.js} +2 -2
  85. package/{gs-picking-pipeline-55sM5LzV.js.map → gs-picking-pipeline-CERN-Trj.js.map} +1 -1
  86. package/{havok-floating-origin-5xp32P-C.js → havok-floating-origin-VVdJRUYc.js} +2 -2
  87. package/{havok-floating-origin-5xp32P-C.js.map → havok-floating-origin-VVdJRUYc.js.map} +1 -1
  88. package/{index-CYZDclhF.js → index-7Bk-uLSM.js} +2 -2
  89. package/{index-CYZDclhF.js.map → index-7Bk-uLSM.js.map} +1 -1
  90. package/{index-C-tEgwbZ.js → index-BgY3QEzL.js} +2817 -1166
  91. package/index-BgY3QEzL.js.map +1 -0
  92. package/{index-SMJ67XwT.js → index-Dr5LK2tg.js} +2 -2
  93. package/{index-SMJ67XwT.js.map → index-Dr5LK2tg.js.map} +1 -1
  94. package/index.d.ts +572 -18
  95. package/index.js +499 -464
  96. package/{input-block-DbRYCnet.js → input-block-DjdlndCL.js} +2 -2
  97. package/{input-block-DbRYCnet.js.map → input-block-DjdlndCL.js.map} +1 -1
  98. package/{iridescence-fragment-S3Ko1jvC.js → iridescence-fragment-kfsCs8lN.js} +2 -2
  99. package/{iridescence-fragment-S3Ko1jvC.js.map → iridescence-fragment-kfsCs8lN.js.map} +1 -1
  100. package/{light-block-CAqWkucp.js → light-block-qjCrz3de.js} +2 -2
  101. package/{light-block-CAqWkucp.js.map → light-block-qjCrz3de.js.map} +1 -1
  102. package/{loop-block-ch-biPFY.js → loop-block-C8vkQ2bz.js} +2 -2
  103. package/{loop-block-ch-biPFY.js.map → loop-block-C8vkQ2bz.js.map} +1 -1
  104. package/{manifold-AS8POaOr.js → manifold-DeXMNgxT.js} +3 -3
  105. package/{manifold-AS8POaOr.js.map → manifold-DeXMNgxT.js.map} +1 -1
  106. package/{morph-fragment-D9he3Ksk.js → morph-fragment-NpZYyIIU.js} +2 -2
  107. package/{morph-fragment-D9he3Ksk.js.map → morph-fragment-NpZYyIIU.js.map} +1 -1
  108. package/{multilight-wgsl-74aXpcJG.js → multilight-wgsl-I5SncF0q.js} +2 -2
  109. package/{multilight-wgsl-74aXpcJG.js.map → multilight-wgsl-I5SncF0q.js.map} +1 -1
  110. package/{node-env-B2bjGcMS.js → node-env-D7Aee08u.js} +2 -2
  111. package/{node-env-B2bjGcMS.js.map → node-env-D7Aee08u.js.map} +1 -1
  112. package/{node-geometry-view-CSXlEAhG.js → node-geometry-view-DfKXWNfV.js} +3 -3
  113. package/{node-geometry-view-CSXlEAhG.js.map → node-geometry-view-DfKXWNfV.js.map} +1 -1
  114. package/{node-registry-extra-compat-BEQH_ksg.js → node-registry-extra-compat-CDLeBR1P.js} +2 -2
  115. package/{node-registry-extra-compat-BEQH_ksg.js.map → node-registry-extra-compat-CDLeBR1P.js.map} +1 -1
  116. package/{node-registry-extra-math-Bm32WBAa.js → node-registry-extra-math-BA8_l4lB.js} +2 -2
  117. package/{node-registry-extra-math-Bm32WBAa.js.map → node-registry-extra-math-BA8_l4lB.js.map} +1 -1
  118. package/{node-renderable-BMHny4tC.js → node-renderable-EwLLnaL1.js} +2 -2
  119. package/{node-renderable-BMHny4tC.js.map → node-renderable-EwLLnaL1.js.map} +1 -1
  120. package/{node-shadow-BRiz7CT1.js → node-shadow-CeTmT6g4.js} +2 -2
  121. package/{node-shadow-BRiz7CT1.js.map → node-shadow-CeTmT6g4.js.map} +1 -1
  122. package/{normal-map-fragment-sE3TjF4U.js → normal-map-fragment-BHImLyM-.js} +2 -2
  123. package/{normal-map-fragment-sE3TjF4U.js.map → normal-map-fragment-BHImLyM-.js.map} +1 -1
  124. package/package.json +10 -3
  125. package/{parse-camera-CmZBS423.js → parse-camera-5IGdctAS.js} +2 -2
  126. package/{parse-camera-CmZBS423.js.map → parse-camera-5IGdctAS.js.map} +1 -1
  127. package/{pbr-geometry-view-T3vMABM8.js → pbr-geometry-view-Dthf9Aut.js} +3 -3
  128. package/{pbr-geometry-view-T3vMABM8.js.map → pbr-geometry-view-Dthf9Aut.js.map} +1 -1
  129. package/{pbr-metallic-roughness-block-full-CHC8w-Uv.js → pbr-metallic-roughness-block-full-DD6zI_Lx.js} +2 -2
  130. package/{pbr-metallic-roughness-block-full-CHC8w-Uv.js.map → pbr-metallic-roughness-block-full-DD6zI_Lx.js.map} +1 -1
  131. package/{pbr-metallic-roughness-block-DbozMlHU.js → pbr-metallic-roughness-block-g7wjzwN_.js} +2 -2
  132. package/{pbr-metallic-roughness-block-DbozMlHU.js.map → pbr-metallic-roughness-block-g7wjzwN_.js.map} +1 -1
  133. package/{pbr-mr-helper-core-DGRgbRXl.js → pbr-mr-helper-core-CWROQ7OA.js} +2 -2
  134. package/{pbr-mr-helper-core-DGRgbRXl.js.map → pbr-mr-helper-core-CWROQ7OA.js.map} +1 -1
  135. package/{pbr-refraction-CquDP9JO.js → pbr-refraction-Dxsm_gii.js} +2 -2
  136. package/{pbr-refraction-CquDP9JO.js.map → pbr-refraction-Dxsm_gii.js.map} +1 -1
  137. package/{pbr-renderable-CaHKHU0g.js → pbr-renderable-CuKWalEM.js} +22 -22
  138. package/{pbr-renderable-CaHKHU0g.js.map → pbr-renderable-CuKWalEM.js.map} +1 -1
  139. package/{pbr-shadow-fragment-DmnNe6yz.js → pbr-shadow-fragment-waeIBQUq.js} +2 -2
  140. package/{pbr-shadow-fragment-DmnNe6yz.js.map → pbr-shadow-fragment-waeIBQUq.js.map} +1 -1
  141. package/{pbr-tracking-Bo7RTANK.js → pbr-tracking-CdeqbBrh.js} +2 -2
  142. package/{pbr-tracking-Bo7RTANK.js.map → pbr-tracking-CdeqbBrh.js.map} +1 -1
  143. package/{pbr-transmission-ext-CoGcJBGE.js → pbr-transmission-ext-BNiXngZc.js} +2 -2
  144. package/{pbr-transmission-ext-CoGcJBGE.js.map → pbr-transmission-ext-BNiXngZc.js.map} +1 -1
  145. package/{recast-navigation.wasm-DG_0AFuk.js → recast-navigation.wasm-VC4lGlEe.js} +3 -3
  146. package/{recast-navigation.wasm-DG_0AFuk.js.map → recast-navigation.wasm-VC4lGlEe.js.map} +1 -1
  147. package/{recast-navigation.wasm-compat-C-Bf2ylB.js → recast-navigation.wasm-compat-CTwYOzRz.js} +3 -3
  148. package/{recast-navigation.wasm-compat-C-Bf2ylB.js.map → recast-navigation.wasm-compat-CTwYOzRz.js.map} +1 -1
  149. package/{reflectance-fragment-CExe6qDY.js → reflectance-fragment-BQFZ_pgy.js} +2 -2
  150. package/{reflectance-fragment-CExe6qDY.js.map → reflectance-fragment-BQFZ_pgy.js.map} +1 -1
  151. package/{rgbd-decode-DkiiiIlt.js → rgbd-decode-duTlXMWd.js} +2 -2
  152. package/{rgbd-decode-DkiiiIlt.js.map → rgbd-decode-duTlXMWd.js.map} +1 -1
  153. package/{screenshot-readback-avr_tYGZ.js → screenshot-readback-DnxR4rhp.js} +2 -2
  154. package/{screenshot-readback-avr_tYGZ.js.map → screenshot-readback-DnxR4rhp.js.map} +1 -1
  155. package/{shader-composer-CZagsJDS.js → shader-composer-CBy2i8nU.js} +2 -2
  156. package/{shader-composer-CZagsJDS.js.map → shader-composer-CBy2i8nU.js.map} +1 -1
  157. package/{shader-renderable-D5sbgzxt.js → shader-renderable-DVMVD6zP.js} +4 -4
  158. package/{shader-renderable-D5sbgzxt.js.map → shader-renderable-DVMVD6zP.js.map} +1 -1
  159. package/{shader-thin-instance-CkQ8rrfH.js → shader-thin-instance-CsDo3ULk.js} +2 -2
  160. package/{shader-thin-instance-CkQ8rrfH.js.map → shader-thin-instance-CsDo3ULk.js.map} +1 -1
  161. package/{sheen-fragment-BEigjpTX.js → sheen-fragment-B_Jd7wrr.js} +2 -2
  162. package/{sheen-fragment-BEigjpTX.js.map → sheen-fragment-B_Jd7wrr.js.map} +1 -1
  163. package/{singlelight-directional-wgsl-Ccsk-ys3.js → singlelight-directional-wgsl-Bw84txva.js} +2 -2
  164. package/{singlelight-directional-wgsl-Ccsk-ys3.js.map → singlelight-directional-wgsl-Bw84txva.js.map} +1 -1
  165. package/{singlelight-hemispheric-wgsl-DL-jpc97.js → singlelight-hemispheric-wgsl-DjxhgI8r.js} +2 -2
  166. package/{singlelight-hemispheric-wgsl-DL-jpc97.js.map → singlelight-hemispheric-wgsl-DjxhgI8r.js.map} +1 -1
  167. package/{singlelight-point-wgsl-hYmiP6ys.js → singlelight-point-wgsl-iA1aRkXA.js} +2 -2
  168. package/{singlelight-point-wgsl-hYmiP6ys.js.map → singlelight-point-wgsl-iA1aRkXA.js.map} +1 -1
  169. package/{singlelight-spot-wgsl-DSjp1p1C.js → singlelight-spot-wgsl-MDdTdstF.js} +2 -2
  170. package/{singlelight-spot-wgsl-DSjp1p1C.js.map → singlelight-spot-wgsl-MDdTdstF.js.map} +1 -1
  171. package/{skeleton-fragment-B__bUbPK.js → skeleton-fragment-COdHWFcK.js} +2 -2
  172. package/{skeleton-fragment-B__bUbPK.js.map → skeleton-fragment-COdHWFcK.js.map} +1 -1
  173. package/{skybox-renderable-BH6uUkal.js → skybox-renderable-DJYkfw32.js} +2 -2
  174. package/{skybox-renderable-BH6uUkal.js.map → skybox-renderable-DJYkfw32.js.map} +1 -1
  175. package/{splat-ply-compressed-BGNK6dnh.js → splat-ply-compressed-SxMlsKNK.js} +2 -2
  176. package/{splat-ply-compressed-BGNK6dnh.js.map → splat-ply-compressed-SxMlsKNK.js.map} +1 -1
  177. package/{standard-pipeline-BvFynkwL.js → standard-pipeline-DXFOUqU_.js} +3 -3
  178. package/{standard-pipeline-BvFynkwL.js.map → standard-pipeline-DXFOUqU_.js.map} +1 -1
  179. package/{standard-renderable-1Q3zemys.js → standard-renderable-BAc-i-ig.js} +3 -3
  180. package/{standard-renderable-1Q3zemys.js.map → standard-renderable-BAc-i-ig.js.map} +1 -1
  181. package/{std-ambient-fragment-__F1KTEu.js → std-ambient-fragment-P8dHZ4An.js} +2 -2
  182. package/{std-ambient-fragment-__F1KTEu.js.map → std-ambient-fragment-P8dHZ4An.js.map} +1 -1
  183. package/{std-cube-reflection-fragment-DidM0byH.js → std-cube-reflection-fragment-CF03MuQt.js} +2 -2
  184. package/{std-cube-reflection-fragment-DidM0byH.js.map → std-cube-reflection-fragment-CF03MuQt.js.map} +1 -1
  185. package/{std-emissive-fragment-Bj62X4Np.js → std-emissive-fragment-P8yJGclx.js} +2 -2
  186. package/{std-emissive-fragment-Bj62X4Np.js.map → std-emissive-fragment-P8yJGclx.js.map} +1 -1
  187. package/{std-lightmap-fragment-DXvfWvKc.js → std-lightmap-fragment-CymEG79z.js} +9 -6
  188. package/std-lightmap-fragment-CymEG79z.js.map +1 -0
  189. package/{std-opacity-fragment-BzMMb1K_.js → std-opacity-fragment-DLa1zV06.js} +2 -2
  190. package/{std-opacity-fragment-BzMMb1K_.js.map → std-opacity-fragment-DLa1zV06.js.map} +1 -1
  191. package/{std-reflection-fragment-DC9Kvu1C.js → std-reflection-fragment-BLySsYos.js} +2 -2
  192. package/{std-reflection-fragment-DC9Kvu1C.js.map → std-reflection-fragment-BLySsYos.js.map} +1 -1
  193. package/{std-shadow-fragment-BnMHeF1-.js → std-shadow-fragment-C_q27Mdi.js} +2 -2
  194. package/{std-shadow-fragment-BnMHeF1-.js.map → std-shadow-fragment-C_q27Mdi.js.map} +1 -1
  195. package/{std-specular-fragment-Bio681OG.js → std-specular-fragment-CaBXyAWY.js} +2 -2
  196. package/{std-specular-fragment-Bio681OG.js.map → std-specular-fragment-CaBXyAWY.js.map} +1 -1
  197. package/{std-tracking-BTcrry2o.js → std-tracking-Bw61Dv98.js} +2 -2
  198. package/{std-tracking-BTcrry2o.js.map → std-tracking-Bw61Dv98.js.map} +1 -1
  199. package/{subsurface-fragment-DpKib445.js → subsurface-fragment-BNQoG9gr.js} +2 -2
  200. package/{subsurface-fragment-DpKib445.js.map → subsurface-fragment-BNQoG9gr.js.map} +1 -1
  201. package/{thin-instance-cull-binding-DwZi7mlE.js → thin-instance-cull-binding-BNC5JiGw.js} +3 -3
  202. package/{thin-instance-cull-binding-DwZi7mlE.js.map → thin-instance-cull-binding-BNC5JiGw.js.map} +1 -1
  203. package/{thin-instance-gpu-uY2NOv0J.js → thin-instance-gpu-C1DGstap.js} +2 -2
  204. package/{thin-instance-gpu-uY2NOv0J.js.map → thin-instance-gpu-C1DGstap.js.map} +1 -1
  205. package/{tracking-primitives-Ck5bgCuo.js → tracking-primitives-CMBWLxGr.js} +2 -2
  206. package/{tracking-primitives-Ck5bgCuo.js.map → tracking-primitives-CMBWLxGr.js.map} +1 -1
  207. package/{unlit-fragment-nc6hu3Mw.js → unlit-fragment-BsHrS9XX.js} +2 -2
  208. package/{unlit-fragment-nc6hu3Mw.js.map → unlit-fragment-BsHrS9XX.js.map} +1 -1
  209. package/gltf-interleave-DWf27t-h.js.map +0 -1
  210. package/gltf-normals-b2h74380.js.map +0 -1
  211. package/index-C-tEgwbZ.js.map +0 -1
  212. package/std-lightmap-fragment-DXvfWvKc.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"subsurface-fragment-DpKib445.js","sources":["../src/material/pbr/fragments/subsurface-fragment.ts"],"sourcesContent":["/**\n * Subsurface Fragment\n *\n * Adds translucency — light passing through thin surfaces.\n * Only bundled when a scene uses PbrMaterialProps.subsurface.\n *\n * Math follows BJS PBRSubSurfaceConfiguration:\n * - Burley transmittance BRDF: exp-based approximation\n * - Thickness from texture (.g channel, BJS glTF-style default)\n * - Direct: wrap-around diffuse scaled by transmittance\n * - IBL: irradiance reduced by (1 - intensity), transmittance-weighted contribution added\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { Texture2D } from \"../../../texture/texture-2d.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP, PBR2_HAS_THICKNESS_GLTF_CHANNEL } from \"../pbr-flag-bits.js\";\n\nconst SS_HELPERS = `\nfn transmittanceBRDF_Burley(tintColor: vec3<f32>, diffusionDistance: vec3<f32>, thickness: f32) -> vec3<f32> {\nlet S = 1.0 / max(vec3<f32>(0.000001), diffusionDistance);\nlet temp = exp((-0.333333333 * thickness) * S);\nreturn tintColor * 0.25 * (temp * temp * temp + 3.0 * temp);\n}\nfn computeWrappedDiffuseNdotL(NdotL: f32, w: f32) -> f32 {\nlet t = 1.0 + w;\nlet invt2 = 1.0 / (t * t);\nreturn saturate((NdotL + w) * invt2);\n}\n`;\n\n// SV: declare subsurface scope variables\nconst SS_SCOPE_VARS = `var translucencyDirect = vec3<f32>(0.0);\nvar ssTransmittance = vec3<f32>(0.0);\nvar ssIntensity = 0.0;`;\n\n// AT: sample thickness + compute transmittance.\n// Channel: R by default (matches existing non-glTF path); G when the glTF\n// KHR_materials_volume flag is on (spec mandates G channel).\nfunction makeThicknessBlock(hasThicknessMap: boolean, useGltfChannel: boolean): string {\n const chan = useGltfChannel ? \"g\" : \"r\";\n const texSample = hasThicknessMap ? `let thicknessSample = textureSample(thicknessTexture_, thicknessSampler_, input.uv).${chan};` : `let thicknessSample = 1.0;`;\n return `${texSample}\nlet ssThickness = max(material.subsurfaceParams.y + thicknessSample * material.subsurfaceParams.z, 0.000001);\nlet ssTranslucencyColor = material.subsurfaceParams3.rgb;\nlet ssDiffDist = material.subsurfaceParams2.rgb;\nssIntensity = material.subsurfaceParams.x;\nssTransmittance = transmittanceBRDF_Burley(ssTranslucencyColor, ssDiffDist, ssThickness) * ssIntensity;`;\n}\n\n// AD: direct-light translucency lobe (back-facing only, wrap 0.02, 1/PI diffuse BRDF).\n// BJS also scales the front-facing direct diffuse by (1 - ssIntensity); we cannot easily\n// modify `directDiffuse` at compute time, so compensate via `color -= directDiffuse * ssIntensity`\n// in the AI/NI slot below.\nconst SS_DIRECT = `{\nlet NdotLU = dot(N, L);\nif (NdotLU < 0.0) {\nlet wrapNdotL = computeWrappedDiffuseNdotL(abs(NdotLU), 0.02);\ntranslucencyDirect += (1.0 / PI) * wrapNdotL * ssTransmittance * lightAtten * lightColor * material.directIntensity;\n}\n}`;\n\n// AI: subsurface IBL modification (runs after IBL sets `color`).\n// BJS: finalIrradiance *= (1 - ssI); finalIrradiance += refractionIrradiance;\n// where refractionIrradiance = environmentIrradiance(-N) * transmittance (no albedo by default).\n// AO/occlusion applies to the full finalIrradiance in BJS.\n// Also: scale direct diffuse by (1-ssI) and add translucencyDirect lobe.\nconst SS_IBL_MOD = `{\nlet N_back = -N_env;\nlet envIrrBack = (scene.vSphericalL00.rgb\n + scene.vSphericalL1_1.rgb * N_back.y + scene.vSphericalL10.rgb * N_back.z + scene.vSphericalL11.rgb * N_back.x\n + scene.vSphericalL2_2.rgb * (N_back.y * N_back.x) + scene.vSphericalL2_1.rgb * (N_back.y * N_back.z)\n + scene.vSphericalL20.rgb * (3.0 * N_back.z * N_back.z - 1.0) + scene.vSphericalL21.rgb * (N_back.z * N_back.x)\n + scene.vSphericalL22.rgb * (N_back.x * N_back.x - N_back.y * N_back.y)) * material.environmentIntensity;\nlet refractionIrradiance = envIrrBack * ssTransmittance;\ncolor -= finalIrradiance * ssIntensity;\ncolor += refractionIrradiance * occlusion;\ncolor -= directDiffuse * ssIntensity;\ncolor += translucencyDirect * occlusion;\n}`;\n\n// NI: no-IBL path — just scale direct diffuse and add translucency lobe.\nconst SS_NO_IBL_MOD = `color -= directDiffuse * ssIntensity;\ncolor += translucencyDirect;`;\n\nconst STAGE_FRAGMENT = 0x2;\n\n/**\n * Create a subsurface translucency fragment.\n * @param hasThicknessMap - Whether the material has a thickness texture.\n * @param hasIbl - Whether the scene has IBL.\n * @param useGltfThicknessChannel - Sample the thickness texture's G channel\n * (KHR_materials_volume) instead of R (BJS default).\n */\nexport function createSubsurfaceFragment(hasThicknessMap: boolean, hasIbl: boolean, useGltfThicknessChannel: boolean): ShaderFragment {\n const bindings = hasThicknessMap\n ? [\n { _name: \"thicknessTexture_\", _type: { _kind: \"texture\" as const, _textureType: \"texture_2d<f32>\" as const }, _visibility: STAGE_FRAGMENT },\n { _name: \"thicknessSampler_\", _type: { _kind: \"sampler\" as const, _samplerType: \"sampler\" as const }, _visibility: STAGE_FRAGMENT },\n ]\n : [];\n\n const slots: Partial<Record<string, string>> = {\n SV: SS_SCOPE_VARS,\n AT: makeThicknessBlock(hasThicknessMap, useGltfThicknessChannel),\n AD: SS_DIRECT,\n };\n if (hasIbl) {\n slots.AI = SS_IBL_MOD;\n } else {\n slots.NI = SS_NO_IBL_MOD;\n }\n\n const deps: string[] = [];\n if (hasIbl) {\n deps.push(\"ibl\");\n }\n\n return {\n _id: \"subsurface\",\n _dependencies: deps.length > 0 ? deps : undefined,\n _bindings: bindings.length > 0 ? bindings : undefined,\n _uboFields: [\n { _name: \"subsurfaceParams\", _type: \"vec4<f32>\" as const },\n { _name: \"subsurfaceParams2\", _type: \"vec4<f32>\" as const },\n { _name: \"subsurfaceParams3\", _type: \"vec4<f32>\" as const },\n ],\n _helperFunctions: SS_HELPERS,\n _fragmentSlots: slots,\n };\n}\n\n/** Write subsurface UBO data. Called from pbr-renderable.ts only when subsurface is active. */\nexport function writeSubsurfaceUBO(data: Float32Array, ss: SubSurfaceProps, offsets: ReadonlyMap<string, number>): void {\n const trans = ss.translucency!;\n const thick = ss.thickness;\n\n const off = offsets.get(\"subsurfaceParams\")! / 4;\n data[off] = trans.intensity ?? 1.0;\n const minThick = thick?.min ?? 0;\n const maxThick = thick?.max ?? 1.0;\n data[off + 1] = minThick;\n data[off + 2] = maxThick - minThick;\n\n const off2 = offsets.get(\"subsurfaceParams2\")! / 4;\n const dd = trans.diffusionDistance ?? [1, 1, 1];\n data[off2] = dd[0]!;\n data[off2 + 1] = dd[1]!;\n data[off2 + 2] = dd[2]!;\n\n const off3 = offsets.get(\"subsurfaceParams3\")! / 4;\n const tc = trans.color ?? [1, 1, 1];\n data[off3] = tc[0]!;\n data[off3 + 1] = tc[1]!;\n data[off3 + 2] = tc[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"subsurface\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as PbrMaterialProps;\n if (!m.subsurface?.translucency) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SUBSURFACE;\n let f2 = 0;\n if (m.subsurface.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (m.subsurface.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SUBSURFACE)) {\n return null;\n }\n return createSubsurfaceFragment((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0, ctx._hasIbl, (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0);\n },\n writeUbo(data, mat, offsets) {\n const m = mat as PbrMaterialProps;\n if (m.subsurface?.translucency && offsets.has(\"subsurfaceParams\")) {\n writeSubsurfaceUBO(data, m.subsurface as SubSurfaceProps, offsets);\n }\n },\n bind(ctx, entries, b) {\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const tex = (ctx._material as PbrMaterialProps).subsurface?.thickness?.texture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n return b;\n },\n textures(mat, out) {\n const t = (mat as PbrMaterialProps).subsurface?.thickness?.texture;\n if (t) {\n out.push(t);\n }\n },\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subsurface-fragment-BNQoG9gr.js","sources":["../src/material/pbr/fragments/subsurface-fragment.ts"],"sourcesContent":["/**\n * Subsurface Fragment\n *\n * Adds translucency — light passing through thin surfaces.\n * Only bundled when a scene uses PbrMaterialProps.subsurface.\n *\n * Math follows BJS PBRSubSurfaceConfiguration:\n * - Burley transmittance BRDF: exp-based approximation\n * - Thickness from texture (.g channel, BJS glTF-style default)\n * - Direct: wrap-around diffuse scaled by transmittance\n * - IBL: irradiance reduced by (1 - intensity), transmittance-weighted contribution added\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { Texture2D } from \"../../../texture/texture-2d.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP, PBR2_HAS_THICKNESS_GLTF_CHANNEL } from \"../pbr-flag-bits.js\";\n\nconst SS_HELPERS = `\nfn transmittanceBRDF_Burley(tintColor: vec3<f32>, diffusionDistance: vec3<f32>, thickness: f32) -> vec3<f32> {\nlet S = 1.0 / max(vec3<f32>(0.000001), diffusionDistance);\nlet temp = exp((-0.333333333 * thickness) * S);\nreturn tintColor * 0.25 * (temp * temp * temp + 3.0 * temp);\n}\nfn computeWrappedDiffuseNdotL(NdotL: f32, w: f32) -> f32 {\nlet t = 1.0 + w;\nlet invt2 = 1.0 / (t * t);\nreturn saturate((NdotL + w) * invt2);\n}\n`;\n\n// SV: declare subsurface scope variables\nconst SS_SCOPE_VARS = `var translucencyDirect = vec3<f32>(0.0);\nvar ssTransmittance = vec3<f32>(0.0);\nvar ssIntensity = 0.0;`;\n\n// AT: sample thickness + compute transmittance.\n// Channel: R by default (matches existing non-glTF path); G when the glTF\n// KHR_materials_volume flag is on (spec mandates G channel).\nfunction makeThicknessBlock(hasThicknessMap: boolean, useGltfChannel: boolean): string {\n const chan = useGltfChannel ? \"g\" : \"r\";\n const texSample = hasThicknessMap ? `let thicknessSample = textureSample(thicknessTexture_, thicknessSampler_, input.uv).${chan};` : `let thicknessSample = 1.0;`;\n return `${texSample}\nlet ssThickness = max(material.subsurfaceParams.y + thicknessSample * material.subsurfaceParams.z, 0.000001);\nlet ssTranslucencyColor = material.subsurfaceParams3.rgb;\nlet ssDiffDist = material.subsurfaceParams2.rgb;\nssIntensity = material.subsurfaceParams.x;\nssTransmittance = transmittanceBRDF_Burley(ssTranslucencyColor, ssDiffDist, ssThickness) * ssIntensity;`;\n}\n\n// AD: direct-light translucency lobe (back-facing only, wrap 0.02, 1/PI diffuse BRDF).\n// BJS also scales the front-facing direct diffuse by (1 - ssIntensity); we cannot easily\n// modify `directDiffuse` at compute time, so compensate via `color -= directDiffuse * ssIntensity`\n// in the AI/NI slot below.\nconst SS_DIRECT = `{\nlet NdotLU = dot(N, L);\nif (NdotLU < 0.0) {\nlet wrapNdotL = computeWrappedDiffuseNdotL(abs(NdotLU), 0.02);\ntranslucencyDirect += (1.0 / PI) * wrapNdotL * ssTransmittance * lightAtten * lightColor * material.directIntensity;\n}\n}`;\n\n// AI: subsurface IBL modification (runs after IBL sets `color`).\n// BJS: finalIrradiance *= (1 - ssI); finalIrradiance += refractionIrradiance;\n// where refractionIrradiance = environmentIrradiance(-N) * transmittance (no albedo by default).\n// AO/occlusion applies to the full finalIrradiance in BJS.\n// Also: scale direct diffuse by (1-ssI) and add translucencyDirect lobe.\nconst SS_IBL_MOD = `{\nlet N_back = -N_env;\nlet envIrrBack = (scene.vSphericalL00.rgb\n + scene.vSphericalL1_1.rgb * N_back.y + scene.vSphericalL10.rgb * N_back.z + scene.vSphericalL11.rgb * N_back.x\n + scene.vSphericalL2_2.rgb * (N_back.y * N_back.x) + scene.vSphericalL2_1.rgb * (N_back.y * N_back.z)\n + scene.vSphericalL20.rgb * (3.0 * N_back.z * N_back.z - 1.0) + scene.vSphericalL21.rgb * (N_back.z * N_back.x)\n + scene.vSphericalL22.rgb * (N_back.x * N_back.x - N_back.y * N_back.y)) * material.environmentIntensity;\nlet refractionIrradiance = envIrrBack * ssTransmittance;\ncolor -= finalIrradiance * ssIntensity;\ncolor += refractionIrradiance * occlusion;\ncolor -= directDiffuse * ssIntensity;\ncolor += translucencyDirect * occlusion;\n}`;\n\n// NI: no-IBL path — just scale direct diffuse and add translucency lobe.\nconst SS_NO_IBL_MOD = `color -= directDiffuse * ssIntensity;\ncolor += translucencyDirect;`;\n\nconst STAGE_FRAGMENT = 0x2;\n\n/**\n * Create a subsurface translucency fragment.\n * @param hasThicknessMap - Whether the material has a thickness texture.\n * @param hasIbl - Whether the scene has IBL.\n * @param useGltfThicknessChannel - Sample the thickness texture's G channel\n * (KHR_materials_volume) instead of R (BJS default).\n */\nexport function createSubsurfaceFragment(hasThicknessMap: boolean, hasIbl: boolean, useGltfThicknessChannel: boolean): ShaderFragment {\n const bindings = hasThicknessMap\n ? [\n { _name: \"thicknessTexture_\", _type: { _kind: \"texture\" as const, _textureType: \"texture_2d<f32>\" as const }, _visibility: STAGE_FRAGMENT },\n { _name: \"thicknessSampler_\", _type: { _kind: \"sampler\" as const, _samplerType: \"sampler\" as const }, _visibility: STAGE_FRAGMENT },\n ]\n : [];\n\n const slots: Partial<Record<string, string>> = {\n SV: SS_SCOPE_VARS,\n AT: makeThicknessBlock(hasThicknessMap, useGltfThicknessChannel),\n AD: SS_DIRECT,\n };\n if (hasIbl) {\n slots.AI = SS_IBL_MOD;\n } else {\n slots.NI = SS_NO_IBL_MOD;\n }\n\n const deps: string[] = [];\n if (hasIbl) {\n deps.push(\"ibl\");\n }\n\n return {\n _id: \"subsurface\",\n _dependencies: deps.length > 0 ? deps : undefined,\n _bindings: bindings.length > 0 ? bindings : undefined,\n _uboFields: [\n { _name: \"subsurfaceParams\", _type: \"vec4<f32>\" as const },\n { _name: \"subsurfaceParams2\", _type: \"vec4<f32>\" as const },\n { _name: \"subsurfaceParams3\", _type: \"vec4<f32>\" as const },\n ],\n _helperFunctions: SS_HELPERS,\n _fragmentSlots: slots,\n };\n}\n\n/** Write subsurface UBO data. Called from pbr-renderable.ts only when subsurface is active. */\nexport function writeSubsurfaceUBO(data: Float32Array, ss: SubSurfaceProps, offsets: ReadonlyMap<string, number>): void {\n const trans = ss.translucency!;\n const thick = ss.thickness;\n\n const off = offsets.get(\"subsurfaceParams\")! / 4;\n data[off] = trans.intensity ?? 1.0;\n const minThick = thick?.min ?? 0;\n const maxThick = thick?.max ?? 1.0;\n data[off + 1] = minThick;\n data[off + 2] = maxThick - minThick;\n\n const off2 = offsets.get(\"subsurfaceParams2\")! / 4;\n const dd = trans.diffusionDistance ?? [1, 1, 1];\n data[off2] = dd[0]!;\n data[off2 + 1] = dd[1]!;\n data[off2 + 2] = dd[2]!;\n\n const off3 = offsets.get(\"subsurfaceParams3\")! / 4;\n const tc = trans.color ?? [1, 1, 1];\n data[off3] = tc[0]!;\n data[off3 + 1] = tc[1]!;\n data[off3 + 2] = tc[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"subsurface\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as PbrMaterialProps;\n if (!m.subsurface?.translucency) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SUBSURFACE;\n let f2 = 0;\n if (m.subsurface.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (m.subsurface.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SUBSURFACE)) {\n return null;\n }\n return createSubsurfaceFragment((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0, ctx._hasIbl, (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0);\n },\n writeUbo(data, mat, offsets) {\n const m = mat as PbrMaterialProps;\n if (m.subsurface?.translucency && offsets.has(\"subsurfaceParams\")) {\n writeSubsurfaceUBO(data, m.subsurface as SubSurfaceProps, offsets);\n }\n },\n bind(ctx, entries, b) {\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const tex = (ctx._material as PbrMaterialProps).subsurface?.thickness?.texture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n return b;\n },\n textures(mat, out) {\n const t = (mat as PbrMaterialProps).subsurface?.thickness?.texture;\n if (t) {\n out.push(t);\n }\n },\n};\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { B as BU, bQ as getViewProjectionMatrix, U as U32, a as F32 } from "./index-C-tEgwbZ.js";
2
- import { syncThinInstanceGpuData } from "./thin-instance-gpu-uY2NOv0J.js";
1
+ import { B as BU, bS as getViewProjectionMatrix, U as U32, a as F32 } from "./index-BgY3QEzL.js";
2
+ import { syncThinInstanceGpuData } from "./thin-instance-gpu-C1DGstap.js";
3
3
  const WORKGROUP_SIZE = 64;
4
4
  const PARAM_BYTES = 192;
5
5
  const COUNT_U32_OFFSET = 44;
@@ -307,4 +307,4 @@ function tryBind(renderable, scene, mesh, engine, hasColor, excluded, baseUpdate
307
307
  export {
308
308
  tryBind
309
309
  };
310
- //# sourceMappingURL=thin-instance-cull-binding-DwZi7mlE.js.map
310
+ //# sourceMappingURL=thin-instance-cull-binding-BNC5JiGw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thin-instance-cull-binding-DwZi7mlE.js","sources":["../src/mesh/thin-instance-gpu-culling.ts","../src/mesh/thin-instance-cull-binding.ts"],"sourcesContent":["/** GPU frustum culling for opt-in thin instances.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling.\n * Each render binding owns its own state so render tasks with different cameras\n * never clobber one another's compacted instance buffers or indirect args.\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DrawUpdateContext } from \"../render/renderable.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh, MeshGPU } from \"./mesh.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport { syncThinInstanceGpuData } from \"./thin-instance-gpu.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\n\nconst WORKGROUP_SIZE = 64;\nconst PARAM_BYTES = 192;\nconst COUNT_U32_OFFSET = 44;\nconst MESH_WORLD_FLOAT_OFFSET = 24;\nconst LOCAL_SPHERE_FLOAT_OFFSET = 40;\nconst INDIRECT_ARGS_BYTES = 20;\n\nconst CULL_WGSL_NO_COLOR = /* wgsl */ `\nstruct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32};\n@group(0)@binding(0)var<storage,read> srcMatrices:array<mat4x4<f32>>;\n@group(0)@binding(1)var<storage,read_write> dstMatrices:array<mat4x4<f32>>;\n@group(0)@binding(2)var<storage,read_write> args:array<atomic<u32>>;\n@group(0)@binding(3)var<uniform> params:CullParams;\nfn visible(world:mat4x4<f32>)->bool{\nlet center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;\nlet sx=length(world[0].xyz);\nlet sy=length(world[1].xyz);\nlet sz=length(world[2].xyz);\nlet radius=params.localSphere.w*max(max(sx,sy),sz)+0.0001;\nfor(var i=0u;i<6u;i++){\nlet p=params.planes[i];\nif(dot(p.xyz,center)+p.w < -radius){return false;}\n}\nreturn true;\n}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\n}`;\n\nconst CULL_WGSL_COLOR = `${CULL_WGSL_NO_COLOR}\n@group(0)@binding(4)var<storage,read> srcColors:array<vec4<f32>>;\n@group(0)@binding(5)var<storage,read_write> dstColors:array<vec4<f32>>;\n@compute @workgroup_size(64)\nfn mainColor(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\ndstColors[outIndex]=srcColors[i];\n}`;\n\n/** Per-render-binding GPU culling state. */\nexport interface ThinInstanceGpuCullState {\n /** @internal */\n _capacity: number;\n /** @internal */\n _visibleMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _visibleColorBuffer: GPUBuffer | null;\n /** @internal */\n _argsBuffer: GPUBuffer | null;\n /** @internal */\n _paramsBuffer: GPUBuffer | null;\n /** @internal */\n _bindGroup: GPUBindGroup | null;\n /** @internal */\n _srcMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _srcColorBuffer: GPUBuffer | null;\n /** @internal */\n _hasColor: boolean;\n /** @internal */\n _localSphereReady: boolean;\n /** @internal */\n _localSphere: Float32Array;\n /** @internal */\n _paramsBytes: ArrayBuffer;\n /** @internal */\n _paramsF32: Float32Array;\n /** @internal */\n _paramsU32: Uint32Array;\n /** @internal */\n _argsData: Uint32Array;\n /** @internal */\n _drawBuffers: ThinInstanceDrawBuffers | null;\n}\n\n/** Result consumed by a material draw closure after culling has run for the active pass. */\nexport interface ThinInstanceGpuCullResult {\n readonly drawBuffers: ThinInstanceDrawBuffers;\n readonly argsBuffer: GPUBuffer;\n}\n\nlet _cachedDevice: GPUDevice | null = null;\nlet _pipelineNoColor: GPUComputePipeline | null = null;\nlet _pipelineColor: GPUComputePipeline | null = null;\n\n/** Create per-binding culling state. */\nexport function createTiCullState(): ThinInstanceGpuCullState {\n const paramsBytes = new ArrayBuffer(PARAM_BYTES);\n return {\n _capacity: 0,\n _visibleMatrixBuffer: null,\n _visibleColorBuffer: null,\n _argsBuffer: null,\n _paramsBuffer: null,\n _bindGroup: null,\n _srcMatrixBuffer: null,\n _srcColorBuffer: null,\n _hasColor: false,\n _localSphereReady: false,\n _localSphere: new F32(4),\n _paramsBytes: paramsBytes,\n _paramsF32: new F32(paramsBytes),\n _paramsU32: new U32(paramsBytes),\n _argsData: new U32(5),\n _drawBuffers: null,\n };\n}\n\n/** Destroy GPU resources owned by a per-binding cull state. */\nexport function destroyTiCullState(state: ThinInstanceGpuCullState): void {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._argsBuffer?.destroy();\n state._paramsBuffer?.destroy();\n state._visibleMatrixBuffer = null;\n state._visibleColorBuffer = null;\n state._argsBuffer = null;\n state._paramsBuffer = null;\n state._bindGroup = null;\n state._drawBuffers = null;\n}\n\n/** Run culling for one render binding and return buffers for the subsequent indirect draw. */\nexport function prepareTiCull(\n engine: EngineContext,\n state: ThinInstanceGpuCullState,\n mesh: Mesh,\n gpu: MeshGPU,\n ti: ThinInstanceData,\n hasColor: boolean,\n context: DrawUpdateContext\n): ThinInstanceGpuCullResult | null {\n const camera = context._camera;\n if (!ti._gpuCullingEnabled || !camera || mesh.visible === false || ti.count === 0) {\n state._drawBuffers = null;\n return null;\n }\n if (hasColor && !ti.colors) {\n state._drawBuffers = null;\n return null;\n }\n if (!state._localSphereReady && !computeLocalSphere(mesh as Mesh, state._localSphere)) {\n state._drawBuffers = null;\n return null;\n }\n state._localSphereReady = true;\n\n syncThinInstanceGpuData(engine, ti, hasColor);\n const sourceMatrixBuffer = ti._gpuBuffer;\n const sourceColorBuffer = hasColor ? ti._colorGpuBuffer : null;\n if (!sourceMatrixBuffer || (hasColor && !sourceColorBuffer)) {\n state._drawBuffers = null;\n return null;\n }\n\n ensureCullBuffers(engine, state, ti._capacity, hasColor);\n const visibleMatrixBuffer = state._visibleMatrixBuffer!;\n const visibleColorBuffer = hasColor ? state._visibleColorBuffer! : null;\n const argsBuffer = state._argsBuffer!;\n const paramsBuffer = state._paramsBuffer!;\n const pipeline = getCullPipeline(engine, hasColor);\n\n if (state._bindGroup === null || state._srcMatrixBuffer !== sourceMatrixBuffer || state._srcColorBuffer !== sourceColorBuffer || state._hasColor !== hasColor) {\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: sourceMatrixBuffer } },\n { binding: 1, resource: { buffer: visibleMatrixBuffer } },\n { binding: 2, resource: { buffer: argsBuffer } },\n { binding: 3, resource: { buffer: paramsBuffer } },\n ];\n if (hasColor) {\n entries.push({ binding: 4, resource: { buffer: sourceColorBuffer! } }, { binding: 5, resource: { buffer: visibleColorBuffer! } });\n }\n state._bindGroup = engine._device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries });\n state._srcMatrixBuffer = sourceMatrixBuffer;\n state._srcColorBuffer = sourceColorBuffer;\n state._hasColor = hasColor;\n }\n\n const v = camera.viewport;\n const aspect = (context.targetWidth / context.targetHeight) * (v ? v.width / v.height : 1);\n writeCullParams(engine, state, mesh, gpu.indexCount, ti.count, camera, aspect);\n\n const pass = engine._currentEncoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, state._bindGroup);\n pass.dispatchWorkgroups(Math.ceil(ti.count / WORKGROUP_SIZE));\n pass.end();\n\n state._drawBuffers = { matrixBuffer: visibleMatrixBuffer, colorBuffer: visibleColorBuffer };\n return { drawBuffers: state._drawBuffers, argsBuffer };\n}\n\nfunction ensureCullBuffers(engine: EngineContext, state: ThinInstanceGpuCullState, capacity: number, hasColor: boolean): void {\n const device = engine._device;\n if (state._capacity < capacity) {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._visibleMatrixBuffer = device.createBuffer({\n size: Math.max(capacity * 64, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._visibleColorBuffer = hasColor\n ? device.createBuffer({\n size: Math.max(capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n })\n : null;\n state._capacity = capacity;\n state._bindGroup = null;\n state._drawBuffers = null;\n } else if (hasColor && !state._visibleColorBuffer) {\n state._visibleColorBuffer = device.createBuffer({\n size: Math.max(state._capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._bindGroup = null;\n state._drawBuffers = null;\n }\n if (!state._argsBuffer) {\n state._argsBuffer = device.createBuffer({\n size: INDIRECT_ARGS_BYTES,\n usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST,\n });\n }\n if (!state._paramsBuffer) {\n state._paramsBuffer = device.createBuffer({\n size: PARAM_BYTES,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n }\n}\n\nfunction getCullPipeline(engine: EngineContext, hasColor: boolean): GPUComputePipeline {\n const device = engine._device;\n if (_cachedDevice !== device) {\n _cachedDevice = device;\n _pipelineNoColor = null;\n _pipelineColor = null;\n }\n if (hasColor) {\n _pipelineColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_COLOR }), entryPoint: \"mainColor\" },\n });\n return _pipelineColor;\n }\n _pipelineNoColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_NO_COLOR }), entryPoint: \"main\" },\n });\n return _pipelineNoColor;\n}\n\nfunction writeCullParams(engine: EngineContext, state: ThinInstanceGpuCullState, mesh: Mesh, indexCount: number, instanceCount: number, camera: Camera, aspect: number): void {\n const params = state._paramsF32;\n const viewProjection = getViewProjectionMatrix(camera, aspect);\n writeFrustumPlanes(params, viewProjection);\n params.set(mesh.worldMatrix, MESH_WORLD_FLOAT_OFFSET);\n params.set(state._localSphere, LOCAL_SPHERE_FLOAT_OFFSET);\n state._paramsU32[COUNT_U32_OFFSET] = instanceCount;\n\n const args = state._argsData;\n args[0] = indexCount;\n args[1] = 0;\n args[2] = 0;\n args[3] = 0;\n args[4] = 0;\n\n engine._device.queue.writeBuffer(state._argsBuffer!, 0, args.buffer, args.byteOffset, args.byteLength);\n engine._device.queue.writeBuffer(state._paramsBuffer!, 0, state._paramsBytes);\n}\n\nfunction writeFrustumPlanes(out: Float32Array, m: Mat4): void {\n writePlane(out, 0, m[3]! + m[0]!, m[7]! + m[4]!, m[11]! + m[8]!, m[15]! + m[12]!);\n writePlane(out, 4, m[3]! - m[0]!, m[7]! - m[4]!, m[11]! - m[8]!, m[15]! - m[12]!);\n writePlane(out, 8, m[3]! + m[1]!, m[7]! + m[5]!, m[11]! + m[9]!, m[15]! + m[13]!);\n writePlane(out, 12, m[3]! - m[1]!, m[7]! - m[5]!, m[11]! - m[9]!, m[15]! - m[13]!);\n writePlane(out, 16, m[2]!, m[6]!, m[10]!, m[14]!);\n writePlane(out, 20, m[3]! - m[2]!, m[7]! - m[6]!, m[11]! - m[10]!, m[15]! - m[14]!);\n}\n\nfunction writePlane(out: Float32Array, offset: number, x: number, y: number, z: number, w: number): void {\n const invLen = 1 / Math.hypot(x, y, z);\n out[offset] = x * invLen;\n out[offset + 1] = y * invLen;\n out[offset + 2] = z * invLen;\n out[offset + 3] = w * invLen;\n}\n\nfunction computeLocalSphere(mesh: Mesh, out: Float32Array): boolean {\n const positions = mesh._cpuPositions;\n if (!positions || positions.length < 3) {\n return false;\n }\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < positions.length; i += 3) {\n const x = positions[i]!;\n const y = positions[i + 1]!;\n const z = positions[i + 2]!;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n if (!isFinite(minX)) {\n return false;\n }\n const cx = (minX + maxX) * 0.5;\n const cy = (minY + maxY) * 0.5;\n const cz = (minZ + maxZ) * 0.5;\n const dx = maxX - cx;\n const dy = maxY - cy;\n const dz = maxZ - cz;\n out[0] = cx;\n out[1] = cy;\n out[2] = cz;\n out[3] = Math.hypot(dx, dy, dz);\n return true;\n}\n","/** Shared per-binding GPU frustum-culling lifecycle for thin-instanced renderables.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling, and\n * it statically pulls in the compute-cull module — so non-culling scenes fetch\n * neither this helper nor `thin-instance-gpu-culling.ts`.\n *\n * Factored here so Standard, PBR, and ShaderMaterial renderables share one\n * implementation of the cull lifecycle instead of copy-pasting it three times.\n * `tryBind` is the single seam a renderable's `bind()` calls: it does the\n * opaque-only gate + per-mesh `_gpuCullingEnabled` check, marks the renderable\n * `_direct` (read by the render task's buildBindings right after `bind()`\n * returns), and creates the per-binding state. The renderable then reads\n * `cullDrawBufs` for the compacted instance source and calls `binding.draw(...)`\n * for the indirect-vs-fallback draw call. Keeping these few seams tiny is what\n * lets non-culling scenes — which still fetch the per-material renderable\n * chunks — stay within their bundle-size ceilings. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { SceneContext } from \"../scene/scene.js\";\nimport type { DrawUpdateContext, Renderable } from \"../render/renderable.js\";\nimport type { Mesh } from \"./mesh.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\nimport { createTiCullState, destroyTiCullState, prepareTiCull } from \"./thin-instance-gpu-culling.js\";\n\n/** Per-binding cull lifecycle. The renderable's `bind()` obtains one from\n * `tryBind`, uses `update` as the binding's update, reads `cullDrawBufs` (the\n * compacted instance source) and calls `draw()` for the final draw call. */\nexport interface TiCullBinding {\n /** Run the binding's base update, then dispatch the compute cull pass and stash the result. */\n update(context: DrawUpdateContext): void;\n /** Compacted visible-instance buffers, or null to fall back to a full instanced draw. */\n cullDrawBufs: ThinInstanceDrawBuffers | null;\n /** @internal Indirect draw-args buffer (null until/unless culling ran this frame). */\n _args: GPUBuffer | null;\n /** Issue the indirect (culled) draw when visible instances were compacted, else a full instanced draw. */\n draw(pass: GPURenderPassEncoder | GPURenderBundleEncoder, indexCount: number, instanceCount: number): void;\n}\n\n/** Create a per-binding cull lifecycle for one thin-instanced renderable binding,\n * iff the mesh opts in and is not excluded (transparent / transmissive — v1 is\n * opaque-only). Marks the renderable `_direct` so it leaves the cached opaque\n * bundle; this is safe to do during `bind()` because buildBindings reads\n * `_direct` only after `bind()` returns. Returns undefined when culling does not\n * apply, so the caller falls back to a normal instanced draw. */\nexport function tryBind(\n renderable: Renderable,\n scene: SceneContext,\n mesh: Mesh,\n engine: EngineContext,\n hasColor: boolean,\n excluded: boolean,\n baseUpdate: ((context: DrawUpdateContext) => void) | undefined\n): TiCullBinding | undefined {\n const ti = mesh.thinInstances;\n if (excluded || !ti?._gpuCullingEnabled) {\n return undefined;\n }\n (renderable as { _direct?: boolean })._direct = true;\n const state = createTiCullState();\n scene._meshDisposables.get(mesh)?.push(() => {\n destroyTiCullState(state);\n });\n const binding: TiCullBinding = {\n cullDrawBufs: null,\n _args: null,\n update(context: DrawUpdateContext): void {\n baseUpdate?.(context);\n const res = prepareTiCull(engine, state, mesh, mesh._gpu, ti, hasColor, context);\n binding.cullDrawBufs = res?.drawBuffers ?? null;\n binding._args = res?.argsBuffer ?? null;\n },\n draw(pass: GPURenderPassEncoder | GPURenderBundleEncoder, indexCount: number, instanceCount: number): void {\n if (binding._args) {\n pass.drawIndexedIndirect(binding._args, 0);\n } else {\n pass.drawIndexed(indexCount, instanceCount);\n }\n },\n };\n return binding;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"thin-instance-cull-binding-BNC5JiGw.js","sources":["../src/mesh/thin-instance-gpu-culling.ts","../src/mesh/thin-instance-cull-binding.ts"],"sourcesContent":["/** GPU frustum culling for opt-in thin instances.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling.\n * Each render binding owns its own state so render tasks with different cameras\n * never clobber one another's compacted instance buffers or indirect args.\n */\n\nimport { F32, U32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport { getViewProjectionMatrix } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DrawUpdateContext } from \"../render/renderable.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Mesh, MeshGPU } from \"./mesh.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport { syncThinInstanceGpuData } from \"./thin-instance-gpu.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\n\nconst WORKGROUP_SIZE = 64;\nconst PARAM_BYTES = 192;\nconst COUNT_U32_OFFSET = 44;\nconst MESH_WORLD_FLOAT_OFFSET = 24;\nconst LOCAL_SPHERE_FLOAT_OFFSET = 40;\nconst INDIRECT_ARGS_BYTES = 20;\n\nconst CULL_WGSL_NO_COLOR = /* wgsl */ `\nstruct CullParams{planes:array<vec4<f32>,6>,meshWorld:mat4x4<f32>,localSphere:vec4<f32>,count:u32};\n@group(0)@binding(0)var<storage,read> srcMatrices:array<mat4x4<f32>>;\n@group(0)@binding(1)var<storage,read_write> dstMatrices:array<mat4x4<f32>>;\n@group(0)@binding(2)var<storage,read_write> args:array<atomic<u32>>;\n@group(0)@binding(3)var<uniform> params:CullParams;\nfn visible(world:mat4x4<f32>)->bool{\nlet center=(world*vec4<f32>(params.localSphere.xyz,1.0)).xyz;\nlet sx=length(world[0].xyz);\nlet sy=length(world[1].xyz);\nlet sz=length(world[2].xyz);\nlet radius=params.localSphere.w*max(max(sx,sy),sz)+0.0001;\nfor(var i=0u;i<6u;i++){\nlet p=params.planes[i];\nif(dot(p.xyz,center)+p.w < -radius){return false;}\n}\nreturn true;\n}\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\n}`;\n\nconst CULL_WGSL_COLOR = `${CULL_WGSL_NO_COLOR}\n@group(0)@binding(4)var<storage,read> srcColors:array<vec4<f32>>;\n@group(0)@binding(5)var<storage,read_write> dstColors:array<vec4<f32>>;\n@compute @workgroup_size(64)\nfn mainColor(@builtin(global_invocation_id) gid:vec3<u32>){\nlet i=gid.x;\nif(i>=params.count){return;}\nlet world=params.meshWorld*srcMatrices[i];\nif(!visible(world)){return;}\nlet outIndex=atomicAdd(&args[1],1u);\ndstMatrices[outIndex]=srcMatrices[i];\ndstColors[outIndex]=srcColors[i];\n}`;\n\n/** Per-render-binding GPU culling state. */\nexport interface ThinInstanceGpuCullState {\n /** @internal */\n _capacity: number;\n /** @internal */\n _visibleMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _visibleColorBuffer: GPUBuffer | null;\n /** @internal */\n _argsBuffer: GPUBuffer | null;\n /** @internal */\n _paramsBuffer: GPUBuffer | null;\n /** @internal */\n _bindGroup: GPUBindGroup | null;\n /** @internal */\n _srcMatrixBuffer: GPUBuffer | null;\n /** @internal */\n _srcColorBuffer: GPUBuffer | null;\n /** @internal */\n _hasColor: boolean;\n /** @internal */\n _localSphereReady: boolean;\n /** @internal */\n _localSphere: Float32Array;\n /** @internal */\n _paramsBytes: ArrayBuffer;\n /** @internal */\n _paramsF32: Float32Array;\n /** @internal */\n _paramsU32: Uint32Array;\n /** @internal */\n _argsData: Uint32Array;\n /** @internal */\n _drawBuffers: ThinInstanceDrawBuffers | null;\n}\n\n/** Result consumed by a material draw closure after culling has run for the active pass. */\nexport interface ThinInstanceGpuCullResult {\n readonly drawBuffers: ThinInstanceDrawBuffers;\n readonly argsBuffer: GPUBuffer;\n}\n\nlet _cachedDevice: GPUDevice | null = null;\nlet _pipelineNoColor: GPUComputePipeline | null = null;\nlet _pipelineColor: GPUComputePipeline | null = null;\n\n/** Create per-binding culling state. */\nexport function createTiCullState(): ThinInstanceGpuCullState {\n const paramsBytes = new ArrayBuffer(PARAM_BYTES);\n return {\n _capacity: 0,\n _visibleMatrixBuffer: null,\n _visibleColorBuffer: null,\n _argsBuffer: null,\n _paramsBuffer: null,\n _bindGroup: null,\n _srcMatrixBuffer: null,\n _srcColorBuffer: null,\n _hasColor: false,\n _localSphereReady: false,\n _localSphere: new F32(4),\n _paramsBytes: paramsBytes,\n _paramsF32: new F32(paramsBytes),\n _paramsU32: new U32(paramsBytes),\n _argsData: new U32(5),\n _drawBuffers: null,\n };\n}\n\n/** Destroy GPU resources owned by a per-binding cull state. */\nexport function destroyTiCullState(state: ThinInstanceGpuCullState): void {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._argsBuffer?.destroy();\n state._paramsBuffer?.destroy();\n state._visibleMatrixBuffer = null;\n state._visibleColorBuffer = null;\n state._argsBuffer = null;\n state._paramsBuffer = null;\n state._bindGroup = null;\n state._drawBuffers = null;\n}\n\n/** Run culling for one render binding and return buffers for the subsequent indirect draw. */\nexport function prepareTiCull(\n engine: EngineContext,\n state: ThinInstanceGpuCullState,\n mesh: Mesh,\n gpu: MeshGPU,\n ti: ThinInstanceData,\n hasColor: boolean,\n context: DrawUpdateContext\n): ThinInstanceGpuCullResult | null {\n const camera = context._camera;\n if (!ti._gpuCullingEnabled || !camera || mesh.visible === false || ti.count === 0) {\n state._drawBuffers = null;\n return null;\n }\n if (hasColor && !ti.colors) {\n state._drawBuffers = null;\n return null;\n }\n if (!state._localSphereReady && !computeLocalSphere(mesh as Mesh, state._localSphere)) {\n state._drawBuffers = null;\n return null;\n }\n state._localSphereReady = true;\n\n syncThinInstanceGpuData(engine, ti, hasColor);\n const sourceMatrixBuffer = ti._gpuBuffer;\n const sourceColorBuffer = hasColor ? ti._colorGpuBuffer : null;\n if (!sourceMatrixBuffer || (hasColor && !sourceColorBuffer)) {\n state._drawBuffers = null;\n return null;\n }\n\n ensureCullBuffers(engine, state, ti._capacity, hasColor);\n const visibleMatrixBuffer = state._visibleMatrixBuffer!;\n const visibleColorBuffer = hasColor ? state._visibleColorBuffer! : null;\n const argsBuffer = state._argsBuffer!;\n const paramsBuffer = state._paramsBuffer!;\n const pipeline = getCullPipeline(engine, hasColor);\n\n if (state._bindGroup === null || state._srcMatrixBuffer !== sourceMatrixBuffer || state._srcColorBuffer !== sourceColorBuffer || state._hasColor !== hasColor) {\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: sourceMatrixBuffer } },\n { binding: 1, resource: { buffer: visibleMatrixBuffer } },\n { binding: 2, resource: { buffer: argsBuffer } },\n { binding: 3, resource: { buffer: paramsBuffer } },\n ];\n if (hasColor) {\n entries.push({ binding: 4, resource: { buffer: sourceColorBuffer! } }, { binding: 5, resource: { buffer: visibleColorBuffer! } });\n }\n state._bindGroup = engine._device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries });\n state._srcMatrixBuffer = sourceMatrixBuffer;\n state._srcColorBuffer = sourceColorBuffer;\n state._hasColor = hasColor;\n }\n\n const v = camera.viewport;\n const aspect = (context.targetWidth / context.targetHeight) * (v ? v.width / v.height : 1);\n writeCullParams(engine, state, mesh, gpu.indexCount, ti.count, camera, aspect);\n\n const pass = engine._currentEncoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, state._bindGroup);\n pass.dispatchWorkgroups(Math.ceil(ti.count / WORKGROUP_SIZE));\n pass.end();\n\n state._drawBuffers = { matrixBuffer: visibleMatrixBuffer, colorBuffer: visibleColorBuffer };\n return { drawBuffers: state._drawBuffers, argsBuffer };\n}\n\nfunction ensureCullBuffers(engine: EngineContext, state: ThinInstanceGpuCullState, capacity: number, hasColor: boolean): void {\n const device = engine._device;\n if (state._capacity < capacity) {\n state._visibleMatrixBuffer?.destroy();\n state._visibleColorBuffer?.destroy();\n state._visibleMatrixBuffer = device.createBuffer({\n size: Math.max(capacity * 64, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._visibleColorBuffer = hasColor\n ? device.createBuffer({\n size: Math.max(capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n })\n : null;\n state._capacity = capacity;\n state._bindGroup = null;\n state._drawBuffers = null;\n } else if (hasColor && !state._visibleColorBuffer) {\n state._visibleColorBuffer = device.createBuffer({\n size: Math.max(state._capacity * 16, 4),\n usage: BU.VERTEX | BU.STORAGE,\n });\n state._bindGroup = null;\n state._drawBuffers = null;\n }\n if (!state._argsBuffer) {\n state._argsBuffer = device.createBuffer({\n size: INDIRECT_ARGS_BYTES,\n usage: BU.INDIRECT | BU.STORAGE | BU.COPY_DST,\n });\n }\n if (!state._paramsBuffer) {\n state._paramsBuffer = device.createBuffer({\n size: PARAM_BYTES,\n usage: BU.UNIFORM | BU.COPY_DST,\n });\n }\n}\n\nfunction getCullPipeline(engine: EngineContext, hasColor: boolean): GPUComputePipeline {\n const device = engine._device;\n if (_cachedDevice !== device) {\n _cachedDevice = device;\n _pipelineNoColor = null;\n _pipelineColor = null;\n }\n if (hasColor) {\n _pipelineColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_COLOR }), entryPoint: \"mainColor\" },\n });\n return _pipelineColor;\n }\n _pipelineNoColor ??= device.createComputePipeline({\n layout: \"auto\",\n compute: { module: device.createShaderModule({ code: CULL_WGSL_NO_COLOR }), entryPoint: \"main\" },\n });\n return _pipelineNoColor;\n}\n\nfunction writeCullParams(engine: EngineContext, state: ThinInstanceGpuCullState, mesh: Mesh, indexCount: number, instanceCount: number, camera: Camera, aspect: number): void {\n const params = state._paramsF32;\n const viewProjection = getViewProjectionMatrix(camera, aspect);\n writeFrustumPlanes(params, viewProjection);\n params.set(mesh.worldMatrix, MESH_WORLD_FLOAT_OFFSET);\n params.set(state._localSphere, LOCAL_SPHERE_FLOAT_OFFSET);\n state._paramsU32[COUNT_U32_OFFSET] = instanceCount;\n\n const args = state._argsData;\n args[0] = indexCount;\n args[1] = 0;\n args[2] = 0;\n args[3] = 0;\n args[4] = 0;\n\n engine._device.queue.writeBuffer(state._argsBuffer!, 0, args.buffer, args.byteOffset, args.byteLength);\n engine._device.queue.writeBuffer(state._paramsBuffer!, 0, state._paramsBytes);\n}\n\nfunction writeFrustumPlanes(out: Float32Array, m: Mat4): void {\n writePlane(out, 0, m[3]! + m[0]!, m[7]! + m[4]!, m[11]! + m[8]!, m[15]! + m[12]!);\n writePlane(out, 4, m[3]! - m[0]!, m[7]! - m[4]!, m[11]! - m[8]!, m[15]! - m[12]!);\n writePlane(out, 8, m[3]! + m[1]!, m[7]! + m[5]!, m[11]! + m[9]!, m[15]! + m[13]!);\n writePlane(out, 12, m[3]! - m[1]!, m[7]! - m[5]!, m[11]! - m[9]!, m[15]! - m[13]!);\n writePlane(out, 16, m[2]!, m[6]!, m[10]!, m[14]!);\n writePlane(out, 20, m[3]! - m[2]!, m[7]! - m[6]!, m[11]! - m[10]!, m[15]! - m[14]!);\n}\n\nfunction writePlane(out: Float32Array, offset: number, x: number, y: number, z: number, w: number): void {\n const invLen = 1 / Math.hypot(x, y, z);\n out[offset] = x * invLen;\n out[offset + 1] = y * invLen;\n out[offset + 2] = z * invLen;\n out[offset + 3] = w * invLen;\n}\n\nfunction computeLocalSphere(mesh: Mesh, out: Float32Array): boolean {\n const positions = mesh._cpuPositions;\n if (!positions || positions.length < 3) {\n return false;\n }\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let i = 0; i < positions.length; i += 3) {\n const x = positions[i]!;\n const y = positions[i + 1]!;\n const z = positions[i + 2]!;\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n if (!isFinite(minX)) {\n return false;\n }\n const cx = (minX + maxX) * 0.5;\n const cy = (minY + maxY) * 0.5;\n const cz = (minZ + maxZ) * 0.5;\n const dx = maxX - cx;\n const dy = maxY - cy;\n const dz = maxZ - cz;\n out[0] = cx;\n out[1] = cy;\n out[2] = cz;\n out[3] = Math.hypot(dx, dy, dz);\n return true;\n}\n","/** Shared per-binding GPU frustum-culling lifecycle for thin-instanced renderables.\n *\n * Dynamically imported only when a scene enables thin-instance GPU culling, and\n * it statically pulls in the compute-cull module — so non-culling scenes fetch\n * neither this helper nor `thin-instance-gpu-culling.ts`.\n *\n * Factored here so Standard, PBR, and ShaderMaterial renderables share one\n * implementation of the cull lifecycle instead of copy-pasting it three times.\n * `tryBind` is the single seam a renderable's `bind()` calls: it does the\n * opaque-only gate + per-mesh `_gpuCullingEnabled` check, marks the renderable\n * `_direct` (read by the render task's buildBindings right after `bind()`\n * returns), and creates the per-binding state. The renderable then reads\n * `cullDrawBufs` for the compacted instance source and calls `binding.draw(...)`\n * for the indirect-vs-fallback draw call. Keeping these few seams tiny is what\n * lets non-culling scenes — which still fetch the per-material renderable\n * chunks — stay within their bundle-size ceilings. */\n\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { SceneContext } from \"../scene/scene.js\";\nimport type { DrawUpdateContext, Renderable } from \"../render/renderable.js\";\nimport type { Mesh } from \"./mesh.js\";\nimport type { ThinInstanceDrawBuffers } from \"./thin-instance-gpu.js\";\nimport { createTiCullState, destroyTiCullState, prepareTiCull } from \"./thin-instance-gpu-culling.js\";\n\n/** Per-binding cull lifecycle. The renderable's `bind()` obtains one from\n * `tryBind`, uses `update` as the binding's update, reads `cullDrawBufs` (the\n * compacted instance source) and calls `draw()` for the final draw call. */\nexport interface TiCullBinding {\n /** Run the binding's base update, then dispatch the compute cull pass and stash the result. */\n update(context: DrawUpdateContext): void;\n /** Compacted visible-instance buffers, or null to fall back to a full instanced draw. */\n cullDrawBufs: ThinInstanceDrawBuffers | null;\n /** @internal Indirect draw-args buffer (null until/unless culling ran this frame). */\n _args: GPUBuffer | null;\n /** Issue the indirect (culled) draw when visible instances were compacted, else a full instanced draw. */\n draw(pass: GPURenderPassEncoder | GPURenderBundleEncoder, indexCount: number, instanceCount: number): void;\n}\n\n/** Create a per-binding cull lifecycle for one thin-instanced renderable binding,\n * iff the mesh opts in and is not excluded (transparent / transmissive — v1 is\n * opaque-only). Marks the renderable `_direct` so it leaves the cached opaque\n * bundle; this is safe to do during `bind()` because buildBindings reads\n * `_direct` only after `bind()` returns. Returns undefined when culling does not\n * apply, so the caller falls back to a normal instanced draw. */\nexport function tryBind(\n renderable: Renderable,\n scene: SceneContext,\n mesh: Mesh,\n engine: EngineContext,\n hasColor: boolean,\n excluded: boolean,\n baseUpdate: ((context: DrawUpdateContext) => void) | undefined\n): TiCullBinding | undefined {\n const ti = mesh.thinInstances;\n if (excluded || !ti?._gpuCullingEnabled) {\n return undefined;\n }\n (renderable as { _direct?: boolean })._direct = true;\n const state = createTiCullState();\n scene._meshDisposables.get(mesh)?.push(() => {\n destroyTiCullState(state);\n });\n const binding: TiCullBinding = {\n cullDrawBufs: null,\n _args: null,\n update(context: DrawUpdateContext): void {\n baseUpdate?.(context);\n const res = prepareTiCull(engine, state, mesh, mesh._gpu, ti, hasColor, context);\n binding.cullDrawBufs = res?.drawBuffers ?? null;\n binding._args = res?.argsBuffer ?? null;\n },\n draw(pass: GPURenderPassEncoder | GPURenderBundleEncoder, indexCount: number, instanceCount: number): void {\n if (binding._args) {\n pass.drawIndexedIndirect(binding._args, 0);\n } else {\n pass.drawIndexed(indexCount, instanceCount);\n }\n },\n };\n return binding;\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,iBAAiB;AACvB,MAAM,cAAc;AACpB,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;AAChC,MAAM,4BAA4B;AAClC,MAAM,sBAAsB;AAE5B,MAAM;AAAA;AAAA,EAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BtC,MAAM,kBAAkB,GAAG,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwD7C,IAAI,gBAAkC;AACtC,IAAI,mBAA8C;AAClD,IAAI,iBAA4C;AAGzC,SAAS,oBAA8C;AAC1D,QAAM,cAAc,IAAI,YAAY,WAAW;AAC/C,SAAO;AAAA,IACH,WAAW;AAAA,IACX,sBAAsB;AAAA,IACtB,qBAAqB;AAAA,IACrB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,IAAI,IAAI,CAAC;AAAA,IACvB,cAAc;AAAA,IACd,YAAY,IAAI,IAAI,WAAW;AAAA,IAC/B,YAAY,IAAI,IAAI,WAAW;AAAA,IAC/B,WAAW,IAAI,IAAI,CAAC;AAAA,IACpB,cAAc;AAAA,EAAA;AAEtB;AAGO,SAAS,mBAAmB,OAAuC;;AACtE,cAAM,yBAAN,mBAA4B;AAC5B,cAAM,wBAAN,mBAA2B;AAC3B,cAAM,gBAAN,mBAAmB;AACnB,cAAM,kBAAN,mBAAqB;AACrB,QAAM,uBAAuB;AAC7B,QAAM,sBAAsB;AAC5B,QAAM,cAAc;AACpB,QAAM,gBAAgB;AACtB,QAAM,aAAa;AACnB,QAAM,eAAe;AACzB;AAGO,SAAS,cACZ,QACA,OACA,MACA,KACA,IACA,UACA,SACgC;AAChC,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,GAAG,sBAAsB,CAAC,UAAU,KAAK,YAAY,SAAS,GAAG,UAAU,GAAG;AAC/E,UAAM,eAAe;AACrB,WAAO;AAAA,EACX;AACA,MAAI,YAAY,CAAC,GAAG,QAAQ;AACxB,UAAM,eAAe;AACrB,WAAO;AAAA,EACX;AACA,MAAI,CAAC,MAAM,qBAAqB,CAAC,mBAAmB,MAAc,MAAM,YAAY,GAAG;AACnF,UAAM,eAAe;AACrB,WAAO;AAAA,EACX;AACA,QAAM,oBAAoB;AAE1B,0BAAwB,QAAQ,IAAI,QAAQ;AAC5C,QAAM,qBAAqB,GAAG;AAC9B,QAAM,oBAAoB,WAAW,GAAG,kBAAkB;AAC1D,MAAI,CAAC,sBAAuB,YAAY,CAAC,mBAAoB;AACzD,UAAM,eAAe;AACrB,WAAO;AAAA,EACX;AAEA,oBAAkB,QAAQ,OAAO,GAAG,WAAW,QAAQ;AACvD,QAAM,sBAAsB,MAAM;AAClC,QAAM,qBAAqB,WAAW,MAAM,sBAAuB;AACnE,QAAM,aAAa,MAAM;AACzB,QAAM,eAAe,MAAM;AAC3B,QAAM,WAAW,gBAAgB,QAAQ,QAAQ;AAEjD,MAAI,MAAM,eAAe,QAAQ,MAAM,qBAAqB,sBAAsB,MAAM,oBAAoB,qBAAqB,MAAM,cAAc,UAAU;AAC3J,UAAM,UAA+B;AAAA,MACjC,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,qBAAmB;AAAA,MACrD,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,sBAAoB;AAAA,MACtD,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,aAAW;AAAA,MAC7C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,eAAa;AAAA,IAAE;AAErD,QAAI,UAAU;AACV,cAAQ,KAAK,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,kBAAA,EAAmB,GAAK,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,mBAAA,GAAuB;AAAA,IACpI;AACA,UAAM,aAAa,OAAO,QAAQ,gBAAgB,EAAE,QAAQ,SAAS,mBAAmB,CAAC,GAAG,QAAA,CAAS;AACrG,UAAM,mBAAmB;AACzB,UAAM,kBAAkB;AACxB,UAAM,YAAY;AAAA,EACtB;AAEA,QAAM,IAAI,OAAO;AACjB,QAAM,SAAU,QAAQ,cAAc,QAAQ,gBAAiB,IAAI,EAAE,QAAQ,EAAE,SAAS;AACxF,kBAAgB,QAAQ,OAAO,MAAM,IAAI,YAAY,GAAG,OAAO,QAAQ,MAAM;AAE7E,QAAM,OAAO,OAAO,gBAAgB,iBAAA;AACpC,OAAK,YAAY,QAAQ;AACzB,OAAK,aAAa,GAAG,MAAM,UAAU;AACrC,OAAK,mBAAmB,KAAK,KAAK,GAAG,QAAQ,cAAc,CAAC;AAC5D,OAAK,IAAA;AAEL,QAAM,eAAe,EAAE,cAAc,qBAAqB,aAAa,mBAAA;AACvE,SAAO,EAAE,aAAa,MAAM,cAAc,WAAA;AAC9C;AAEA,SAAS,kBAAkB,QAAuB,OAAiC,UAAkB,UAAyB;;AAC1H,QAAM,SAAS,OAAO;AACtB,MAAI,MAAM,YAAY,UAAU;AAC5B,gBAAM,yBAAN,mBAA4B;AAC5B,gBAAM,wBAAN,mBAA2B;AAC3B,UAAM,uBAAuB,OAAO,aAAa;AAAA,MAC7C,MAAM,KAAK,IAAI,WAAW,IAAI,CAAC;AAAA,MAC/B,OAAO,GAAG,SAAS,GAAG;AAAA,IAAA,CACzB;AACD,UAAM,sBAAsB,WACtB,OAAO,aAAa;AAAA,MAChB,MAAM,KAAK,IAAI,WAAW,IAAI,CAAC;AAAA,MAC/B,OAAO,GAAG,SAAS,GAAG;AAAA,IAAA,CACzB,IACD;AACN,UAAM,YAAY;AAClB,UAAM,aAAa;AACnB,UAAM,eAAe;AAAA,EACzB,WAAW,YAAY,CAAC,MAAM,qBAAqB;AAC/C,UAAM,sBAAsB,OAAO,aAAa;AAAA,MAC5C,MAAM,KAAK,IAAI,MAAM,YAAY,IAAI,CAAC;AAAA,MACtC,OAAO,GAAG,SAAS,GAAG;AAAA,IAAA,CACzB;AACD,UAAM,aAAa;AACnB,UAAM,eAAe;AAAA,EACzB;AACA,MAAI,CAAC,MAAM,aAAa;AACpB,UAAM,cAAc,OAAO,aAAa;AAAA,MACpC,MAAM;AAAA,MACN,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG;AAAA,IAAA,CACxC;AAAA,EACL;AACA,MAAI,CAAC,MAAM,eAAe;AACtB,UAAM,gBAAgB,OAAO,aAAa;AAAA,MACtC,MAAM;AAAA,MACN,OAAO,GAAG,UAAU,GAAG;AAAA,IAAA,CAC1B;AAAA,EACL;AACJ;AAEA,SAAS,gBAAgB,QAAuB,UAAuC;AACnF,QAAM,SAAS,OAAO;AACtB,MAAI,kBAAkB,QAAQ;AAC1B,oBAAgB;AAChB,uBAAmB;AACnB,qBAAiB;AAAA,EACrB;AACA,MAAI,UAAU;AACV,wCAAmB,OAAO,sBAAsB;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS,EAAE,QAAQ,OAAO,mBAAmB,EAAE,MAAM,gBAAA,CAAiB,GAAG,YAAY,YAAA;AAAA,IAAY,CACpG;AACD,WAAO;AAAA,EACX;AACA,0CAAqB,OAAO,sBAAsB;AAAA,IAC9C,QAAQ;AAAA,IACR,SAAS,EAAE,QAAQ,OAAO,mBAAmB,EAAE,MAAM,mBAAA,CAAoB,GAAG,YAAY,OAAA;AAAA,EAAO,CAClG;AACD,SAAO;AACX;AAEA,SAAS,gBAAgB,QAAuB,OAAiC,MAAY,YAAoB,eAAuB,QAAgB,QAAsB;AAC1K,QAAM,SAAS,MAAM;AACrB,QAAM,iBAAiB,wBAAwB,QAAQ,MAAM;AAC7D,qBAAmB,QAAQ,cAAc;AACzC,SAAO,IAAI,KAAK,aAAa,uBAAuB;AACpD,SAAO,IAAI,MAAM,cAAc,yBAAyB;AACxD,QAAM,WAAW,gBAAgB,IAAI;AAErC,QAAM,OAAO,MAAM;AACnB,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AAEV,SAAO,QAAQ,MAAM,YAAY,MAAM,aAAc,GAAG,KAAK,QAAQ,KAAK,YAAY,KAAK,UAAU;AACrG,SAAO,QAAQ,MAAM,YAAY,MAAM,eAAgB,GAAG,MAAM,YAAY;AAChF;AAEA,SAAS,mBAAmB,KAAmB,GAAe;AAC1D,aAAW,KAAK,GAAG,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,CAAE;AAChF,aAAW,KAAK,GAAG,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,CAAE;AAChF,aAAW,KAAK,GAAG,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,CAAE;AAChF,aAAW,KAAK,IAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,CAAE;AACjF,aAAW,KAAK,IAAI,EAAE,CAAC,GAAI,EAAE,CAAC,GAAI,EAAE,EAAE,GAAI,EAAE,EAAE,CAAE;AAChD,aAAW,KAAK,IAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,CAAC,IAAK,EAAE,CAAC,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,GAAI,EAAE,EAAE,IAAK,EAAE,EAAE,CAAE;AACtF;AAEA,SAAS,WAAW,KAAmB,QAAgB,GAAW,GAAW,GAAW,GAAiB;AACrG,QAAM,SAAS,IAAI,KAAK,MAAM,GAAG,GAAG,CAAC;AACrC,MAAI,MAAM,IAAI,IAAI;AAClB,MAAI,SAAS,CAAC,IAAI,IAAI;AACtB,MAAI,SAAS,CAAC,IAAI,IAAI;AACtB,MAAI,SAAS,CAAC,IAAI,IAAI;AAC1B;AAEA,SAAS,mBAAmB,MAAY,KAA4B;AAChE,QAAM,YAAY,KAAK;AACvB,MAAI,CAAC,aAAa,UAAU,SAAS,GAAG;AACpC,WAAO;AAAA,EACX;AACA,MAAI,OAAO,UACP,OAAO,UACP,OAAO;AACX,MAAI,OAAO,WACP,OAAO,WACP,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,GAAG;AAC1C,UAAM,IAAI,UAAU,CAAC;AACrB,UAAM,IAAI,UAAU,IAAI,CAAC;AACzB,UAAM,IAAI,UAAU,IAAI,CAAC;AACzB,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AACA,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AACA,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AACA,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AACA,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AACA,QAAI,IAAI,MAAM;AACV,aAAO;AAAA,IACX;AAAA,EACJ;AACA,MAAI,CAAC,SAAS,IAAI,GAAG;AACjB,WAAO;AAAA,EACX;AACA,QAAM,MAAM,OAAO,QAAQ;AAC3B,QAAM,MAAM,OAAO,QAAQ;AAC3B,QAAM,MAAM,OAAO,QAAQ;AAC3B,QAAM,KAAK,OAAO;AAClB,QAAM,KAAK,OAAO;AAClB,QAAM,KAAK,OAAO;AAClB,MAAI,CAAC,IAAI;AACT,MAAI,CAAC,IAAI;AACT,MAAI,CAAC,IAAI;AACT,MAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,EAAE;AAC9B,SAAO;AACX;AClUO,SAAS,QACZ,YACA,OACA,MACA,QACA,UACA,UACA,YACyB;;AACzB,QAAM,KAAK,KAAK;AAChB,MAAI,YAAY,EAAC,yBAAI,qBAAoB;AACrC,WAAO;AAAA,EACX;AACC,aAAqC,UAAU;AAChD,QAAM,QAAQ,kBAAA;AACd,cAAM,iBAAiB,IAAI,IAAI,MAA/B,mBAAkC,KAAK,MAAM;AACzC,uBAAmB,KAAK;AAAA,EAC5B;AACA,QAAM,UAAyB;AAAA,IAC3B,cAAc;AAAA,IACd,OAAO;AAAA,IACP,OAAO,SAAkC;AACrC,+CAAa;AACb,YAAM,MAAM,cAAc,QAAQ,OAAO,MAAM,KAAK,MAAM,IAAI,UAAU,OAAO;AAC/E,cAAQ,gBAAe,2BAAK,gBAAe;AAC3C,cAAQ,SAAQ,2BAAK,eAAc;AAAA,IACvC;AAAA,IACA,KAAK,MAAqD,YAAoB,eAA6B;AACvG,UAAI,QAAQ,OAAO;AACf,aAAK,oBAAoB,QAAQ,OAAO,CAAC;AAAA,MAC7C,OAAO;AACH,aAAK,YAAY,YAAY,aAAa;AAAA,MAC9C;AAAA,IACJ;AAAA,EAAA;AAEJ,SAAO;AACX;"}
@@ -1,4 +1,4 @@
1
- import { B as BU, a as F32, p as packMat4IntoF32 } from "./index-C-tEgwbZ.js";
1
+ import { B as BU, a as F32, p as packMat4IntoF32 } from "./index-BgY3QEzL.js";
2
2
  function syncThinInstanceGpuData(engine, ti, hasColor) {
3
3
  var _a, _b;
4
4
  const device = engine._device;
@@ -84,4 +84,4 @@ export {
84
84
  syncThinInstanceBuffers,
85
85
  syncThinInstanceGpuData
86
86
  };
87
- //# sourceMappingURL=thin-instance-gpu-uY2NOv0J.js.map
87
+ //# sourceMappingURL=thin-instance-gpu-C1DGstap.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thin-instance-gpu-uY2NOv0J.js","sources":["../src/mesh/thin-instance-gpu.ts"],"sourcesContent":["/** Thin instance GPU buffer sync — dynamically loaded only by scenes with thin instances.\n * Keeps the standard renderable chunk unchanged for scenes without thin instances. */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\n\n/** @internal Optional replacement buffers used by GPU culling after it compacts visible instances. */\nexport interface ThinInstanceDrawBuffers {\n readonly matrixBuffer: GPUBuffer;\n readonly colorBuffer: GPUBuffer | null;\n}\n\n/** @internal Sync CPU thin-instance data to GPU buffers, optionally with STORAGE usage for compute culling. */\nexport function syncThinInstanceGpuData(engine: EngineContext, ti: ThinInstanceData, hasColor: boolean): void {\n const device = engine._device;\n const needsStorage = ti._gpuCullingEnabled;\n if (ti._version !== ti._gpuVersion || ti._gpuBufferStorage !== needsStorage) {\n const byteSize = ti.count * 64;\n let bufferRecreated = false;\n if (!ti._gpuBuffer || ti._gpuBuffer.size < byteSize || ti._gpuBufferStorage !== needsStorage) {\n ti._gpuBuffer?.destroy();\n ti._gpuBuffer = device.createBuffer({\n size: Math.max(ti._capacity * 64, 4),\n // STORAGE is always included: the GPU picker binds this matrix\n // buffer as a read-only storage buffer for thin-instance picking,\n // so it must be storage-capable even when compute culling is off\n // (otherwise the whole pick pass is invalidated → nothing is pickable).\n usage: BU.VERTEX | BU.COPY_DST | BU.STORAGE,\n });\n ti._gpuBufferStorage = needsStorage;\n bufferRecreated = true;\n }\n // Upload only the dirty range (or full range if buffer was just created)\n const dirtyMin = bufferRecreated ? 0 : ti._dirtyMin;\n const dirtyMax = bufferRecreated ? ti.count : Math.min(ti._dirtyMax, ti.count);\n if (dirtyMax > dirtyMin) {\n const minByte = dirtyMin * 64;\n const maxByte = dirtyMax * 64;\n if (ti.matrices instanceof F32) {\n // Fast path: F32 source — direct byte copy, no per-instance pack.\n device.queue.writeBuffer(ti._gpuBuffer, minByte, ti.matrices.buffer, ti.matrices.byteOffset + minByte, maxByte - minByte);\n } else {\n // F64 source (HPM-on path) — pack each dirty instance into a\n // per-mesh reused F32 upload scratch, then writeBuffer the\n // dirty subrange. Scratch is sized to capacity in F32 floats\n // and grown when capacity grows; never per-frame allocated.\n const neededFloats = ti._capacity * 16;\n if (!ti._uploadF32 || ti._uploadF32.length < neededFloats) {\n ti._uploadF32 = new F32(neededFloats);\n }\n const upload = ti._uploadF32;\n for (let i = dirtyMin; i < dirtyMax; i++) {\n packMat4IntoF32(upload, ti.matrices, i * 16, i * 16);\n }\n device.queue.writeBuffer(ti._gpuBuffer, minByte, upload.buffer, upload.byteOffset + minByte, maxByte - minByte);\n }\n }\n ti._dirtyMin = ti.count;\n ti._dirtyMax = 0;\n ti._gpuVersion = ti._version;\n }\n\n if (hasColor && ti.colors) {\n if (ti._colorVersion !== ti._colorGpuVersion || ti._colorGpuBufferStorage !== needsStorage) {\n const colorByteSize = ti.count * 16;\n let colorRecreated = false;\n if (!ti._colorGpuBuffer || ti._colorGpuBuffer.size < colorByteSize || ti._colorGpuBufferStorage !== needsStorage) {\n ti._colorGpuBuffer?.destroy();\n ti._colorGpuBuffer = device.createBuffer({\n size: Math.max(ti._capacity * 16, 4),\n usage: BU.VERTEX | BU.COPY_DST | (needsStorage ? BU.STORAGE : 0),\n });\n ti._colorGpuBufferStorage = needsStorage;\n colorRecreated = true;\n }\n // Upload only the dirty colour range (mirrors the matrix path) — full range on (re)create.\n const cMin = colorRecreated ? 0 : ti._colorDirtyMin;\n const cMax = colorRecreated ? ti.count : Math.min(ti._colorDirtyMax, ti.count);\n if (cMax > cMin) {\n device.queue.writeBuffer(ti._colorGpuBuffer, cMin * 16, ti.colors.buffer, ti.colors.byteOffset + cMin * 16, (cMax - cMin) * 16);\n }\n ti._colorDirtyMin = ti.count;\n ti._colorDirtyMax = 0;\n ti._colorGpuVersion = ti._colorVersion;\n }\n }\n}\n\n/** Sync thin instance matrix + optional color GPU buffers and bind to vertex slots. */\nexport function syncThinInstanceBuffers(\n engine: EngineContext,\n ti: ThinInstanceData,\n pass: GPURenderPassEncoder | GPURenderBundleEncoder,\n slot: number,\n hasColor: boolean,\n drawBuffers?: ThinInstanceDrawBuffers | null\n): number {\n syncThinInstanceGpuData(engine, ti, hasColor);\n const matrixBuffer = drawBuffers?.matrixBuffer ?? ti._gpuBuffer;\n if (matrixBuffer) {\n pass.setVertexBuffer(slot++, matrixBuffer);\n }\n\n if (hasColor) {\n const colorBuffer = drawBuffers?.colorBuffer ?? ti._colorGpuBuffer;\n if (colorBuffer) {\n pass.setVertexBuffer(slot++, colorBuffer);\n }\n }\n\n return slot;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"thin-instance-gpu-C1DGstap.js","sources":["../src/mesh/thin-instance-gpu.ts"],"sourcesContent":["/** Thin instance GPU buffer sync — dynamically loaded only by scenes with thin instances.\n * Keeps the standard renderable chunk unchanged for scenes without thin instances. */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { ThinInstanceData } from \"./thin-instance.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\n\n/** @internal Optional replacement buffers used by GPU culling after it compacts visible instances. */\nexport interface ThinInstanceDrawBuffers {\n readonly matrixBuffer: GPUBuffer;\n readonly colorBuffer: GPUBuffer | null;\n}\n\n/** @internal Sync CPU thin-instance data to GPU buffers, optionally with STORAGE usage for compute culling. */\nexport function syncThinInstanceGpuData(engine: EngineContext, ti: ThinInstanceData, hasColor: boolean): void {\n const device = engine._device;\n const needsStorage = ti._gpuCullingEnabled;\n if (ti._version !== ti._gpuVersion || ti._gpuBufferStorage !== needsStorage) {\n const byteSize = ti.count * 64;\n let bufferRecreated = false;\n if (!ti._gpuBuffer || ti._gpuBuffer.size < byteSize || ti._gpuBufferStorage !== needsStorage) {\n ti._gpuBuffer?.destroy();\n ti._gpuBuffer = device.createBuffer({\n size: Math.max(ti._capacity * 64, 4),\n // STORAGE is always included: the GPU picker binds this matrix\n // buffer as a read-only storage buffer for thin-instance picking,\n // so it must be storage-capable even when compute culling is off\n // (otherwise the whole pick pass is invalidated → nothing is pickable).\n usage: BU.VERTEX | BU.COPY_DST | BU.STORAGE,\n });\n ti._gpuBufferStorage = needsStorage;\n bufferRecreated = true;\n }\n // Upload only the dirty range (or full range if buffer was just created)\n const dirtyMin = bufferRecreated ? 0 : ti._dirtyMin;\n const dirtyMax = bufferRecreated ? ti.count : Math.min(ti._dirtyMax, ti.count);\n if (dirtyMax > dirtyMin) {\n const minByte = dirtyMin * 64;\n const maxByte = dirtyMax * 64;\n if (ti.matrices instanceof F32) {\n // Fast path: F32 source — direct byte copy, no per-instance pack.\n device.queue.writeBuffer(ti._gpuBuffer, minByte, ti.matrices.buffer, ti.matrices.byteOffset + minByte, maxByte - minByte);\n } else {\n // F64 source (HPM-on path) — pack each dirty instance into a\n // per-mesh reused F32 upload scratch, then writeBuffer the\n // dirty subrange. Scratch is sized to capacity in F32 floats\n // and grown when capacity grows; never per-frame allocated.\n const neededFloats = ti._capacity * 16;\n if (!ti._uploadF32 || ti._uploadF32.length < neededFloats) {\n ti._uploadF32 = new F32(neededFloats);\n }\n const upload = ti._uploadF32;\n for (let i = dirtyMin; i < dirtyMax; i++) {\n packMat4IntoF32(upload, ti.matrices, i * 16, i * 16);\n }\n device.queue.writeBuffer(ti._gpuBuffer, minByte, upload.buffer, upload.byteOffset + minByte, maxByte - minByte);\n }\n }\n ti._dirtyMin = ti.count;\n ti._dirtyMax = 0;\n ti._gpuVersion = ti._version;\n }\n\n if (hasColor && ti.colors) {\n if (ti._colorVersion !== ti._colorGpuVersion || ti._colorGpuBufferStorage !== needsStorage) {\n const colorByteSize = ti.count * 16;\n let colorRecreated = false;\n if (!ti._colorGpuBuffer || ti._colorGpuBuffer.size < colorByteSize || ti._colorGpuBufferStorage !== needsStorage) {\n ti._colorGpuBuffer?.destroy();\n ti._colorGpuBuffer = device.createBuffer({\n size: Math.max(ti._capacity * 16, 4),\n usage: BU.VERTEX | BU.COPY_DST | (needsStorage ? BU.STORAGE : 0),\n });\n ti._colorGpuBufferStorage = needsStorage;\n colorRecreated = true;\n }\n // Upload only the dirty colour range (mirrors the matrix path) — full range on (re)create.\n const cMin = colorRecreated ? 0 : ti._colorDirtyMin;\n const cMax = colorRecreated ? ti.count : Math.min(ti._colorDirtyMax, ti.count);\n if (cMax > cMin) {\n device.queue.writeBuffer(ti._colorGpuBuffer, cMin * 16, ti.colors.buffer, ti.colors.byteOffset + cMin * 16, (cMax - cMin) * 16);\n }\n ti._colorDirtyMin = ti.count;\n ti._colorDirtyMax = 0;\n ti._colorGpuVersion = ti._colorVersion;\n }\n }\n}\n\n/** Sync thin instance matrix + optional color GPU buffers and bind to vertex slots. */\nexport function syncThinInstanceBuffers(\n engine: EngineContext,\n ti: ThinInstanceData,\n pass: GPURenderPassEncoder | GPURenderBundleEncoder,\n slot: number,\n hasColor: boolean,\n drawBuffers?: ThinInstanceDrawBuffers | null\n): number {\n syncThinInstanceGpuData(engine, ti, hasColor);\n const matrixBuffer = drawBuffers?.matrixBuffer ?? ti._gpuBuffer;\n if (matrixBuffer) {\n pass.setVertexBuffer(slot++, matrixBuffer);\n }\n\n if (hasColor) {\n const colorBuffer = drawBuffers?.colorBuffer ?? ti._colorGpuBuffer;\n if (colorBuffer) {\n pass.setVertexBuffer(slot++, colorBuffer);\n }\n }\n\n return slot;\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { f as markMaterialUboDirty } from "./index-C-tEgwbZ.js";
1
+ import { f as markMaterialUboDirty } from "./index-BgY3QEzL.js";
2
2
  function observableColor3(r, g, b, owner) {
3
3
  const arr = [r, g, b];
4
4
  for (let i = 0; i < 3; i++) {
@@ -79,4 +79,4 @@ export {
79
79
  observableColor3 as o,
80
80
  trackScalar as t
81
81
  };
82
- //# sourceMappingURL=tracking-primitives-Ck5bgCuo.js.map
82
+ //# sourceMappingURL=tracking-primitives-CMBWLxGr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracking-primitives-Ck5bgCuo.js","sources":["../src/material/tracking/tracking-primitives.ts"],"sourcesContent":["/** Shared tracking primitives for observable material properties. */\n\nimport type { Material } from \"../material.js\";\nimport { markMaterialUboDirty } from \"../material-dirty.js\";\n\nexport function observableColor3(r: number, g: number, b: number, owner: Material): [number, number, number] {\n const arr = [r, g, b] as [number, number, number];\n for (let i = 0; i < 3; i++) {\n let val = arr[i]!;\n Object.defineProperty(arr, i, {\n get() {\n return val;\n },\n set(v: number) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(owner);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n return arr;\n}\n\nexport function observableVec2(x: number, y: number, owner: Material): [number, number] {\n const arr = [x, y] as [number, number];\n for (let i = 0; i < 2; i++) {\n let val = arr[i]!;\n Object.defineProperty(arr, i, {\n get() {\n return val;\n },\n set(v: number) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(owner);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n return arr;\n}\n\nexport function trackScalar(obj: any, key: string): void {\n let val = obj[key];\n Object.defineProperty(obj, key, {\n get() {\n return val;\n },\n set(v: any) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(obj as Material);\n }\n },\n configurable: true,\n enumerable: true,\n });\n}\n\nexport function trackSubProps(parent: Material, sub: any, keys: string[]): void {\n for (const key of keys) {\n let val = sub[key];\n Object.defineProperty(sub, key, {\n get() {\n return val;\n },\n set(v: any) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(parent);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n}\n"],"names":[],"mappings":";AAKO,SAAS,iBAAiB,GAAW,GAAW,GAAW,OAA2C;AACzG,QAAM,MAAM,CAAC,GAAG,GAAG,CAAC;AACpB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,MAAM,IAAI,CAAC;AACf,WAAO,eAAe,KAAK,GAAG;AAAA,MAC1B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAW;AACX,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,KAAK;AAAA,QAC9B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACA,SAAO;AACX;AAEO,SAAS,eAAe,GAAW,GAAW,OAAmC;AACpF,QAAM,MAAM,CAAC,GAAG,CAAC;AACjB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,MAAM,IAAI,CAAC;AACf,WAAO,eAAe,KAAK,GAAG;AAAA,MAC1B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAW;AACX,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,KAAK;AAAA,QAC9B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACA,SAAO;AACX;AAEO,SAAS,YAAY,KAAU,KAAmB;AACrD,MAAI,MAAM,IAAI,GAAG;AACjB,SAAO,eAAe,KAAK,KAAK;AAAA,IAC5B,MAAM;AACF,aAAO;AAAA,IACX;AAAA,IACA,IAAI,GAAQ;AACR,UAAI,QAAQ,GAAG;AACX,cAAM;AACN,6BAAqB,GAAe;AAAA,MACxC;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,IACd,YAAY;AAAA,EAAA,CACf;AACL;AAEO,SAAS,cAAc,QAAkB,KAAU,MAAsB;AAC5E,aAAW,OAAO,MAAM;AACpB,QAAI,MAAM,IAAI,GAAG;AACjB,WAAO,eAAe,KAAK,KAAK;AAAA,MAC5B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAQ;AACR,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,MAAM;AAAA,QAC/B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACJ;"}
1
+ {"version":3,"file":"tracking-primitives-CMBWLxGr.js","sources":["../src/material/tracking/tracking-primitives.ts"],"sourcesContent":["/** Shared tracking primitives for observable material properties. */\n\nimport type { Material } from \"../material.js\";\nimport { markMaterialUboDirty } from \"../material-dirty.js\";\n\nexport function observableColor3(r: number, g: number, b: number, owner: Material): [number, number, number] {\n const arr = [r, g, b] as [number, number, number];\n for (let i = 0; i < 3; i++) {\n let val = arr[i]!;\n Object.defineProperty(arr, i, {\n get() {\n return val;\n },\n set(v: number) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(owner);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n return arr;\n}\n\nexport function observableVec2(x: number, y: number, owner: Material): [number, number] {\n const arr = [x, y] as [number, number];\n for (let i = 0; i < 2; i++) {\n let val = arr[i]!;\n Object.defineProperty(arr, i, {\n get() {\n return val;\n },\n set(v: number) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(owner);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n return arr;\n}\n\nexport function trackScalar(obj: any, key: string): void {\n let val = obj[key];\n Object.defineProperty(obj, key, {\n get() {\n return val;\n },\n set(v: any) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(obj as Material);\n }\n },\n configurable: true,\n enumerable: true,\n });\n}\n\nexport function trackSubProps(parent: Material, sub: any, keys: string[]): void {\n for (const key of keys) {\n let val = sub[key];\n Object.defineProperty(sub, key, {\n get() {\n return val;\n },\n set(v: any) {\n if (val !== v) {\n val = v;\n markMaterialUboDirty(parent);\n }\n },\n configurable: true,\n enumerable: true,\n });\n }\n}\n"],"names":[],"mappings":";AAKO,SAAS,iBAAiB,GAAW,GAAW,GAAW,OAA2C;AACzG,QAAM,MAAM,CAAC,GAAG,GAAG,CAAC;AACpB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,MAAM,IAAI,CAAC;AACf,WAAO,eAAe,KAAK,GAAG;AAAA,MAC1B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAW;AACX,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,KAAK;AAAA,QAC9B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACA,SAAO;AACX;AAEO,SAAS,eAAe,GAAW,GAAW,OAAmC;AACpF,QAAM,MAAM,CAAC,GAAG,CAAC;AACjB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,QAAI,MAAM,IAAI,CAAC;AACf,WAAO,eAAe,KAAK,GAAG;AAAA,MAC1B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAW;AACX,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,KAAK;AAAA,QAC9B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACA,SAAO;AACX;AAEO,SAAS,YAAY,KAAU,KAAmB;AACrD,MAAI,MAAM,IAAI,GAAG;AACjB,SAAO,eAAe,KAAK,KAAK;AAAA,IAC5B,MAAM;AACF,aAAO;AAAA,IACX;AAAA,IACA,IAAI,GAAQ;AACR,UAAI,QAAQ,GAAG;AACX,cAAM;AACN,6BAAqB,GAAe;AAAA,MACxC;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,IACd,YAAY;AAAA,EAAA,CACf;AACL;AAEO,SAAS,cAAc,QAAkB,KAAU,MAAsB;AAC5E,aAAW,OAAO,MAAM;AACpB,QAAI,MAAM,IAAI,GAAG;AACjB,WAAO,eAAe,KAAK,KAAK;AAAA,MAC5B,MAAM;AACF,eAAO;AAAA,MACX;AAAA,MACA,IAAI,GAAQ;AACR,YAAI,QAAQ,GAAG;AACX,gBAAM;AACN,+BAAqB,MAAM;AAAA,QAC/B;AAAA,MACJ;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IAAA,CACf;AAAA,EACL;AACJ;"}
@@ -1,4 +1,4 @@
1
- import { b4 as PBR2_HAS_UNLIT } from "./index-C-tEgwbZ.js";
1
+ import { b6 as PBR2_HAS_UNLIT } from "./index-BgY3QEzL.js";
2
2
  function createUnlitFragment(hasIbl) {
3
3
  const assign = `color = baseColor * material.unlitColor;`;
4
4
  return {
@@ -40,4 +40,4 @@ export {
40
40
  pbrExt,
41
41
  writeUnlitUBO
42
42
  };
43
- //# sourceMappingURL=unlit-fragment-nc6hu3Mw.js.map
43
+ //# sourceMappingURL=unlit-fragment-BsHrS9XX.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"unlit-fragment-nc6hu3Mw.js","sources":["../src/material/pbr/fragments/unlit-fragment.ts"],"sourcesContent":["/**\n * Unlit Fragment (KHR_materials_unlit).\n *\n * Replaces the lit-color computation with `baseColor * unlitColor` right\n * before the tonemap/gamma/contrast chain runs. Depends on the IBL fragment\n * when present so our AI injection runs *after* IBL's, overwriting the IBL\n * color contribution. The subsequent tonemap/gamma/contrast stages still\n * apply, matching BJS's unlit output under `createDefaultEnvironment`.\n *\n * Zero bytes in bundles for scenes that don't use unlit materials.\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 { PBR2_HAS_UNLIT } from \"../pbr-flag-bits.js\";\n\nexport function createUnlitFragment(hasIbl: boolean): ShaderFragment {\n const assign = `color = baseColor * material.unlitColor;`;\n return {\n _id: \"unlit\",\n _dependencies: hasIbl ? [\"ibl\"] : undefined,\n _uboFields: [\n { _name: \"unlitColor\", _type: \"vec3<f32>\" },\n { _name: \"_unlitColorPad\", _type: \"f32\" },\n ],\n _fragmentSlots: hasIbl ? { AI: assign } : { NI: assign },\n };\n}\n\n/** Write the unlit material-UBO slice. */\nexport function writeUnlitUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n if (!material.unlit || !offsets.has(\"unlitColor\")) {\n return;\n }\n const off = offsets.get(\"unlitColor\")! / 4;\n const tint = material.unlitColor ?? [1, 1, 1];\n data[off] = tint[0]!;\n data[off + 1] = tint[1]!;\n data[off + 2] = tint[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"unlit\",\n phase: \"fragment\",\n detect(mat) {\n return (mat as PbrMaterialProps).unlit ? { f: 0, f2: PBR2_HAS_UNLIT } : { f: 0, f2: 0 };\n },\n frag(ctx) {\n if (!(ctx._features2 & PBR2_HAS_UNLIT)) {\n return null;\n }\n return createUnlitFragment(ctx._hasIbl);\n },\n writeUbo: writeUnlitUBO as PbrExt[\"writeUbo\"],\n};\n"],"names":[],"mappings":";AAiBO,SAAS,oBAAoB,QAAiC;AACjE,QAAM,SAAS;AACf,SAAO;AAAA,IACH,KAAK;AAAA,IACL,eAAe,SAAS,CAAC,KAAK,IAAI;AAAA,IAClC,YAAY;AAAA,MACR,EAAE,OAAO,cAAc,OAAO,YAAA;AAAA,MAC9B,EAAE,OAAO,kBAAkB,OAAO,MAAA;AAAA,IAAM;AAAA,IAE5C,gBAAgB,SAAS,EAAE,IAAI,WAAW,EAAE,IAAI,OAAA;AAAA,EAAO;AAE/D;AAGO,SAAS,cAAc,MAAoB,UAA4B,SAA4C;AACtH,MAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,IAAI,YAAY,GAAG;AAC/C;AAAA,EACJ;AACA,QAAM,MAAM,QAAQ,IAAI,YAAY,IAAK;AACzC,QAAM,OAAO,SAAS,cAAc,CAAC,GAAG,GAAG,CAAC;AAC5C,OAAK,GAAG,IAAI,KAAK,CAAC;AAClB,OAAK,MAAM,CAAC,IAAI,KAAK,CAAC;AACtB,OAAK,MAAM,CAAC,IAAI,KAAK,CAAC;AAC1B;AAEO,MAAM,SAAiB;AAAA,EAC1B,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO,KAAK;AACR,WAAQ,IAAyB,QAAQ,EAAE,GAAG,GAAG,IAAI,eAAA,IAAmB,EAAE,GAAG,GAAG,IAAI,EAAA;AAAA,EACxF;AAAA,EACA,KAAK,KAAK;AACN,QAAI,EAAE,IAAI,aAAa,iBAAiB;AACpC,aAAO;AAAA,IACX;AACA,WAAO,oBAAoB,IAAI,OAAO;AAAA,EAC1C;AAAA,EACA,UAAU;AACd;"}
1
+ {"version":3,"file":"unlit-fragment-BsHrS9XX.js","sources":["../src/material/pbr/fragments/unlit-fragment.ts"],"sourcesContent":["/**\n * Unlit Fragment (KHR_materials_unlit).\n *\n * Replaces the lit-color computation with `baseColor * unlitColor` right\n * before the tonemap/gamma/contrast chain runs. Depends on the IBL fragment\n * when present so our AI injection runs *after* IBL's, overwriting the IBL\n * color contribution. The subsequent tonemap/gamma/contrast stages still\n * apply, matching BJS's unlit output under `createDefaultEnvironment`.\n *\n * Zero bytes in bundles for scenes that don't use unlit materials.\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 { PBR2_HAS_UNLIT } from \"../pbr-flag-bits.js\";\n\nexport function createUnlitFragment(hasIbl: boolean): ShaderFragment {\n const assign = `color = baseColor * material.unlitColor;`;\n return {\n _id: \"unlit\",\n _dependencies: hasIbl ? [\"ibl\"] : undefined,\n _uboFields: [\n { _name: \"unlitColor\", _type: \"vec3<f32>\" },\n { _name: \"_unlitColorPad\", _type: \"f32\" },\n ],\n _fragmentSlots: hasIbl ? { AI: assign } : { NI: assign },\n };\n}\n\n/** Write the unlit material-UBO slice. */\nexport function writeUnlitUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n if (!material.unlit || !offsets.has(\"unlitColor\")) {\n return;\n }\n const off = offsets.get(\"unlitColor\")! / 4;\n const tint = material.unlitColor ?? [1, 1, 1];\n data[off] = tint[0]!;\n data[off + 1] = tint[1]!;\n data[off + 2] = tint[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"unlit\",\n phase: \"fragment\",\n detect(mat) {\n return (mat as PbrMaterialProps).unlit ? { f: 0, f2: PBR2_HAS_UNLIT } : { f: 0, f2: 0 };\n },\n frag(ctx) {\n if (!(ctx._features2 & PBR2_HAS_UNLIT)) {\n return null;\n }\n return createUnlitFragment(ctx._hasIbl);\n },\n writeUbo: writeUnlitUBO as PbrExt[\"writeUbo\"],\n};\n"],"names":[],"mappings":";AAiBO,SAAS,oBAAoB,QAAiC;AACjE,QAAM,SAAS;AACf,SAAO;AAAA,IACH,KAAK;AAAA,IACL,eAAe,SAAS,CAAC,KAAK,IAAI;AAAA,IAClC,YAAY;AAAA,MACR,EAAE,OAAO,cAAc,OAAO,YAAA;AAAA,MAC9B,EAAE,OAAO,kBAAkB,OAAO,MAAA;AAAA,IAAM;AAAA,IAE5C,gBAAgB,SAAS,EAAE,IAAI,WAAW,EAAE,IAAI,OAAA;AAAA,EAAO;AAE/D;AAGO,SAAS,cAAc,MAAoB,UAA4B,SAA4C;AACtH,MAAI,CAAC,SAAS,SAAS,CAAC,QAAQ,IAAI,YAAY,GAAG;AAC/C;AAAA,EACJ;AACA,QAAM,MAAM,QAAQ,IAAI,YAAY,IAAK;AACzC,QAAM,OAAO,SAAS,cAAc,CAAC,GAAG,GAAG,CAAC;AAC5C,OAAK,GAAG,IAAI,KAAK,CAAC;AAClB,OAAK,MAAM,CAAC,IAAI,KAAK,CAAC;AACtB,OAAK,MAAM,CAAC,IAAI,KAAK,CAAC;AAC1B;AAEO,MAAM,SAAiB;AAAA,EAC1B,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,OAAO,KAAK;AACR,WAAQ,IAAyB,QAAQ,EAAE,GAAG,GAAG,IAAI,eAAA,IAAmB,EAAE,GAAG,GAAG,IAAI,EAAA;AAAA,EACxF;AAAA,EACA,KAAK,KAAK;AACN,QAAI,EAAE,IAAI,aAAa,iBAAiB;AACpC,aAAO;AAAA,IACX;AACA,WAAO,oBAAoB,IAAI,OAAO;AAAA,EAC1C;AAAA,EACA,UAAU;AACd;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"gltf-interleave-DWf27t-h.js","sources":["../src/loader-gltf/gltf-interleave.ts"],"sourcesContent":["/**\n * Interleaved (strided) glTF vertex-buffer support — dynamically imported.\n *\n * The engine renders interleaved attributes genuinely: the raw strided\n * bufferView slice is uploaded ONCE as a shared GPU buffer and bound to each\n * attribute at its byte offset with the pipeline's vertex `arrayStride` set to\n * the bufferView byteStride. The loader never rewrites the asset.\n *\n * This whole module is loaded via `await import()` only when an asset actually\n * contains an interleaved bufferView, so non-interleaved scenes pay ZERO bundle\n * cost. The tight CPU copy of position/normal/uv (for AABB, picking, CSG, …) is\n * de-strided LAZILY — only on first CPU read via `installLazyCpu` — so scenes\n * that only render never materialize it.\n */\n\nimport { F32, U32, U16, U8, DV } from \"../engine/typed-arrays.js\";\nimport { BU } from \"../engine/gpu-flags.js\";\nimport type { Mat4 } from \"../math/types.js\";\nimport type { Aabb } from \"../math/aabb.js\";\nimport { computeAabb } from \"../math/compute-aabb.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mesh, MeshGPU } from \"../mesh/mesh.js\";\nimport { initMeshTransform } from \"../mesh/mesh.js\";\nimport type { PbrMaterialProps } from \"../material/pbr/pbr-material.js\";\nimport { createMappedBuffer } from \"../resource/gpu-buffers.js\";\nimport { resolveAccessor, TYPE_SIZES } from \"./gltf-parser.js\";\nimport type { GltfMeshData } from \"./load-gltf.js\";\n\nconst FLOAT = 5126;\nconst UNSIGNED_SHORT = 5123;\nconst UNSIGNED_INT = 5125;\nconst UNSIGNED_BYTE = 5121;\n\nconst COMP_BYTES: Record<number, number> = { [UNSIGNED_BYTE]: 1, [UNSIGNED_SHORT]: 2, [UNSIGNED_INT]: 4, [FLOAT]: 4 };\n\n/** Interleave descriptor for one attribute sourced from a strided bufferView.\n * The raw slice is shared across attributes of the same bufferView; the\n * pipeline uses `_stride` as arrayStride and binds at `_offset`. */\nexport interface AccessorInterleave {\n /** @internal glTF bufferView index — shared-buffer key (same view → one GPU buffer). */\n _bufferView: number;\n /** @internal Interleave byte stride (bufferView.byteStride) → pipeline arrayStride. */\n _stride: number;\n /** @internal Attribute byte offset within the bufferView → setVertexBuffer bind offset. */\n _offset: number;\n /** @internal glTF component type (FLOAT, UNSIGNED_SHORT, …). */\n _componentType: number;\n /** @internal Components per vertex. */\n _componentCount: number;\n /** @internal Vertex count. */\n _count: number;\n /** @internal Raw bufferView bytes (shared across attributes). Retained after GPU upload\n * so the CPU copy can be de-strided lazily on demand. */\n _slice?: Uint8Array;\n}\n\n/** Per-attribute interleave sources for a primitive (keys mirror MeshVbLayout). */\nexport interface GltfVb {\n /** @internal */\n _p?: AccessorInterleave;\n /** @internal */\n _n?: AccessorInterleave;\n /** @internal */\n _t?: AccessorInterleave;\n /** @internal */\n _u?: AccessorInterleave;\n /** @internal */\n _u2?: AccessorInterleave;\n /** @internal */\n _c?: AccessorInterleave;\n}\n\n/** True if accessor `idx`'s bufferView is interleaved (byteStride present and\n * larger than the attribute's tightly-packed element size). */\nexport function accessorIsStrided(json: any, idx: number): boolean {\n const a = json.accessors[idx];\n const bv = json.bufferViews[a.bufferView];\n const stride: number | undefined = bv.byteStride;\n if (stride === undefined) {\n return false;\n }\n const elemBytes = (TYPE_SIZES[a.type] ?? 1) * (COMP_BYTES[a.componentType] ?? 4);\n return stride !== elemBytes;\n}\n\n/** Resolve a strided accessor into an {@link AccessorInterleave} descriptor. */\nfunction resolveStrided(json: any, binChunk: DataView, accessorIdx: number): AccessorInterleave {\n const accessor = json.accessors[accessorIdx];\n const bufferView = json.bufferViews[accessor.bufferView];\n const ab = binChunk.buffer as ArrayBuffer;\n return {\n _bufferView: accessor.bufferView,\n _stride: bufferView.byteStride,\n _offset: accessor.byteOffset ?? 0,\n _componentType: accessor.componentType,\n _componentCount: TYPE_SIZES[accessor.type] ?? 1,\n _count: accessor.count,\n _slice: new U8(ab, binChunk.byteOffset + (bufferView.byteOffset ?? 0), bufferView.byteLength),\n };\n}\n\n/** De-stride an interleaved attribute into a tight Float32Array, reading raw\n * component values (no normalization) so the result matches what a tight\n * accessor view would have produced. */\nfunction destrideToTight(il: AccessorInterleave): Float32Array {\n const dv = new DV(il._slice!.buffer, il._slice!.byteOffset, il._slice!.byteLength);\n const cb = COMP_BYTES[il._componentType] ?? 4;\n const ct = il._componentType;\n const cc = il._componentCount;\n const out = new F32(il._count * cc);\n for (let v = 0; v < il._count; v++) {\n const rowBase = il._offset + v * il._stride;\n for (let c = 0; c < cc; c++) {\n const off = rowBase + c * cb;\n out[v * cc + c] =\n ct === FLOAT ? dv.getFloat32(off, true) : ct === UNSIGNED_SHORT ? dv.getUint16(off, true) : ct === UNSIGNED_INT ? dv.getUint32(off, true) : dv.getUint8(off);\n }\n }\n return out;\n}\n\n/** Build a mesh-data partial for a primitive, but ONLY if it actually sources\n * ≥1 attribute from an interleaved (strided) bufferView. Returns `undefined`\n * for fully-tight primitives so the caller falls back to its tight path.\n *\n * Strided POSITION/NORMAL/TEXCOORD_0 attributes keep their raw slice in `_vb`\n * (for genuine GPU interleaving) and leave the tight CPU field `null` — the\n * de-strided copy is materialized lazily on first CPU read (see\n * {@link installLazyCpu}). Strided TANGENT/TEXCOORD_1/COLOR are eagerly\n * de-strided (they feed device-lost recovery), but no current asset interleaves\n * them. Tight attributes resolve exactly like the core loader. */\nexport function buildInterleavedPartial(json: any, binChunk: DataView, primitive: any, worldMatrix: Mat4, nodeIdx: number): Omit<GltfMeshData, \"_material\"> | undefined {\n const attrs = primitive.attributes;\n\n // Per-primitive gate: bail (→ tight path) unless a vertex attribute is strided.\n let anyStrided = false;\n for (const name in attrs) {\n if (accessorIsStrided(json, attrs[name])) {\n anyStrided = true;\n break;\n }\n }\n if (!anyStrided) {\n return undefined;\n }\n\n const vb: GltfVb = {};\n let vertexCount = 0;\n\n // Resolve one attribute. Returns the interleave descriptor (when the source is\n // strided) and/or a tight CPU array. `eager` de-strides strided sources up-front\n // (TANGENT/UV2/COLOR feed device-lost recovery); lazy ones leave `_tight` null and\n // are de-strided on demand. The caller assigns `vb.<attr>` with a STATIC property\n // name (never a computed `vb[key]`) — a computed write would stay an unmangled\n // literal while every reader uses the mangled static name, corrupting the object\n // across the dynamic-import chunk boundary.\n const resolveOne = (name: string, eager: boolean): { _tight: Float32Array | null; _il?: AccessorInterleave; _count: number } => {\n const idx = attrs[name];\n if (idx === undefined) {\n return { _tight: null, _count: 0 };\n }\n if (accessorIsStrided(json, idx)) {\n const il = resolveStrided(json, binChunk, idx);\n return { _tight: eager ? destrideToTight(il) : null, _il: il, _count: il._count };\n }\n const av = resolveAccessor(json, binChunk, idx);\n return { _tight: av._data as Float32Array, _count: av._count };\n };\n\n const pos = resolveOne(\"POSITION\", false);\n vb._p = pos._il;\n vertexCount = pos._count;\n const nrm = resolveOne(\"NORMAL\", false);\n vb._n = nrm._il;\n const uv = resolveOne(\"TEXCOORD_0\", false);\n vb._u = uv._il;\n const tan = resolveOne(\"TANGENT\", true);\n vb._t = tan._il;\n const uv2 = resolveOne(\"TEXCOORD_1\", true);\n vb._u2 = uv2._il;\n const col = resolveOne(\"COLOR_0\", true);\n vb._c = col._il;\n\n const positions = pos._tight;\n let normals = nrm._tight;\n let uvs = uv._tight;\n const tangents = tan._tight;\n const uv2s = uv2._tight;\n const colors = col._tight;\n\n // Absent (not merely strided) NORMAL/UV need a tight zero-filled buffer so the\n // GPU has a bindable vertex buffer — matches the core loader's tight path.\n if (!normals && !vb._n) {\n normals = new F32(vertexCount * 3);\n }\n if (!uvs && !vb._u) {\n uvs = new F32(vertexCount * 2);\n }\n\n const idxData = primitive.indices !== undefined ? resolveAccessor(json, binChunk, primitive.indices) : null;\n const indices = idxData\n ? idxData._data instanceof U32\n ? new U32(idxData._data)\n : idxData._data instanceof U8\n ? Uint16Array.from(idxData._data)\n : new U16(idxData._data.buffer, idxData._data.byteOffset, idxData._count)\n : new U16(0);\n\n return {\n _positions: positions,\n _normals: normals,\n _tangents: tangents,\n _uvs: uvs,\n _uv2s: uv2s,\n _colors: colors,\n _indices: indices,\n _vertexCount: vertexCount,\n _indexCount: idxData?._count ?? 0,\n _worldMatrix: worldMatrix,\n _vb: vb,\n _nodeIndex: nodeIdx,\n _primitive: primitive,\n };\n}\n\n/** Build the GPU geometry for an interleaved mesh: one shared buffer per\n * bufferView for strided attributes (bound at offset with arrayStride), tight\n * attributes get their own buffer — byte-identical to non-interleaved meshes.\n * The raw `_slice` is intentionally retained on `_vb` so the CPU copy can be\n * de-strided lazily later (see {@link installLazyCpu}). */\nfunction buildInterleavedGpu(engine: EngineContext, m: GltfMeshData): MeshGPU {\n const vbsrc = m._vb!;\n const shared = new Map<number, GPUBuffer>();\n const vbuf = (a: AccessorInterleave | undefined, tight: Float32Array | null): GPUBuffer | null => {\n if (!a) {\n return tight ? createMappedBuffer(engine, tight, BU.VERTEX) : null;\n }\n let b = shared.get(a._bufferView);\n if (!b) {\n shared.set(a._bufferView, (b = createMappedBuffer(engine, a._slice!, BU.VERTEX)));\n }\n return b;\n };\n return {\n positionBuffer: vbuf(vbsrc._p, m._positions)!,\n normalBuffer: vbuf(vbsrc._n, m._normals)!,\n tangentBuffer: m._tangents ? vbuf(vbsrc._t, m._tangents) : null,\n uvBuffer: vbuf(vbsrc._u, m._uvs)!,\n uv2Buffer: m._uv2s ? vbuf(vbsrc._u2, m._uv2s) : null,\n colorBuffer: m._colors ? vbuf(vbsrc._c, m._colors) : null,\n indexBuffer: createMappedBuffer(engine, m._indices, BU.INDEX),\n indexCount: m._indexCount,\n indexFormat: (m._indices instanceof U32 ? \"uint32\" : \"uint16\") as GPUIndexFormat,\n _vbLayout: vbsrc,\n _vbKey: `vb${vbsrc._p?._stride ?? 0}.${vbsrc._n?._stride ?? 0}.${vbsrc._t?._stride ?? 0}.${vbsrc._u?._stride ?? 0}`,\n };\n}\n\n/** Build a complete engine mesh from interleaved glTF mesh-data. Owns ALL\n * interleave-specific work (GPU upload, AABB fold, lazy CPU install, device-lost\n * retention) so the core loader's tight path stays byte-identical to the\n * non-interleaved engine — keeping interleave bytes out of every glTF scene that\n * doesn't use it. */\nexport function buildInterleavedMesh(engine: EngineContext, m: GltfMeshData, index: number, material: PbrMaterialProps): Mesh {\n const gpu = buildInterleavedGpu(engine, m);\n\n // AABB: fold strided positions straight from the slice; tight positions normally.\n const [boundMin, boundMax] = m._vb!._p ? computeAabbStrided(m._vb!._p, m._worldMatrix) : computeAabb(m._positions!, m._worldMatrix);\n\n const mesh = {\n name: `gltf_mesh_${index}`,\n material,\n receiveShadows: false,\n boundMin,\n boundMax,\n skeleton: null,\n morphTargets: null,\n _gpu: gpu,\n } as unknown as Mesh;\n initMeshTransform(mesh);\n\n // Lazy CPU geometry: the de-strided tight copy is built only on first read.\n installLazyCpu(mesh, m);\n mesh._cpuIndices = m._indices instanceof U32 ? m._indices : new U32(m._indices);\n engine._dlr?.m(mesh, m._uv2s, m._tangents, m._colors, m._indices, gpu.indexFormat);\n\n return mesh as Mesh;\n}\n\n/** Fold an AABB directly over an interleaved (strided) FLOAT vec3 position\n * source — no tight copy is materialized. Mirrors {@link computeAabb}'s\n * world-transform handling. All current interleaved assets use FLOAT positions. */\nexport function computeAabbStrided(il: AccessorInterleave, world?: Mat4): Aabb {\n const dv = new DV(il._slice!.buffer, il._slice!.byteOffset, il._slice!.byteLength);\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n for (let v = 0; v < il._count; v++) {\n const base = il._offset + v * il._stride;\n const lx = dv.getFloat32(base, true);\n const ly = dv.getFloat32(base + 4, true);\n const lz = dv.getFloat32(base + 8, true);\n let x = lx,\n y = ly,\n z = lz;\n if (world) {\n x = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]!;\n y = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]!;\n z = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]!;\n }\n if (x < minX) {\n minX = x;\n }\n if (x > maxX) {\n maxX = x;\n }\n if (y < minY) {\n minY = y;\n }\n if (y > maxY) {\n maxY = y;\n }\n if (z < minZ) {\n minZ = z;\n }\n if (z > maxZ) {\n maxZ = z;\n }\n }\n return [\n [minX, minY, minZ],\n [maxX, maxY, maxZ],\n ];\n}\n\n/** Install lazy CPU-geometry accessors on an interleaved mesh. Each of\n * `_cpuPositions/_cpuNormals/_cpuUvs` that comes from a strided source is\n * defined as a getter that de-strides a tight copy on first access and caches\n * it; tight attributes are assigned directly. A mesh that is never picked /\n * CSG'd / navigated never materializes the de-strided arrays.\n *\n * The property names are written as STATIC literals (not a computed key) so the\n * minifier mangles them identically to the static reads in the picking /\n * device-lost code — a computed `defineProperty(mesh, key)` would leave the name\n * an unmangled literal and mismatch those reads across the chunk boundary. */\nexport function installLazyCpu(mesh: any, m: GltfMeshData): void {\n const vb = m._vb!;\n if (vb._p) {\n Object.defineProperty(mesh, \"_cpuPositions\", lazyCpuDesc(vb._p));\n } else if (m._positions) {\n mesh._cpuPositions = m._positions;\n }\n if (vb._n) {\n Object.defineProperty(mesh, \"_cpuNormals\", lazyCpuDesc(vb._n));\n } else if (m._normals) {\n mesh._cpuNormals = m._normals;\n }\n if (vb._u) {\n Object.defineProperty(mesh, \"_cpuUvs\", lazyCpuDesc(vb._u));\n } else if (m._uvs) {\n mesh._cpuUvs = m._uvs;\n }\n}\n\n/** Build a caching lazy-getter descriptor that de-strides `il` on first read. */\nfunction lazyCpuDesc(il: AccessorInterleave): PropertyDescriptor {\n let cached: Float32Array | undefined;\n return {\n configurable: true,\n enumerable: true,\n get(): Float32Array {\n return (cached ??= destrideToTight(il));\n },\n set(v: Float32Array): void {\n cached = v;\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"gltf-normals-b2h74380.js","sources":["../src/loader-gltf/gltf-normals.ts"],"sourcesContent":["/** glTF smooth-normal generation — dynamically imported.\n *\n * Isolated from the core loader so scenes whose assets always provide the NORMAL\n * attribute (the common case) never bundle or fetch this code. Loaded lazily by\n * `load-gltf.ts` only when a primitive omits NORMAL.\n *\n * Zero module-level side effects — safe for tree-shaking.\n */\n\n/** Compute smooth (area-weighted) vertex normals from positions + indices. Used when a glTF\n * primitive omits the NORMAL attribute (the spec allows this and requires clients to generate\n * normals — e.g. THREE.GLTFExporter output for morph-only meshes). */\nexport function computeSmoothNormals(positions: Float32Array, indices: Uint16Array | Uint32Array, vertexCount: number): Float32Array {\n const normals = new Float32Array(vertexCount * 3);\n const indexed = indices.length > 0;\n const triCount = indexed ? (indices.length / 3) | 0 : (vertexCount / 3) | 0;\n for (let f = 0; f < triCount; f++) {\n const ia = indexed ? indices[f * 3]! : f * 3;\n const ib = indexed ? indices[f * 3 + 1]! : f * 3 + 1;\n const ic = indexed ? indices[f * 3 + 2]! : f * 3 + 2;\n const ax = positions[ia * 3]!,\n ay = positions[ia * 3 + 1]!,\n az = positions[ia * 3 + 2]!;\n const bx = positions[ib * 3]!,\n by = positions[ib * 3 + 1]!,\n bz = positions[ib * 3 + 2]!;\n const cx = positions[ic * 3]!,\n cy = positions[ic * 3 + 1]!,\n cz = positions[ic * 3 + 2]!;\n const e1x = bx - ax,\n e1y = by - ay,\n e1z = bz - az;\n const e2x = cx - ax,\n e2y = cy - ay,\n e2z = cz - az;\n const nx = e1y * e2z - e1z * e2y,\n ny = e1z * e2x - e1x * e2z,\n nz = e1x * e2y - e1y * e2x;\n normals[ia * 3]! += nx;\n normals[ia * 3 + 1]! += ny;\n normals[ia * 3 + 2]! += nz;\n normals[ib * 3]! += nx;\n normals[ib * 3 + 1]! += ny;\n normals[ib * 3 + 2]! += nz;\n normals[ic * 3]! += nx;\n normals[ic * 3 + 1]! += ny;\n normals[ic * 3 + 2]! += nz;\n }\n for (let i = 0; i < vertexCount; i++) {\n const x = normals[i * 3]!,\n y = normals[i * 3 + 1]!,\n z = normals[i * 3 + 2]!;\n const len = Math.hypot(x, y, z) || 1;\n normals[i * 3] = x / len;\n normals[i * 3 + 1] = y / len;\n normals[i * 3 + 2] = z / len;\n }\n return normals;\n}\n"],"names":[],"mappings":"AAYO,SAAS,qBAAqB,WAAyB,SAAoC,aAAmC;AACjI,QAAM,UAAU,IAAI,aAAa,cAAc,CAAC;AAChD,QAAM,UAAU,QAAQ,SAAS;AACjC,QAAM,WAAW,UAAW,QAAQ,SAAS,IAAK,IAAK,cAAc,IAAK;AAC1E,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAC/B,UAAM,KAAK,UAAU,QAAQ,IAAI,CAAC,IAAK,IAAI;AAC3C,UAAM,KAAK,UAAU,QAAQ,IAAI,IAAI,CAAC,IAAK,IAAI,IAAI;AACnD,UAAM,KAAK,UAAU,QAAQ,IAAI,IAAI,CAAC,IAAK,IAAI,IAAI;AACnD,UAAM,KAAK,UAAU,KAAK,CAAC,GACvB,KAAK,UAAU,KAAK,IAAI,CAAC,GACzB,KAAK,UAAU,KAAK,IAAI,CAAC;AAC7B,UAAM,KAAK,UAAU,KAAK,CAAC,GACvB,KAAK,UAAU,KAAK,IAAI,CAAC,GACzB,KAAK,UAAU,KAAK,IAAI,CAAC;AAC7B,UAAM,KAAK,UAAU,KAAK,CAAC,GACvB,KAAK,UAAU,KAAK,IAAI,CAAC,GACzB,KAAK,UAAU,KAAK,IAAI,CAAC;AAC7B,UAAM,MAAM,KAAK,IACb,MAAM,KAAK,IACX,MAAM,KAAK;AACf,UAAM,MAAM,KAAK,IACb,MAAM,KAAK,IACX,MAAM,KAAK;AACf,UAAM,KAAK,MAAM,MAAM,MAAM,KACzB,KAAK,MAAM,MAAM,MAAM,KACvB,KAAK,MAAM,MAAM,MAAM;AAC3B,YAAQ,KAAK,CAAC,KAAM;AACpB,YAAQ,KAAK,IAAI,CAAC,KAAM;AACxB,YAAQ,KAAK,IAAI,CAAC,KAAM;AACxB,YAAQ,KAAK,CAAC,KAAM;AACpB,YAAQ,KAAK,IAAI,CAAC,KAAM;AACxB,YAAQ,KAAK,IAAI,CAAC,KAAM;AACxB,YAAQ,KAAK,CAAC,KAAM;AACpB,YAAQ,KAAK,IAAI,CAAC,KAAM;AACxB,YAAQ,KAAK,IAAI,CAAC,KAAM;AAAA,EAC5B;AACA,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,UAAM,IAAI,QAAQ,IAAI,CAAC,GACnB,IAAI,QAAQ,IAAI,IAAI,CAAC,GACrB,IAAI,QAAQ,IAAI,IAAI,CAAC;AACzB,UAAM,MAAM,KAAK,MAAM,GAAG,GAAG,CAAC,KAAK;AACnC,YAAQ,IAAI,CAAC,IAAI,IAAI;AACrB,YAAQ,IAAI,IAAI,CAAC,IAAI,IAAI;AACzB,YAAQ,IAAI,IAAI,CAAC,IAAI,IAAI;AAAA,EAC7B;AACA,SAAO;AACX;"}