@forgeax/engine-render 0.1.21 → 0.1.24

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 (584) hide show
  1. package/README.md +281 -38
  2. package/dist/assembly/backend-contract.d.ts +13 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/bundler-contract.d.ts +9 -0
  5. package/dist/assembly/bundler-contract.d.ts.map +1 -0
  6. package/dist/assembly/device-feature-admission.d.ts +8 -0
  7. package/dist/assembly/device-feature-admission.d.ts.map +1 -1
  8. package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
  9. package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
  10. package/dist/assembly/factory.d.ts +7 -235
  11. package/dist/assembly/factory.d.ts.map +1 -1
  12. package/dist/assembly/host-contract.d.ts +10 -0
  13. package/dist/assembly/host-contract.d.ts.map +1 -1
  14. package/dist/assembly/material/assembly.d.ts +3 -2
  15. package/dist/assembly/material/assembly.d.ts.map +1 -1
  16. package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
  17. package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
  18. package/dist/assembly/material-shader-policy.d.ts +168 -0
  19. package/dist/assembly/material-shader-policy.d.ts.map +1 -0
  20. package/dist/assembly/material-shader-prewarm.d.ts +21 -0
  21. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
  22. package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
  23. package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
  24. package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
  26. package/dist/assembly/recovery/generation.d.ts +46 -0
  27. package/dist/assembly/recovery/generation.d.ts.map +1 -0
  28. package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
  29. package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
  30. package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
  31. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
  32. package/dist/assembly/renderer-facade.d.ts +10 -0
  33. package/dist/assembly/renderer-facade.d.ts.map +1 -0
  34. package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
  35. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  36. package/dist/assembly/renderer-helpers.d.ts +19 -0
  37. package/dist/assembly/renderer-helpers.d.ts.map +1 -0
  38. package/dist/assembly/renderer-lifecycle.d.ts +34 -0
  39. package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
  40. package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
  41. package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
  42. package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
  43. package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
  44. package/dist/assembly/webgpu-ready.d.ts +55 -0
  45. package/dist/assembly/webgpu-ready.d.ts.map +1 -0
  46. package/dist/assembly/webgpu-renderer.d.ts +152 -0
  47. package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
  48. package/dist/authoring.mjs +1 -1
  49. package/dist/{chunk-PCHBPYML.mjs → chunk-GE3SDD72.mjs} +37 -5
  50. package/dist/chunk-GE3SDD72.mjs.map +1 -0
  51. package/dist/chunk-KZFTK6DO.mjs +1191 -0
  52. package/dist/chunk-KZFTK6DO.mjs.map +1 -0
  53. package/dist/{chunk-FS2KNUQH.mjs → chunk-Q752SHI5.mjs} +332 -568
  54. package/dist/chunk-Q752SHI5.mjs.map +1 -0
  55. package/dist/{chunk-6OPXDQ2E.mjs → chunk-RR5L4SRS.mjs} +33 -294
  56. package/dist/chunk-RR5L4SRS.mjs.map +1 -0
  57. package/dist/chunk-TFH5I7JJ.mjs +296 -0
  58. package/dist/chunk-TFH5I7JJ.mjs.map +1 -0
  59. package/dist/chunk-UQYS7FRM.mjs +1003 -0
  60. package/dist/chunk-UQYS7FRM.mjs.map +1 -0
  61. package/dist/chunk-YKB5DQV7.mjs +345 -0
  62. package/dist/chunk-YKB5DQV7.mjs.map +1 -0
  63. package/dist/{chunk-5YADUCA7.mjs → chunk-YRUYGA4A.mjs} +1189 -1217
  64. package/dist/chunk-YRUYGA4A.mjs.map +1 -0
  65. package/dist/chunk-Z3YYH2MB.mjs +5082 -0
  66. package/dist/chunk-Z3YYH2MB.mjs.map +1 -0
  67. package/dist/cluster-binner.d.ts +5 -0
  68. package/dist/cluster-binner.d.ts.map +1 -1
  69. package/dist/components/index.d.ts +3 -0
  70. package/dist/components/index.d.ts.map +1 -1
  71. package/dist/components/light-helpers.d.ts +4 -0
  72. package/dist/components/light-helpers.d.ts.map +1 -1
  73. package/dist/components/light-probe.d.ts +9 -0
  74. package/dist/components/light-probe.d.ts.map +1 -0
  75. package/dist/components/rect-area-light.d.ts +12 -0
  76. package/dist/components/rect-area-light.d.ts.map +1 -0
  77. package/dist/components/scene-instance.d.ts +4 -0
  78. package/dist/components/scene-instance.d.ts.map +1 -1
  79. package/dist/components/spot-light.d.ts +3 -0
  80. package/dist/components/spot-light.d.ts.map +1 -1
  81. package/dist/construct-renderer.mjs +27276 -23232
  82. package/dist/construct-renderer.mjs.map +1 -1
  83. package/dist/device/device-scope.d.ts +2 -0
  84. package/dist/device/device-scope.d.ts.map +1 -1
  85. package/dist/device/gpu-residency.d.ts +32 -5
  86. package/dist/device/gpu-residency.d.ts.map +1 -1
  87. package/dist/device/lifecycle-transaction.d.ts +2 -0
  88. package/dist/device/lifecycle-transaction.d.ts.map +1 -0
  89. package/dist/environment/frame.d.ts +5 -0
  90. package/dist/environment/frame.d.ts.map +1 -1
  91. package/dist/environment/inspection.d.ts +7 -0
  92. package/dist/environment/inspection.d.ts.map +1 -1
  93. package/dist/environment/lifecycle.d.ts +20 -2
  94. package/dist/environment/lifecycle.d.ts.map +1 -1
  95. package/dist/errors/gpu-driven.d.ts +26 -0
  96. package/dist/errors/gpu-driven.d.ts.map +1 -0
  97. package/dist/errors/index.d.ts +1 -0
  98. package/dist/errors/index.d.ts.map +1 -1
  99. package/dist/errors/recover.d.ts +67 -3
  100. package/dist/errors/recover.d.ts.map +1 -1
  101. package/dist/errors/render.d.ts +39 -1
  102. package/dist/errors/render.d.ts.map +1 -1
  103. package/dist/extract/contracts.d.ts +899 -0
  104. package/dist/extract/contracts.d.ts.map +1 -0
  105. package/dist/extract/gpu-driven.d.ts +50 -0
  106. package/dist/extract/gpu-driven.d.ts.map +1 -0
  107. package/dist/extract/visibility.d.ts.map +1 -1
  108. package/dist/features/host.d.ts +2 -0
  109. package/dist/features/host.d.ts.map +1 -1
  110. package/dist/features/prepared-gpu-work.d.ts +3 -0
  111. package/dist/features/prepared-gpu-work.d.ts.map +1 -1
  112. package/dist/features/prepared-graphics-store.d.ts +2 -0
  113. package/dist/features/prepared-graphics-store.d.ts.map +1 -1
  114. package/dist/gpu-driven/batch-topology.d.ts +34 -0
  115. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  116. package/dist/gpu-driven/prepared-draw.d.ts +63 -0
  117. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -0
  118. package/dist/gpu-driven/production-raster.d.ts +126 -2
  119. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  120. package/dist/gpu-driven/view-gpu.d.ts +64 -1
  121. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  122. package/dist/gpu-scene-schema.d.ts +14 -0
  123. package/dist/gpu-scene-schema.d.ts.map +1 -1
  124. package/dist/gpu-scene.d.ts +9 -1
  125. package/dist/gpu-scene.d.ts.map +1 -1
  126. package/dist/gpu-usage.d.ts +0 -1
  127. package/dist/gpu-usage.d.ts.map +1 -1
  128. package/dist/hdrp-buffers.d.ts +3 -3
  129. package/dist/hdrp-buffers.d.ts.map +1 -1
  130. package/dist/ibl/IblPipelineCache.d.ts +7 -6
  131. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  132. package/dist/ibl/skylight-bind-group.d.ts +7 -1
  133. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  134. package/dist/index.d.ts +13 -2
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.mjs +90 -5
  137. package/dist/index.mjs.map +1 -1
  138. package/dist/inspection-types.d.ts +163 -1
  139. package/dist/inspection-types.d.ts.map +1 -1
  140. package/dist/internal.d.ts +9 -0
  141. package/dist/internal.d.ts.map +1 -1
  142. package/dist/internal.mjs +23 -2
  143. package/dist/internal.mjs.map +1 -1
  144. package/dist/light-buffer-layout.d.ts +60 -148
  145. package/dist/light-buffer-layout.d.ts.map +1 -1
  146. package/dist/materials.d.ts +34 -10
  147. package/dist/materials.d.ts.map +1 -1
  148. package/dist/mesh-material-bindings.d.ts +56 -0
  149. package/dist/mesh-material-bindings.d.ts.map +1 -1
  150. package/dist/occlusion-proxy.d.ts +4 -0
  151. package/dist/occlusion-proxy.d.ts.map +1 -0
  152. package/dist/pbr-pipeline.d.ts +58 -21
  153. package/dist/pbr-pipeline.d.ts.map +1 -1
  154. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  155. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -1
  156. package/dist/pipeline/standard-lighting/light-frame.d.ts +3 -3
  157. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -1
  158. package/dist/pipeline/standard-lighting/topology.d.ts +1 -1
  159. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -1
  160. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -1
  161. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  162. package/dist/pipeline-builder.d.ts +2 -0
  163. package/dist/pipeline-builder.d.ts.map +1 -1
  164. package/dist/pipeline-spec.d.ts +1 -1
  165. package/dist/pipeline-spec.d.ts.map +1 -1
  166. package/dist/plugin.d.ts.map +1 -1
  167. package/dist/points-lines/prepare.d.ts +3 -0
  168. package/dist/points-lines/prepare.d.ts.map +1 -1
  169. package/dist/points-lines/standard-owner.d.ts +33 -0
  170. package/dist/points-lines/standard-owner.d.ts.map +1 -0
  171. package/dist/prepare/extended-lighting/ltc-resources.d.ts +31 -0
  172. package/dist/prepare/extended-lighting/ltc-resources.d.ts.map +1 -0
  173. package/dist/prepare/extended-lighting/resources.d.ts +72 -0
  174. package/dist/prepare/extended-lighting/resources.d.ts.map +1 -0
  175. package/dist/prepare/extended-lighting/spot-modifiers.d.ts +42 -0
  176. package/dist/prepare/extended-lighting/spot-modifiers.d.ts.map +1 -0
  177. package/dist/prepare/extended-lighting/state.d.ts +24 -0
  178. package/dist/prepare/extended-lighting/state.d.ts.map +1 -0
  179. package/dist/record/frame-lighting.d.ts +8 -6
  180. package/dist/record/frame-lighting.d.ts.map +1 -1
  181. package/dist/record/frame-snapshot.d.ts +55 -10
  182. package/dist/record/frame-snapshot.d.ts.map +1 -1
  183. package/dist/record/frame-targets.d.ts.map +1 -1
  184. package/dist/record/frame.d.ts +21 -5
  185. package/dist/record/frame.d.ts.map +1 -1
  186. package/dist/record/gpu-timing.d.ts +19 -7
  187. package/dist/record/gpu-timing.d.ts.map +1 -1
  188. package/dist/record/helpers.d.ts +0 -20
  189. package/dist/record/helpers.d.ts.map +1 -1
  190. package/dist/record/main-pass-geometry.d.ts +20 -2
  191. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  192. package/dist/record/main-pass-material.d.ts +10 -18
  193. package/dist/record/main-pass-material.d.ts.map +1 -1
  194. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  195. package/dist/record/main-pass.d.ts.map +1 -1
  196. package/dist/record/mesh-ssbo.d.ts +11 -3
  197. package/dist/record/mesh-ssbo.d.ts.map +1 -1
  198. package/dist/record/recovery-pipeline.d.ts +30 -0
  199. package/dist/record/recovery-pipeline.d.ts.map +1 -0
  200. package/dist/record/render-context.d.ts +82 -9
  201. package/dist/record/render-context.d.ts.map +1 -1
  202. package/dist/record/shadow-pass.d.ts.map +1 -1
  203. package/dist/record/typed-frame-graph.d.ts +49 -2
  204. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  205. package/dist/record/view-ubo.d.ts +1 -2
  206. package/dist/record/view-ubo.d.ts.map +1 -1
  207. package/dist/recovery/render-system-candidate.d.ts +65 -0
  208. package/dist/recovery/render-system-candidate.d.ts.map +1 -0
  209. package/dist/reflection/inspection.d.ts +10 -0
  210. package/dist/reflection/inspection.d.ts.map +1 -0
  211. package/dist/reflection/projection.d.ts +49 -0
  212. package/dist/reflection/projection.d.ts.map +1 -1
  213. package/dist/reflection/record-owner.d.ts +60 -0
  214. package/dist/reflection/record-owner.d.ts.map +1 -0
  215. package/dist/render-contract.d.ts +78 -15
  216. package/dist/render-contract.d.ts.map +1 -1
  217. package/dist/render-pipeline.d.ts +7 -0
  218. package/dist/render-pipeline.d.ts.map +1 -1
  219. package/dist/render-system-extract-tail.d.ts +12 -0
  220. package/dist/render-system-extract-tail.d.ts.map +1 -0
  221. package/dist/render-system-extract.d.ts +252 -30
  222. package/dist/render-system-extract.d.ts.map +1 -1
  223. package/dist/render-system.d.ts +140 -5
  224. package/dist/render-system.d.ts.map +1 -1
  225. package/dist/scene/probe-blend-record.d.ts +22 -0
  226. package/dist/scene/probe-blend-record.d.ts.map +1 -0
  227. package/dist/scene/probe-blend.d.ts +142 -0
  228. package/dist/scene/probe-blend.d.ts.map +1 -0
  229. package/dist/scene/render-scene-types.d.ts +0 -6
  230. package/dist/scene/render-scene-types.d.ts.map +1 -1
  231. package/dist/scene/render-scene.d.ts +122 -9
  232. package/dist/scene/render-scene.d.ts.map +1 -1
  233. package/dist/scene/visibility/bounds.d.ts +20 -0
  234. package/dist/scene/visibility/bounds.d.ts.map +1 -0
  235. package/dist/scene/visibility/budget.d.ts +16 -0
  236. package/dist/scene/visibility/budget.d.ts.map +1 -0
  237. package/dist/scene/visibility/facet.d.ts +73 -0
  238. package/dist/scene/visibility/facet.d.ts.map +1 -0
  239. package/dist/scene/visibility/gpu-frame-timing.d.ts +41 -0
  240. package/dist/scene/visibility/gpu-frame-timing.d.ts.map +1 -0
  241. package/dist/scene/visibility/gpu-lod.d.ts +46 -0
  242. package/dist/scene/visibility/gpu-lod.d.ts.map +1 -0
  243. package/dist/scene/visibility/inspection.d.ts +132 -0
  244. package/dist/scene/visibility/inspection.d.ts.map +1 -0
  245. package/dist/scene/visibility/lod-selector.d.ts +25 -0
  246. package/dist/scene/visibility/lod-selector.d.ts.map +1 -0
  247. package/dist/scene/visibility/occlusion-confidence.d.ts +81 -0
  248. package/dist/scene/visibility/occlusion-confidence.d.ts.map +1 -0
  249. package/dist/scene/visibility/occlusion-pass.d.ts +57 -0
  250. package/dist/scene/visibility/occlusion-pass.d.ts.map +1 -0
  251. package/dist/scene/visibility/occlusion-query-pool.d.ts +57 -0
  252. package/dist/scene/visibility/occlusion-query-pool.d.ts.map +1 -0
  253. package/dist/scene/visibility/occlusion-runtime.d.ts +96 -0
  254. package/dist/scene/visibility/occlusion-runtime.d.ts.map +1 -0
  255. package/dist/scene/visibility/types.d.ts +34 -0
  256. package/dist/scene/visibility/types.d.ts.map +1 -0
  257. package/dist/ssr/admission.d.ts +122 -0
  258. package/dist/ssr/admission.d.ts.map +1 -0
  259. package/dist/ssr/composition.d.ts +32 -0
  260. package/dist/ssr/composition.d.ts.map +1 -0
  261. package/dist/ssr/errors.d.ts +39 -0
  262. package/dist/ssr/errors.d.ts.map +1 -0
  263. package/dist/ssr/identity.d.ts +13 -0
  264. package/dist/ssr/identity.d.ts.map +1 -0
  265. package/dist/systems/skin-palette-allocator.d.ts +1 -1
  266. package/dist/temporal/frame-coordinator.d.ts +13 -0
  267. package/dist/temporal/frame-coordinator.d.ts.map +1 -1
  268. package/dist/temporal/frame.d.ts +2 -0
  269. package/dist/temporal/frame.d.ts.map +1 -1
  270. package/dist/temporal/index.mjs +6 -5
  271. package/dist/temporal/taa-history-store.d.ts +15 -1
  272. package/dist/temporal/taa-history-store.d.ts.map +1 -1
  273. package/dist/temporal/transaction.d.ts +5 -0
  274. package/dist/temporal/transaction.d.ts.map +1 -1
  275. package/dist/temporal/view.d.ts +7 -0
  276. package/dist/temporal/view.d.ts.map +1 -1
  277. package/dist/tilemap-chunk-extract-system.d.ts +1 -1
  278. package/dist/typed-render-graph-primitives.d.ts +4 -0
  279. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  280. package/dist/volume/passes.d.ts +8 -4
  281. package/dist/volume/passes.d.ts.map +1 -1
  282. package/package.json +20 -20
  283. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +5 -0
  284. package/src/__tests__/detached-inspection.integration.test.ts +6 -0
  285. package/src/__tests__/device-feature-admission.unit.test.ts +19 -1
  286. package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
  287. package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
  288. package/src/__tests__/direct-light-snapshot.unit.test.ts +59 -3
  289. package/src/__tests__/environment-generation.integration.test.ts +39 -0
  290. package/src/__tests__/evidence-identity.ts +13 -0
  291. package/src/__tests__/evidence-identity.unit.test.ts +24 -0
  292. package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
  293. package/src/__tests__/extended-lighting-recovery.browser.test.ts +14 -0
  294. package/src/__tests__/extended-lighting-recovery.dawn.test.ts +14 -0
  295. package/src/__tests__/extended-lighting-recovery.integration.test.ts +81 -0
  296. package/src/__tests__/extended-lighting-resources.unit.test.ts +51 -0
  297. package/src/__tests__/extended-lighting-zero-feature.integration.test.ts +52 -0
  298. package/src/__tests__/factory-contract.integration.test.ts +154 -6
  299. package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
  300. package/src/__tests__/frame-observation.contract.test.ts +15 -0
  301. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +146 -0
  302. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +1 -0
  303. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +1 -0
  304. package/src/__tests__/gpu-driven-production.integration.test.ts +572 -9
  305. package/src/__tests__/gpu-driven-scaling.unit.test.ts +66 -2
  306. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +26 -1
  307. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +89 -2
  308. package/src/__tests__/gpu-driven-view.browser.test.ts +3 -3
  309. package/src/__tests__/gpu-driven-view.dawn.test.ts +3 -3
  310. package/src/__tests__/gpu-driven-view.unit.test.ts +50 -0
  311. package/src/__tests__/gpu-lod-evidence.ts +188 -0
  312. package/src/__tests__/gpu-lod-fallback.integration.test.ts +10 -0
  313. package/src/__tests__/gpu-lod-indirect.integration.test.ts +40 -0
  314. package/src/__tests__/gpu-lod-parity.dawn.test.ts +29 -0
  315. package/src/__tests__/gpu-lod-readiness.integration.test.ts +52 -0
  316. package/src/__tests__/gpu-lod-schema.unit.test.ts +66 -0
  317. package/src/__tests__/gpu-lod-selector.unit.test.ts +28 -0
  318. package/src/__tests__/gpu-lod-silhouette.browser.test.ts +13 -0
  319. package/src/__tests__/gpu-resource-store-stride.unit.test.ts +66 -1
  320. package/src/__tests__/gpu-scene.dawn.test.ts +8 -1
  321. package/src/__tests__/gpu-scene.unit.test.ts +49 -3
  322. package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
  323. package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
  324. package/src/__tests__/light-buffer-layout.unit.test.ts +113 -3
  325. package/src/__tests__/light-inspection.unit.test.ts +55 -0
  326. package/src/__tests__/light-resource-error.unit.test.ts +43 -0
  327. package/src/__tests__/lighting-scene-roundtrip.integration.test.ts +109 -0
  328. package/src/__tests__/lod-bounds.unit.test.ts +42 -0
  329. package/src/__tests__/lod-cpu-lane.integration.test.ts +55 -0
  330. package/src/__tests__/lod-cpu-no-change.perf.test.ts +19 -0
  331. package/src/__tests__/lod-gpu-frame-timing.unit.test.ts +49 -0
  332. package/src/__tests__/lod-multi-view.integration.test.ts +63 -0
  333. package/src/__tests__/lod-occlusion-device-loss.integration.test.ts +27 -0
  334. package/src/__tests__/lod-occlusion-final-decision.integration.test.ts +47 -0
  335. package/src/__tests__/lod-occlusion-inspection.integration.test.ts +217 -0
  336. package/src/__tests__/lod-occlusion-inspection.schema.test-d.ts +14 -0
  337. package/src/__tests__/lod-occlusion-inspection.unit.test.ts +72 -0
  338. package/src/__tests__/lod-occlusion-visual-evidence.ts +91 -0
  339. package/src/__tests__/lod-occlusion.browser.test.ts +15 -0
  340. package/src/__tests__/lod-occlusion.dawn.test.ts +20 -0
  341. package/src/__tests__/lod-selector.profile.test.ts +35 -0
  342. package/src/__tests__/lod-selector.unit.test.ts +68 -0
  343. package/src/__tests__/lod-visibility-identity.unit.test.ts +198 -0
  344. package/src/__tests__/lod-visibility-lifecycle.integration.test.ts +132 -0
  345. package/src/__tests__/ltc-resources.unit.test.ts +32 -0
  346. package/src/__tests__/material-contract-inventory.unit.test.ts +41 -9
  347. package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
  348. package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
  349. package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
  350. package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
  351. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  352. package/src/__tests__/occlusion-confidence.unit.test.ts +168 -0
  353. package/src/__tests__/occlusion-invalidation.integration.test.ts +37 -0
  354. package/src/__tests__/occlusion-pass-routing.unit.test.ts +16 -0
  355. package/src/__tests__/occlusion-pass.dawn.test.ts +20 -0
  356. package/src/__tests__/occlusion-pass.integration.test.ts +43 -0
  357. package/src/__tests__/occlusion-pass.rhi-null.test.ts +22 -0
  358. package/src/__tests__/occlusion-query-pool.rhi-null.test.ts +21 -0
  359. package/src/__tests__/occlusion-query-pool.unit.test.ts +95 -0
  360. package/src/__tests__/occlusion-query-ticket.integration.test.ts +47 -0
  361. package/src/__tests__/occlusion-query.dawn.test.ts +16 -0
  362. package/src/__tests__/occlusion-query.evidence.ts +178 -0
  363. package/src/__tests__/occlusion-query.rhi-null.test.ts +31 -0
  364. package/src/__tests__/occlusion-runtime.unit.test.ts +120 -0
  365. package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
  366. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +196 -0
  367. package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
  368. package/src/__tests__/probe-bindings.unit.test.ts +200 -0
  369. package/src/__tests__/probe-blend-numeric.unit.test.ts +67 -0
  370. package/src/__tests__/probe-blend-oracle.unit.test.ts +136 -0
  371. package/src/__tests__/probe-capacity.integration.test.ts +97 -0
  372. package/src/__tests__/probe-recovery.integration.test.ts +104 -0
  373. package/src/__tests__/probe-scene-dirty.integration.test.ts +211 -0
  374. package/src/__tests__/profiler-phase-catalog.test.ts +4 -1
  375. package/src/__tests__/profiler-phase-token.test.ts +1 -0
  376. package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
  377. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
  378. package/src/__tests__/rect-area-boundary.unit.test.ts +24 -0
  379. package/src/__tests__/reflection-fallback-graph.unit.test.ts +67 -0
  380. package/src/__tests__/reflection-fallback-inspection.unit.test.ts +77 -0
  381. package/src/__tests__/reflection-fallback-lifecycle.integration.test.ts +21 -0
  382. package/src/__tests__/reflection-fallback-projection.unit.test.ts +90 -0
  383. package/src/__tests__/reflection-fallback-source.unit.test.ts +32 -0
  384. package/src/__tests__/reflection-probe-owner-placement.unit.test.ts +39 -0
  385. package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +120 -0
  386. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  387. package/src/__tests__/render-feature-docs.unit.test.ts +12 -7
  388. package/src/__tests__/render-graph-fallback.integration.test.ts +24 -0
  389. package/src/__tests__/render-perf/extended-lighting.bench.test.ts +66 -0
  390. package/src/__tests__/render-scene-projection.unit.test.ts +447 -18
  391. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +160 -17
  392. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
  393. package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
  394. package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
  395. package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
  396. package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
  397. package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
  398. package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
  399. package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
  400. package/src/__tests__/shader-manifest-fixture.ts +13 -16
  401. package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
  402. package/src/__tests__/skin-motion-regression.unit.test.ts +22 -0
  403. package/src/__tests__/skinned-shadow-caster.test.ts +2 -2
  404. package/src/__tests__/spot-modifier-projection.unit.test.ts +70 -0
  405. package/src/__tests__/ssr-admission-matrix.integration.test.ts +206 -0
  406. package/src/__tests__/ssr-composition.unit.test.ts +46 -0
  407. package/src/__tests__/ssr-fallback-zero-work.bench.test.ts +94 -0
  408. package/src/__tests__/ssr-recovery-errors.unit.test.ts +58 -0
  409. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +67 -0
  410. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +7 -0
  411. package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
  412. package/src/__tests__/standard-lighting-inspection.integration.test.ts +1 -1
  413. package/src/__tests__/standard-lighting-write.unit.test.ts +66 -2
  414. package/src/__tests__/temporal-fallback-generation.integration.test.ts +16 -0
  415. package/src/__tests__/temporal-view.unit.test.ts +3 -3
  416. package/src/__tests__/transmission-prewarm.unit.test.ts +111 -32
  417. package/src/__tests__/visibility-budget.integration.test.ts +140 -0
  418. package/src/__tests__/visibility-budget.unit.test.ts +70 -0
  419. package/src/__tests__/visibility-extract.integration.test.ts +11 -6
  420. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +6 -3
  421. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +31 -28
  422. package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
  423. package/src/assembly/backend-contract.ts +13 -0
  424. package/src/assembly/bundler-contract.ts +9 -0
  425. package/src/assembly/device-feature-admission.ts +26 -9
  426. package/src/assembly/extended-lighting-fallback.ts +216 -0
  427. package/src/assembly/factory.ts +81 -9634
  428. package/src/assembly/host-contract.ts +10 -0
  429. package/src/assembly/material/assembly.ts +18 -2
  430. package/src/assembly/material/standard-layer-projection.ts +16 -0
  431. package/src/assembly/material-shader-policy.ts +854 -0
  432. package/src/assembly/material-shader-prewarm.ts +88 -0
  433. package/src/assembly/mesh-ssbo-grow.ts +270 -0
  434. package/src/assembly/recovery/device-loss-fanout.ts +89 -0
  435. package/src/assembly/recovery/generation.ts +141 -0
  436. package/src/assembly/recovery/recovery-attempt.ts +800 -0
  437. package/src/assembly/recovery/renderer-recover.ts +906 -0
  438. package/src/assembly/renderer-facade.ts +342 -0
  439. package/src/assembly/renderer-frame-transaction.ts +45 -0
  440. package/src/assembly/renderer-helpers.ts +99 -0
  441. package/src/assembly/renderer-lifecycle.ts +159 -0
  442. package/src/assembly/shader-prewarm-policy.ts +157 -0
  443. package/src/assembly/webgpu-ready-contract.ts +14 -0
  444. package/src/assembly/webgpu-ready.ts +4079 -0
  445. package/src/assembly/webgpu-renderer.ts +4095 -0
  446. package/src/cluster-binner.ts +31 -0
  447. package/src/components/__tests__/lighting-authoring.unit.test.ts +39 -0
  448. package/src/components/__tests__/rect-area-light.unit.test.ts +33 -0
  449. package/src/components/camera.ts +1 -1
  450. package/src/components/index.ts +3 -0
  451. package/src/components/light-helpers.ts +52 -1
  452. package/src/components/light-probe.ts +13 -0
  453. package/src/components/rect-area-light.ts +15 -0
  454. package/src/components/scene-instance.ts +6 -0
  455. package/src/components/spot-light.ts +3 -0
  456. package/src/debug-draw-glue.ts +1 -1
  457. package/src/device/__tests__/extended-lighting-recovery.unit.test.ts +24 -0
  458. package/src/device/device-scope.ts +35 -6
  459. package/src/device/gpu-residency.ts +334 -35
  460. package/src/device/lifecycle-transaction.ts +12 -0
  461. package/src/environment/frame.ts +6 -0
  462. package/src/environment/inspection.ts +10 -0
  463. package/src/environment/lifecycle.ts +122 -9
  464. package/src/errors/gpu-driven.ts +92 -0
  465. package/src/errors/index.ts +1 -0
  466. package/src/errors/recover.ts +108 -5
  467. package/src/errors/render.ts +72 -1
  468. package/src/extract/camera.ts +3 -3
  469. package/src/extract/contracts.ts +974 -0
  470. package/src/extract/gpu-driven.ts +108 -0
  471. package/src/extract/visibility.ts +0 -23
  472. package/src/features/host.ts +16 -0
  473. package/src/features/prepared-gpu-work.ts +20 -2
  474. package/src/features/prepared-graphics-store.ts +17 -0
  475. package/src/gpu-driven/batch-topology.ts +206 -28
  476. package/src/gpu-driven/prepared-draw.ts +208 -0
  477. package/src/gpu-driven/production-raster.ts +1046 -39
  478. package/src/gpu-driven/view-gpu.ts +411 -29
  479. package/src/gpu-scene-schema.ts +13 -0
  480. package/src/gpu-scene.ts +137 -67
  481. package/src/gpu-usage.ts +0 -1
  482. package/src/hdrp-buffers.ts +6 -6
  483. package/src/ibl/IblPipelineCache.ts +134 -50
  484. package/src/ibl/skylight-bind-group.ts +26 -0
  485. package/src/index.ts +83 -1
  486. package/src/inspection-types.ts +220 -1
  487. package/src/internal.ts +38 -0
  488. package/src/light-buffer-layout.ts +157 -324
  489. package/src/materials.ts +278 -47
  490. package/src/mesh-material-bindings.ts +59 -0
  491. package/src/occlusion-proxy.ts +64 -0
  492. package/src/pbr-pipeline.ts +290 -60
  493. package/src/pipeline/standard-forward-lane.ts +47 -0
  494. package/src/pipeline/standard-lighting/graph.ts +2 -1
  495. package/src/pipeline/standard-lighting/light-frame.ts +3 -2
  496. package/src/pipeline/standard-lighting/topology.ts +1 -1
  497. package/src/pipeline/standard-lighting/transport.ts +2 -1
  498. package/src/pipeline/standard-pipeline.ts +2 -0
  499. package/src/pipeline-builder.ts +5 -2
  500. package/src/pipeline-spec.ts +12 -1
  501. package/src/plugin.ts +4 -0
  502. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
  503. package/src/points-lines/prepare.ts +9 -0
  504. package/src/points-lines/standard-owner.ts +403 -0
  505. package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +56 -0
  506. package/src/prepare/extended-lighting/ltc-resources.ts +136 -0
  507. package/src/prepare/extended-lighting/resources.ts +389 -0
  508. package/src/prepare/extended-lighting/spot-modifiers.ts +194 -0
  509. package/src/prepare/extended-lighting/state.ts +92 -0
  510. package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
  511. package/src/record/__tests__/gpu-timing.unit.test.ts +177 -0
  512. package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
  513. package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
  514. package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
  515. package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
  516. package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
  517. package/src/record/__tests__/temporal-payload.unit.test.ts +29 -28
  518. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +21 -2
  519. package/src/record/frame-lighting.ts +252 -53
  520. package/src/record/frame-snapshot.ts +72 -12
  521. package/src/record/frame-targets.ts +11 -1
  522. package/src/record/frame.ts +416 -95
  523. package/src/record/gpu-timing.ts +108 -44
  524. package/src/record/helpers.ts +1 -59
  525. package/src/record/main-pass-geometry.ts +434 -44
  526. package/src/record/main-pass-material.ts +324 -210
  527. package/src/record/main-pass-sprite-draws.ts +58 -92
  528. package/src/record/main-pass.ts +94 -6
  529. package/src/record/mesh-ssbo.ts +79 -46
  530. package/src/record/recovery-pipeline.ts +695 -0
  531. package/src/record/render-context.ts +99 -7
  532. package/src/record/shadow-pass.ts +66 -40
  533. package/src/record/typed-frame-graph.ts +270 -84
  534. package/src/record/view-ubo.ts +17 -27
  535. package/src/recovery/render-system-candidate.ts +839 -0
  536. package/src/reflection/inspection.ts +67 -0
  537. package/src/reflection/projection.ts +196 -1
  538. package/src/reflection/record-owner.ts +1283 -0
  539. package/src/render-contract.ts +82 -12
  540. package/src/render-pipeline.ts +5 -0
  541. package/src/render-system-extract-tail.ts +2983 -0
  542. package/src/render-system-extract.ts +290 -2784
  543. package/src/render-system.ts +1597 -1192
  544. package/src/scene/__tests__/changed-block-summary.candidate.test.ts +36 -0
  545. package/src/scene/probe-blend-record.ts +54 -0
  546. package/src/scene/probe-blend.ts +813 -0
  547. package/src/scene/render-scene-types.ts +0 -7
  548. package/src/scene/render-scene.ts +972 -184
  549. package/src/scene/visibility/bounds.ts +57 -0
  550. package/src/scene/visibility/budget.ts +40 -0
  551. package/src/scene/visibility/facet.ts +400 -0
  552. package/src/scene/visibility/gpu-frame-timing.ts +101 -0
  553. package/src/scene/visibility/gpu-lod.ts +119 -0
  554. package/src/scene/visibility/inspection.ts +313 -0
  555. package/src/scene/visibility/lod-selector.ts +84 -0
  556. package/src/scene/visibility/occlusion-confidence.ts +478 -0
  557. package/src/scene/visibility/occlusion-pass.ts +165 -0
  558. package/src/scene/visibility/occlusion-query-pool.ts +178 -0
  559. package/src/scene/visibility/occlusion-runtime.ts +672 -0
  560. package/src/scene/visibility/types.ts +50 -0
  561. package/src/ssr/admission.ts +451 -0
  562. package/src/ssr/composition.ts +73 -0
  563. package/src/ssr/errors.ts +76 -0
  564. package/src/ssr/identity.ts +12 -0
  565. package/src/systems/skin-palette-allocator.ts +1 -1
  566. package/src/temporal/frame-coordinator.ts +30 -1
  567. package/src/temporal/frame.ts +14 -1
  568. package/src/temporal/taa-history-store.ts +46 -2
  569. package/src/temporal/temporal-view.ts +1 -1
  570. package/src/temporal/transaction.ts +9 -0
  571. package/src/temporal/view.ts +11 -0
  572. package/src/tilemap-chunk-extract-system.ts +5 -5
  573. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
  574. package/src/typed-render-graph-primitives.ts +48 -0
  575. package/src/volume/passes.ts +46 -49
  576. package/dist/.tsbuildinfo +0 -1
  577. package/dist/chunk-5YADUCA7.mjs.map +0 -1
  578. package/dist/chunk-6OPXDQ2E.mjs.map +0 -1
  579. package/dist/chunk-BXBQQKFQ.mjs +0 -67
  580. package/dist/chunk-BXBQQKFQ.mjs.map +0 -1
  581. package/dist/chunk-FS2KNUQH.mjs.map +0 -1
  582. package/dist/chunk-PCHBPYML.mjs.map +0 -1
  583. package/dist/chunk-VFPLTKCU.mjs +0 -192
  584. package/dist/chunk-VFPLTKCU.mjs.map +0 -1
@@ -1,10 +1,9 @@
1
- import { RenderIntentInvalidError, PointsLinesBudgetExceededError, VolumeOwnerConflictError, VolumeDensityShapeMismatchError, VolumeInvalidBoundsError, VolumeInvalidParametersError, PointsLinesStyleUnsupportedError, PointsLinesMaterialUnsupportedError, PointsLinesInvalidStyleError, PointsLinesTopologyMismatchError } from './chunk-6OPXDQ2E.mjs';
1
+ import { RenderIntentInvalidError, ShadowInvalidConfigError, VolumeOwnerConflictError, VolumeDensityShapeMismatchError, VolumeInvalidBoundsError, VolumeInvalidParametersError } from './chunk-RR5L4SRS.mjs';
2
2
  import { defineComponent, Entity } from '@forgeax/engine-ecs';
3
3
  import { TONEMAP_SHADER_MODE } from '@forgeax/engine-shader';
4
- import { err, ok } from '@forgeax/engine-types';
5
- import { mat4 } from '@forgeax/engine-math';
4
+ import { R_MIN, err, ok } from '@forgeax/engine-types';
5
+ import { SpawnLightInvalidBoundsError } from '@forgeax/engine-ecs/projection';
6
6
  import { Transform, projectHierarchy } from '@forgeax/engine-scene';
7
- import { createWorldProjection } from '@forgeax/engine-ecs/projection';
8
7
 
9
8
  var Atmosphere = defineComponent("Atmosphere", {
10
9
  turbidity: { type: "f32", default: 2 },
@@ -283,6 +282,221 @@ var Instances = defineComponent("Instances", {
283
282
  var Layer = defineComponent("Layer", {
284
283
  value: { type: "i32", default: 0 }
285
284
  });
285
+
286
+ // src/components/light-helpers.ts
287
+ var RANGE_ZERO_FALLBACK_INV_R2 = 1e8;
288
+ var DEG_TO_RAD = Math.PI / 180;
289
+ var PCSS_RADIUS_MIN = 1e-4;
290
+ var PCSS_RADIUS_MAX = 0.05;
291
+ var PCSS_PENUMBRA_MIN = 1;
292
+ var PCSS_PENUMBRA_MAX = 64;
293
+ function degToCos(deg) {
294
+ return Math.cos(deg * DEG_TO_RAD);
295
+ }
296
+ function computeInvRangeSquared(range) {
297
+ if (range === Number.POSITIVE_INFINITY) return 0;
298
+ if (range === 0) return RANGE_ZERO_FALLBACK_INV_R2;
299
+ return 1 / (range * range);
300
+ }
301
+ function validateDirection(componentName, direction) {
302
+ const dir = direction;
303
+ if (dir === void 0 || (dir[0] ?? 0) === 0 && (dir[1] ?? 0) === 0 && (dir[2] ?? 0) === 0) {
304
+ return new SpawnLightInvalidBoundsError(
305
+ componentName,
306
+ "direction",
307
+ dir === void 0 ? [0, 0, 0] : [dir[0] ?? 0, dir[1] ?? 0, dir[2] ?? 0]
308
+ );
309
+ }
310
+ return null;
311
+ }
312
+ function validateDirectionalLightData(data) {
313
+ const directionError = validateDirection(
314
+ "DirectionalLight",
315
+ data.direction
316
+ );
317
+ if (directionError !== null) return err(directionError);
318
+ if (data.castShadow === false) return ok(void 0);
319
+ const mapSize = data.mapSize ?? 2048;
320
+ if (mapSize < 1) {
321
+ return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
322
+ }
323
+ const cascadeCount = data.cascadeCount ?? 4;
324
+ if (cascadeCount < 1 || cascadeCount > 4 || !Number.isInteger(cascadeCount)) {
325
+ return err(new ShadowInvalidConfigError("cascadeCount", cascadeCount, 1, 4));
326
+ }
327
+ const splitLambda = data.splitLambda ?? 0.75;
328
+ if (splitLambda < 0 || splitLambda > 1) {
329
+ return err(new ShadowInvalidConfigError("splitLambda", splitLambda, 0, 1));
330
+ }
331
+ const cascadeBlend = data.cascadeBlend ?? 0.2;
332
+ if (cascadeBlend < 0 || cascadeBlend > 0.5) {
333
+ return err(new ShadowInvalidConfigError("cascadeBlend", cascadeBlend, 0, 0.5));
334
+ }
335
+ const shadowDistance = data.shadowDistance ?? 200;
336
+ if (shadowDistance <= 0) {
337
+ return err(new ShadowInvalidConfigError("shadowDistance", shadowDistance, 0, ">"));
338
+ }
339
+ const shadowFilter = data.shadowFilter ?? DirectionalShadowFilterValue.pcf3;
340
+ const allowedFilters = Object.values(DirectionalShadowFilterValue);
341
+ if (!Number.isFinite(shadowFilter) || !allowedFilters.includes(shadowFilter)) {
342
+ return err(
343
+ new ShadowInvalidConfigError(
344
+ "shadowFilter",
345
+ shadowFilter,
346
+ { kind: "allowed-values", values: allowedFilters },
347
+ void 0,
348
+ "one of [pcf1, pcf3, pcf5, pcssMedium, pcssHigh]"
349
+ )
350
+ );
351
+ }
352
+ if (shadowFilter === DirectionalShadowFilterValue.pcssMedium || shadowFilter === DirectionalShadowFilterValue.pcssHigh) {
353
+ const shadowAngularRadius = data.shadowAngularRadius ?? 465e-5;
354
+ if (!Number.isFinite(shadowAngularRadius)) {
355
+ return err(
356
+ new ShadowInvalidConfigError("shadowAngularRadius", shadowAngularRadius, {
357
+ kind: "range",
358
+ min: PCSS_RADIUS_MIN,
359
+ max: PCSS_RADIUS_MAX
360
+ })
361
+ );
362
+ }
363
+ if (shadowAngularRadius < PCSS_RADIUS_MIN || shadowAngularRadius > PCSS_RADIUS_MAX) {
364
+ return err(
365
+ new ShadowInvalidConfigError("shadowAngularRadius", shadowAngularRadius, {
366
+ kind: "range",
367
+ min: PCSS_RADIUS_MIN,
368
+ max: PCSS_RADIUS_MAX
369
+ })
370
+ );
371
+ }
372
+ const maxPenumbraTexels = data.maxPenumbraTexels ?? 32;
373
+ if (!Number.isFinite(maxPenumbraTexels) || !Number.isInteger(maxPenumbraTexels) || maxPenumbraTexels < PCSS_PENUMBRA_MIN || maxPenumbraTexels > PCSS_PENUMBRA_MAX) {
374
+ return err(
375
+ new ShadowInvalidConfigError(
376
+ "maxPenumbraTexels",
377
+ maxPenumbraTexels,
378
+ { kind: "range", min: PCSS_PENUMBRA_MIN, max: PCSS_PENUMBRA_MAX },
379
+ void 0,
380
+ "a finite integer in [1, 64]"
381
+ )
382
+ );
383
+ }
384
+ }
385
+ return ok(void 0);
386
+ }
387
+ function validateSpotLightData(data) {
388
+ const directionError = validateDirection(
389
+ "SpotLight",
390
+ data.direction
391
+ );
392
+ if (directionError !== null) return err(directionError);
393
+ if (data.castShadow === false) return ok(void 0);
394
+ const range = data.range ?? 10;
395
+ if (typeof range !== "number" || Number.isNaN(range) || range < 0) {
396
+ return err(new SpawnLightInvalidBoundsError("SpotLight", "range", range));
397
+ }
398
+ const innerConeDeg = data.innerConeDeg ?? 0;
399
+ const outerConeDeg = data.outerConeDeg ?? 45;
400
+ if (outerConeDeg > 90) {
401
+ return err(new SpawnLightInvalidBoundsError("SpotLight", "outerNinety", outerConeDeg));
402
+ }
403
+ if (outerConeDeg <= innerConeDeg) {
404
+ return err(new SpawnLightInvalidBoundsError("SpotLight", "innerOuter", outerConeDeg));
405
+ }
406
+ const mapSize = data.mapSize ?? 2048;
407
+ if (mapSize < 1) return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
408
+ const nearPlane = data.nearPlane;
409
+ const farPlane = data.farPlane;
410
+ if (nearPlane !== void 0 && farPlane !== void 0 && farPlane <= nearPlane) {
411
+ return err(new ShadowInvalidConfigError("farPlane", farPlane, nearPlane));
412
+ }
413
+ const pcfKernelSize = data.pcfKernelSize ?? 3;
414
+ if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
415
+ return err(
416
+ new ShadowInvalidConfigError(
417
+ "pcfKernelSize",
418
+ pcfKernelSize,
419
+ { kind: "lower-bound", operator: ">=", value: 1 },
420
+ void 0,
421
+ "an odd integer >= 1"
422
+ )
423
+ );
424
+ }
425
+ const shadowIntensity = data.shadowIntensity ?? 1;
426
+ if (!Number.isFinite(shadowIntensity) || shadowIntensity < 0 || shadowIntensity > 1) {
427
+ return err(new ShadowInvalidConfigError("shadowIntensity", shadowIntensity, 0, 1));
428
+ }
429
+ return ok(void 0);
430
+ }
431
+ function validatePointLightData(data) {
432
+ const range = data.range ?? 10;
433
+ if (typeof range !== "number" || Number.isNaN(range) || range < 0) {
434
+ return err(new SpawnLightInvalidBoundsError("PointLight", "range", range));
435
+ }
436
+ return ok(void 0);
437
+ }
438
+ function validatePointLightShadowData(data) {
439
+ const mapSize = data.mapSize ?? 512;
440
+ if (mapSize < 1) return err(new ShadowInvalidConfigError("mapSize", mapSize, 1));
441
+ const nearPlane = data.nearPlane ?? 0.1;
442
+ const farPlane = data.farPlane ?? 25;
443
+ if (farPlane <= nearPlane) {
444
+ return err(new ShadowInvalidConfigError("farPlane", farPlane, nearPlane));
445
+ }
446
+ const pcfKernelSize = data.pcfKernelSize ?? 3;
447
+ if (pcfKernelSize < 1 || pcfKernelSize % 2 === 0) {
448
+ return err(
449
+ new ShadowInvalidConfigError(
450
+ "pcfKernelSize",
451
+ pcfKernelSize,
452
+ { kind: "lower-bound", operator: ">=", value: 1 },
453
+ void 0,
454
+ "an odd integer >= 1"
455
+ )
456
+ );
457
+ }
458
+ return ok(void 0);
459
+ }
460
+ function validateRectAreaLightData(data) {
461
+ const intensity = data.intensity ?? 1;
462
+ if (typeof intensity !== "number" || !Number.isFinite(intensity) || intensity < 0) {
463
+ return err(new SpawnLightInvalidBoundsError("RectAreaLight", "intensity", intensity));
464
+ }
465
+ const color = data.color ?? [1, 1, 1];
466
+ if (color.length !== 3 || Array.from(color).some(
467
+ (value) => typeof value !== "number" || !Number.isFinite(value) || value < 0
468
+ )) {
469
+ return err(new SpawnLightInvalidBoundsError("RectAreaLight", "color", Array.from(color)));
470
+ }
471
+ for (const field of ["width", "height", "range"]) {
472
+ const value = data[field] ?? (field === "range" ? 10 : 1);
473
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
474
+ return err(new SpawnLightInvalidBoundsError("RectAreaLight", field, value));
475
+ }
476
+ }
477
+ return ok(void 0);
478
+ }
479
+ function validateLightProbeData(data) {
480
+ const irradiance = data.irradiance;
481
+ if (irradiance === void 0 || irradiance.length !== 27 || Array.from(irradiance).some((value) => typeof value !== "number" || !Number.isFinite(value))) {
482
+ return err(
483
+ new SpawnLightInvalidBoundsError(
484
+ "LightProbe",
485
+ "irradiance",
486
+ irradiance === void 0 ? [] : Array.from(irradiance)
487
+ )
488
+ );
489
+ }
490
+ const radius = data.radius ?? R_MIN;
491
+ if (typeof radius !== "number" || !Number.isFinite(radius) || radius < R_MIN) {
492
+ return err(new SpawnLightInvalidBoundsError("LightProbe", "radius", radius));
493
+ }
494
+ return ok(void 0);
495
+ }
496
+ var LightProbe = defineComponent("LightProbe", {
497
+ irradiance: { type: "array<f32, 27>" },
498
+ radius: { type: "f32", default: R_MIN }
499
+ });
286
500
  var Lines = defineComponent(
287
501
  "Lines",
288
502
  {
@@ -357,6 +571,13 @@ var schema = {
357
571
  data: "buffer"
358
572
  };
359
573
  var PostProcessParams = defineComponent("PostProcessParams", schema);
574
+ var RectAreaLight = defineComponent("RectAreaLight", {
575
+ color: { type: "array<f32, 3>", default: new Float32Array([1, 1, 1]) },
576
+ intensity: { type: "f32", default: 1 },
577
+ width: { type: "f32", default: 1 },
578
+ height: { type: "f32", default: 1 },
579
+ range: { type: "f32", default: 10 }
580
+ });
360
581
  var REFLECTION_PROBE_UPDATE_ONCE = 0;
361
582
  var REFLECTION_PROBE_UPDATE_ON_CHANGE = 1;
362
583
  var REFLECTION_PROBE_UPDATE_CONTINUOUS = 2;
@@ -434,6 +655,9 @@ var SpotLight = defineComponent("SpotLight", {
434
655
  range: { type: "f32", default: 10 },
435
656
  innerConeDeg: { type: "f32", default: 0 },
436
657
  outerConeDeg: { type: "f32", default: 45 },
658
+ iesProfile: { type: "shared<IesProfileAsset>" },
659
+ cookie: { type: "shared<TextureAsset>" },
660
+ rollDeg: { type: "f32", default: 0 },
437
661
  // Shadow opt-out gate: defaults to true so zero-config spawns cast shadows.
438
662
  castShadow: { type: "bool", default: true },
439
663
  // 7 shadow fields aligned with the shared light shadow vocabulary.
@@ -486,217 +710,118 @@ var Visibility = defineComponent(
486
710
  }
487
711
  }
488
712
  );
489
- function invalidStyle(input, component, field, value, expected) {
490
- return err(new PointsLinesInvalidStyleError({ entity: input.entity, component, field, value, expected }));
713
+
714
+ // src/scene/visibility/budget.ts
715
+ var DEFAULT_CONFIGURED_QUERY_BUDGET = 2048;
716
+ var MAX_QUERY_BUDGET = 4096;
717
+ var VISIBILITY_CANDIDATE_COUNT = 1e5;
718
+ var VISIBILITY_OCCLUDED_COUNT = 9e4;
719
+ function createVisibilityBudget(configuredQueryBudget = DEFAULT_CONFIGURED_QUERY_BUDGET) {
720
+ if (!Number.isSafeInteger(configuredQueryBudget) || configuredQueryBudget <= 0) {
721
+ throw new RangeError("configuredQueryBudget must be a positive safe integer");
722
+ }
723
+ const effectiveQueryBudget = Math.min(configuredQueryBudget, MAX_QUERY_BUDGET);
724
+ const oneSweepCandidates = oneSweep(VISIBILITY_CANDIDATE_COUNT, effectiveQueryBudget);
725
+ const oneSweepOccluded = oneSweep(VISIBILITY_OCCLUDED_COUNT, effectiveQueryBudget);
726
+ const retestSubmits = Math.max(6, oneSweepOccluded);
727
+ return Object.freeze({
728
+ configuredQueryBudget,
729
+ effectiveQueryBudget,
730
+ oneSweepCandidates,
731
+ oneSweepOccluded,
732
+ settleSubmits: 2 * oneSweepCandidates,
733
+ retestSubmits,
734
+ expirySubmits: Math.max(8, retestSubmits + oneSweepOccluded)
735
+ });
491
736
  }
492
- function topologyMismatch(input, submesh, expected, actual) {
493
- return err(new PointsLinesTopologyMismatchError({ entity: input.entity, submesh, expected, actual }));
737
+ function oneSweep(candidateCount, effectiveQueryBudget) {
738
+ return Math.ceil(candidateCount / effectiveQueryBudget);
494
739
  }
495
- function checkStyle(input) {
496
- const hasPoints = input.points !== void 0;
497
- const hasLines = input.lines !== void 0;
498
- if (hasPoints && hasLines) {
499
- return invalidStyle(
500
- input,
501
- "Points/Lines",
502
- "components",
503
- "Points + Lines",
504
- "exactly one style component"
505
- );
506
- }
507
- if (!hasPoints && !hasLines) {
508
- return invalidStyle(input, "Points/Lines", "components", void 0, "one style component");
509
- }
510
- if (hasPoints) {
511
- const sizePx = input.points?.sizePx ?? 4;
512
- const shapeValue = input.points?.shape ?? PointShapeValue.square;
513
- const shape = pointShapeFromU32(shapeValue);
514
- if (!Number.isFinite(sizePx) || sizePx <= 0) {
515
- return invalidStyle(input, "Points", "sizePx", sizePx, "finite sizePx > 0");
516
- }
517
- if (shape === void 0) {
518
- return invalidStyle(input, "Points", "shape", shapeValue, "shape is 'square' or 'circle'");
519
- }
520
- return ok({ component: "Points", shape, sizePx });
521
- }
522
- const widthPx = input.lines?.widthPx ?? 1;
523
- if (!Number.isFinite(widthPx) || widthPx <= 0) {
524
- return invalidStyle(input, "Lines", "widthPx", widthPx, "finite widthPx > 0");
525
- }
526
- return ok({ component: "Lines", widthPx });
740
+ function hasVolumetricFogCapability(caps, shaders) {
741
+ return caps.compute && caps.storageTexture && shaders !== void 0;
527
742
  }
528
- function checkTopology(input, component) {
529
- const expected = component === "Points" ? "point-list" : "line-list";
530
- let pointCount = 0;
531
- let segmentCount = 0;
532
- const acceptedSubmeshes = [];
533
- let sawNonEmpty = false;
534
- for (const [submeshIndex, submesh] of input.mesh.submeshes.entries()) {
535
- const indexed = input.mesh.indices !== void 0 && submesh.indexCount > 0;
536
- const elementCount = indexed ? submesh.indexCount : submesh.vertexCount;
537
- if (elementCount === 0) continue;
538
- sawNonEmpty = true;
539
- if (component === "Lines" && submesh.topology === "line-strip") {
540
- return err(
541
- new PointsLinesStyleUnsupportedError({
542
- lane: "admission",
543
- field: "topology",
544
- member: "line-strip",
545
- supported: ["line-list"]
546
- })
547
- );
548
- }
549
- if (submesh.topology !== expected) {
550
- return topologyMismatch(input, submeshIndex, expected, submesh.topology);
551
- }
552
- if (component === "Lines" && elementCount % 2 !== 0) {
553
- return topologyMismatch(input, submeshIndex, "line-list pairs", "line-list odd tail");
554
- }
555
- acceptedSubmeshes.push(submeshIndex);
556
- if (component === "Points") pointCount += elementCount;
557
- else segmentCount += elementCount / 2;
743
+ function resolveVolumetricFogLightPair(world, point, spot) {
744
+ const expected = "PointLight + SpotLight in the same World";
745
+ if (!world.get(point, Entity).ok || !world.get(spot, Entity).ok) {
746
+ return {
747
+ status: "unresolved",
748
+ reason: "missing-entity",
749
+ point,
750
+ spot,
751
+ expected,
752
+ actual: "point or spot entity is absent from this World",
753
+ hint: "assign two live entities from the same World and retry"
754
+ };
558
755
  }
559
- if (!sawNonEmpty) return topologyMismatch(input, 0, expected, "empty-range");
560
- return ok({ pointCount, segmentCount, submeshes: acceptedSubmeshes });
561
- }
562
- function checkMaterial(input) {
563
- const passes = input.material.passes ?? [];
564
- const unlitModules = /* @__PURE__ */ new Set(["forgeax_material::unlit", "forgeax::default-unlit"]);
565
- if (passes.length !== 1 || passes[0] === void 0) {
566
- const pass2 = passes.find(
567
- (candidate) => candidate.name === "deferred" || candidate.name === "shadow-caster"
568
- ) ?? passes[0];
569
- return err(
570
- new PointsLinesMaterialUnsupportedError({
571
- entity: input.entity,
572
- material: input.materialId ?? "<anonymous>",
573
- pass: pass2?.name ?? "<empty>",
574
- module: pass2?.program.module ?? "<empty>",
575
- reason: "points-lines admission requires one unlit forward pass"
576
- })
577
- );
756
+ if (point === spot) {
757
+ return {
758
+ status: "unresolved",
759
+ reason: "same-entity",
760
+ point,
761
+ spot,
762
+ expected,
763
+ actual: "PointLight and SpotLight share one EntityHandle",
764
+ hint: "spawn PointLight and SpotLight on two different entities"
765
+ };
578
766
  }
579
- const pass = passes[0];
580
- const lightMode = pass.renderState?.tags?.LightMode;
581
- if (!unlitModules.has(pass.program.module) || pass.name !== "forward" || lightMode === "ShadowCaster") {
582
- return err(
583
- new PointsLinesMaterialUnsupportedError({
584
- entity: input.entity,
585
- material: input.materialId ?? "<anonymous>",
586
- pass: pass.name,
587
- module: pass.program.module,
588
- reason: "points-lines admission requires an engine-owned unlit forward pass"
589
- })
590
- );
767
+ const pointValid = world.hasComponent(point, PointLight) && world.hasComponent(point, Transform);
768
+ const spotValid = world.hasComponent(spot, SpotLight) && world.hasComponent(spot, Transform);
769
+ if (!pointValid || !spotValid) {
770
+ return {
771
+ status: "unresolved",
772
+ reason: "wrong-component",
773
+ point,
774
+ spot,
775
+ expected,
776
+ actual: `pointValid=${pointValid}; spotValid=${spotValid}`,
777
+ hint: "attach PointLight and SpotLight with Transform to separate same-World entities"
778
+ };
591
779
  }
592
- return ok(void 0);
780
+ return { status: "available", mode: "point-spot", point, spot };
593
781
  }
594
- function admitPointsLines(input) {
595
- const style = checkStyle(input);
596
- if (!style.ok) return style;
597
- const topology = checkTopology(input, style.value.component);
598
- if (!topology.ok) return topology;
599
- const material = checkMaterial(input);
600
- if (!material.ok) return material;
601
- if (style.value.component === "Points" && input.limits?.maxPoints !== void 0) {
602
- if (topology.value.pointCount > input.limits.maxPoints) {
603
- return err(
604
- new PointsLinesBudgetExceededError({
605
- lane: "admission",
606
- requested: topology.value.pointCount,
607
- limit: input.limits.maxPoints,
608
- unit: "points"
609
- })
610
- );
611
- }
782
+ function resolveSelectedVolumetricLight(world, entity) {
783
+ const expected = "DirectionalLight | PointLight | SpotLight";
784
+ if (!world.get(entity, Entity).ok) {
785
+ return {
786
+ status: "unresolved",
787
+ reason: "missing-entity",
788
+ entity,
789
+ expected,
790
+ actual: "missing or foreign World entity",
791
+ hint: "assign VolumetricFog.light to a live DirectionalLight or SpotLight in this World"
792
+ };
612
793
  }
613
- if (style.value.component === "Lines" && input.limits?.maxSegments !== void 0) {
614
- if (topology.value.segmentCount > input.limits.maxSegments) {
615
- return err(
616
- new PointsLinesBudgetExceededError({
617
- lane: "admission",
618
- requested: topology.value.segmentCount,
619
- limit: input.limits.maxSegments,
620
- unit: "segments"
621
- })
622
- );
623
- }
794
+ const hasDirectional = world.hasComponent(entity, DirectionalLight);
795
+ const hasSpot = world.hasComponent(entity, SpotLight);
796
+ if (hasDirectional && hasSpot) {
797
+ return {
798
+ status: "unresolved",
799
+ reason: "ambiguous",
800
+ entity,
801
+ expected,
802
+ actual: "DirectionalLight + SpotLight",
803
+ hint: "remove one mutually exclusive light component from the selected entity"
804
+ };
624
805
  }
625
- return ok({ ...style.value, ...topology.value });
626
- }
627
-
628
- // src/volume/inspection.ts
629
- function resourceStage(input) {
630
- if (!input.authored || input.recovery === void 0) return "none";
631
- if (input.recovery.status === "candidate") return "candidate";
632
- if (input.recovery.status === "recovering") return "recovering";
633
- if (input.recovery.status === "degraded") return "lkg";
634
- return "accepted";
635
- }
636
- function inspectVolumetricFog(input) {
637
- const recovery = input.recovery;
638
- const status = !input.authored ? "off" : input.capability === "unavailable" ? "unavailable" : input.degraded === true || recovery?.status === "degraded" ? "degraded" : "available";
639
- return Object.freeze({
640
- status,
641
- resourceStage: resourceStage(input),
642
- guid: recovery?.guid,
643
- generation: recovery?.generation,
644
- digest: input.acceptedDigest,
645
- candidateGeneration: recovery?.candidateGeneration,
646
- candidateDigest: recovery?.candidateDigest,
647
- lkgGeneration: recovery?.lkgGeneration,
648
- candidateFailure: recovery?.candidateFailure,
649
- deviceEpoch: recovery?.deviceEpoch ?? 0,
650
- format: input.format,
651
- passCount: input.passCount ?? 0,
652
- sampleCount: input.sampleCount ?? 0,
653
- memoryBytes: input.memoryBytes ?? 0,
654
- resourceFacts: input.resourceFacts,
655
- selectedLight: recovery?.selectedLight,
656
- candidateSelectedLight: recovery?.candidateSelectedLight
657
- });
658
- }
659
- var FACE_ORIENTATION = [
660
- { direction: [1, 0, 0], up: [0, 1, 0] },
661
- { direction: [-1, 0, 0], up: [0, 1, 0] },
662
- { direction: [0, 1, 0], up: [0, 0, -1] },
663
- { direction: [0, -1, 0], up: [0, 0, 1] },
664
- { direction: [0, 0, 1], up: [0, 1, 0] },
665
- { direction: [0, 0, -1], up: [0, 1, 0] }
666
- ];
667
- function assertRange(near, far) {
668
- if (!Number.isFinite(near) || near <= 0 || !Number.isFinite(far) || far <= near) {
669
- throw new RangeError("CubeCamera requires finite near > 0 and far > near.");
806
+ if (hasDirectional) return { status: "available", entity, kind: "directional" };
807
+ if (world.hasComponent(entity, PointLight) && world.hasComponent(entity, Transform)) {
808
+ return { status: "available", entity, kind: "point" };
670
809
  }
671
- }
672
- function buildCubeCameraFaceViews(input) {
673
- assertRange(input.near, input.far);
674
- const views = [];
675
- for (const [index, face] of CUBE_CAMERA_FACE_ORDER.entries()) {
676
- const orientation = FACE_ORIENTATION[index];
677
- if (orientation === void 0)
678
- throw new Error(`CubeCamera face orientation missing at ${index}`);
679
- const target = [
680
- (input.position[0] ?? 0) + orientation.direction[0],
681
- (input.position[1] ?? 0) + orientation.direction[1],
682
- (input.position[2] ?? 0) + orientation.direction[2]
683
- ];
684
- const view = mat4.lookAt(mat4.create(), input.position, target, orientation.up);
685
- const projection = mat4.perspective(mat4.create(), Math.PI / 2, 1, input.near, input.far);
686
- const viewProjection = mat4.multiply(mat4.create(), projection, view);
687
- views.push({
688
- position: input.position,
689
- face,
690
- direction: orientation.direction,
691
- up: orientation.up,
692
- near: input.near,
693
- far: input.far,
694
- view,
695
- projection,
696
- viewProjection
697
- });
810
+ if (hasSpot && world.hasComponent(entity, Transform)) {
811
+ return { status: "available", entity, kind: "spot" };
698
812
  }
699
- return views;
813
+ const actual = hasSpot ? "SpotLight without Transform" : world.hasComponent(entity, PointLight) ? "PointLight" : "other component";
814
+ return {
815
+ status: "unresolved",
816
+ reason: "wrong-component",
817
+ entity,
818
+ expected,
819
+ actual,
820
+ hint: "add exactly one supported light component and a Transform for PointLight or SpotLight in the same World"
821
+ };
822
+ }
823
+ function resolveIntegratedVolumeConsumer(resource, consumer) {
824
+ return { consumer, resource };
700
825
  }
701
826
 
702
827
  // src/mesh-material-bindings.ts
@@ -808,367 +933,7 @@ function resolveMeshMaterialBindings(mesh, rendererOverrides, deps) {
808
933
  }
809
934
  return { ok: true, bindings, diagnostics };
810
935
  }
811
-
812
- // src/point-shadow-inspection.ts
813
- function inspectPointShadow(snapshots, shadowAtlasCapacity) {
814
- const requested = snapshots.length;
815
- const admitted = snapshots.reduce(
816
- (count, snapshot) => snapshot.shadowAtlasLayer >= 0 && snapshot.shadowAtlasLayer < shadowAtlasCapacity ? count + 1 : count,
817
- 0
818
- );
819
- const status = requested === 0 ? "inactive" : requested > shadowAtlasCapacity || admitted !== requested ? "over-budget" : "ready";
820
- return Object.freeze({
821
- status,
822
- requested,
823
- admitted,
824
- // A point shadow only samples an atlas after it owns an atlas layer. Keep
825
- // these names explicit for AI diagnostics while deriving both from the
826
- // one layer projection above.
827
- shadowed: admitted,
828
- shadowAtlasOccupancy: admitted,
829
- shadowAtlasCapacity
830
- });
831
- }
832
- function hasVolumetricFogCapability(caps, shaders) {
833
- return caps.compute && caps.storageTexture && shaders !== void 0;
834
- }
835
- function resolveVolumetricFogLightPair(world, point, spot) {
836
- const expected = "PointLight + SpotLight in the same World";
837
- if (!world.get(point, Entity).ok || !world.get(spot, Entity).ok) {
838
- return {
839
- status: "unresolved",
840
- reason: "missing-entity",
841
- point,
842
- spot,
843
- expected,
844
- actual: "point or spot entity is absent from this World",
845
- hint: "assign two live entities from the same World and retry"
846
- };
847
- }
848
- if (point === spot) {
849
- return {
850
- status: "unresolved",
851
- reason: "same-entity",
852
- point,
853
- spot,
854
- expected,
855
- actual: "PointLight and SpotLight share one EntityHandle",
856
- hint: "spawn PointLight and SpotLight on two different entities"
857
- };
858
- }
859
- const pointValid = world.hasComponent(point, PointLight) && world.hasComponent(point, Transform);
860
- const spotValid = world.hasComponent(spot, SpotLight) && world.hasComponent(spot, Transform);
861
- if (!pointValid || !spotValid) {
862
- return {
863
- status: "unresolved",
864
- reason: "wrong-component",
865
- point,
866
- spot,
867
- expected,
868
- actual: `pointValid=${pointValid}; spotValid=${spotValid}`,
869
- hint: "attach PointLight and SpotLight with Transform to separate same-World entities"
870
- };
871
- }
872
- return { status: "available", mode: "point-spot", point, spot };
873
- }
874
- function resolveSelectedVolumetricLight(world, entity) {
875
- const expected = "DirectionalLight | PointLight | SpotLight";
876
- if (!world.get(entity, Entity).ok) {
877
- return {
878
- status: "unresolved",
879
- reason: "missing-entity",
880
- entity,
881
- expected,
882
- actual: "missing or foreign World entity",
883
- hint: "assign VolumetricFog.light to a live DirectionalLight or SpotLight in this World"
884
- };
885
- }
886
- const hasDirectional = world.hasComponent(entity, DirectionalLight);
887
- const hasSpot = world.hasComponent(entity, SpotLight);
888
- if (hasDirectional && hasSpot) {
889
- return {
890
- status: "unresolved",
891
- reason: "ambiguous",
892
- entity,
893
- expected,
894
- actual: "DirectionalLight + SpotLight",
895
- hint: "remove one mutually exclusive light component from the selected entity"
896
- };
897
- }
898
- if (hasDirectional) return { status: "available", entity, kind: "directional" };
899
- if (world.hasComponent(entity, PointLight) && world.hasComponent(entity, Transform)) {
900
- return { status: "available", entity, kind: "point" };
901
- }
902
- if (hasSpot && world.hasComponent(entity, Transform)) {
903
- return { status: "available", entity, kind: "spot" };
904
- }
905
- const actual = hasSpot ? "SpotLight without Transform" : world.hasComponent(entity, PointLight) ? "PointLight" : "other component";
906
- return {
907
- status: "unresolved",
908
- reason: "wrong-component",
909
- entity,
910
- expected,
911
- actual,
912
- hint: "add exactly one supported light component and a Transform for PointLight or SpotLight in the same World"
913
- };
914
- }
915
- function resolveIntegratedVolumeConsumer(resource, consumer) {
916
- return { consumer, resource };
917
- }
918
-
919
- // src/reflection/filter.ts
920
- function createProbeFilterState(input) {
921
- return {
922
- probeIndex: input.probeIndex,
923
- faceCount: input.faceCount ?? 6,
924
- mipCount: input.mipCount,
925
- cursor: 0,
926
- activeGeneration: input.activeGeneration ?? 0
927
- };
928
- }
929
- function advanceProbeFilter(state) {
930
- const total = state.faceCount * state.mipCount;
931
- if (state.cursor >= total) return void 0;
932
- return {
933
- probeIndex: state.probeIndex,
934
- faceIndex: state.cursor % state.faceCount,
935
- mipLevel: Math.floor(state.cursor / state.faceCount)
936
- };
937
- }
938
- function commitProbeFilterStep(state, success) {
939
- if (!success) return state;
940
- const nextCursor = state.cursor + 1;
941
- const complete = nextCursor >= state.faceCount * state.mipCount;
942
- return {
943
- ...state,
944
- cursor: nextCursor,
945
- activeGeneration: complete ? state.activeGeneration + 1 : state.activeGeneration
946
- };
947
- }
948
- function probeFilterIsSteady(state) {
949
- return state.cursor >= state.faceCount * state.mipCount;
950
- }
951
- function normalize(vector) {
952
- const length = Math.hypot(vector[0], vector[1], vector[2]);
953
- if (length === 0) return [0, 0, 1];
954
- return [vector[0] / length, vector[1] / length, vector[2] / length];
955
- }
956
- function boxProjectReflectionDirection(direction, boxCenter, halfExtents, point) {
957
- const ray = normalize(direction);
958
- let distance = Number.POSITIVE_INFINITY;
959
- for (let axis = 0; axis < 3; axis += 1) {
960
- const component = ray[axis] ?? 0;
961
- if (component === 0) continue;
962
- const extent = halfExtents[axis] ?? 0;
963
- const edge = component > 0 ? (boxCenter[axis] ?? 0) + extent : (boxCenter[axis] ?? 0) - extent;
964
- const candidate = (edge - (point[axis] ?? 0)) / component;
965
- if (candidate > 0) distance = Math.min(distance, candidate);
966
- }
967
- if (!Number.isFinite(distance)) return ray;
968
- return normalize([
969
- (point[0] ?? 0) + ray[0] * distance - (boxCenter[0] ?? 0),
970
- (point[1] ?? 0) + ray[1] * distance - (boxCenter[1] ?? 0),
971
- (point[2] ?? 0) + ray[2] * distance - (boxCenter[2] ?? 0)
972
- ]);
973
- }
974
-
975
- // src/reflection/gpu-table.ts
976
- function buildReflectionProbeTable(rows) {
977
- const ordered = rows.slice().sort((a, b) => a.index - b.index);
978
- const indices = /* @__PURE__ */ new Map();
979
- for (const row of ordered) {
980
- if (row.primitiveKey !== void 0) indices.set(row.primitiveKey, row.index);
981
- }
982
- const indexFor = (primitiveKey2) => indices.get(primitiveKey2);
983
- return {
984
- rows: Object.freeze(ordered),
985
- cpuIndexByPrimitive: indexFor,
986
- gpuIndexByPrimitive: indexFor
987
- };
988
- }
989
- function reflectionProbeTableBytes(table) {
990
- return table.rows.length * 48;
991
- }
992
-
993
- // src/reflection/projection.ts
994
- var REFLECTION_PROBE_BYTES_PER_TEXEL = 8;
995
- var DEFAULT_REFLECTION_PROBE_LIMITS = Object.freeze({
996
- maxProbes: 16,
997
- maxResolution: 256,
998
- maxBytes: 64 * 1024 * 1024
999
- });
1000
- function validateReflectionProbeInput(input) {
1001
- for (let index = 0; index < input.halfExtents.length; index += 1) {
1002
- const value = input.halfExtents[index];
1003
- if (value === void 0 || !Number.isFinite(value) || value <= 0) {
1004
- return {
1005
- ok: false,
1006
- error: {
1007
- code: "reflection-probe-input-invalid",
1008
- field: `halfExtents[${index}]`,
1009
- value,
1010
- expected: "a finite number greater than zero"
1011
- }
1012
- };
1013
- }
1014
- }
1015
- if (!Number.isFinite(input.priority)) {
1016
- return {
1017
- ok: false,
1018
- error: {
1019
- code: "reflection-probe-input-invalid",
1020
- field: "priority",
1021
- value: input.priority,
1022
- expected: "a finite number"
1023
- }
1024
- };
1025
- }
1026
- if (!Number.isFinite(input.intensity) || input.intensity < 0) {
1027
- return {
1028
- ok: false,
1029
- error: {
1030
- code: "reflection-probe-input-invalid",
1031
- field: "intensity",
1032
- value: input.intensity,
1033
- expected: "a finite number greater than or equal to zero"
1034
- }
1035
- };
1036
- }
1037
- if (!Number.isInteger(input.resolution) || input.resolution <= 0) {
1038
- return {
1039
- ok: false,
1040
- error: {
1041
- code: "reflection-probe-input-invalid",
1042
- field: "resolution",
1043
- value: input.resolution,
1044
- expected: "a positive integer"
1045
- }
1046
- };
1047
- }
1048
- return { ok: true };
1049
- }
1050
- function estimateReflectionProbeBytes(resolution, limits = DEFAULT_REFLECTION_PROBE_LIMITS) {
1051
- const maxResolution = limits.maxResolution ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxResolution;
1052
- const clamped = Math.min(resolution, maxResolution);
1053
- let mipTexels = 0;
1054
- for (let size = clamped; size >= 1; size = Math.floor(size / 2)) {
1055
- mipTexels += size * size;
1056
- }
1057
- return mipTexels * 6 * REFLECTION_PROBE_BYTES_PER_TEXEL;
1058
- }
1059
- function admitReflectionProbe(input, current, limits = DEFAULT_REFLECTION_PROBE_LIMITS) {
1060
- const maxProbes = limits.maxProbes ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxProbes;
1061
- const maxBytes = limits.maxBytes ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxBytes;
1062
- const maxResolution = limits.maxResolution ?? DEFAULT_REFLECTION_PROBE_LIMITS.maxResolution;
1063
- const requested = estimateReflectionProbeBytes(input.resolution, { maxResolution });
1064
- if (input.resolution > maxResolution || current.acceptedCount >= maxProbes || current.acceptedBytes + requested > maxBytes) {
1065
- return {
1066
- ok: false,
1067
- error: {
1068
- code: "reflection-probe-budget-exceeded",
1069
- requested,
1070
- activeCount: current.acceptedCount,
1071
- activeBytes: current.acceptedBytes,
1072
- maxProbes,
1073
- maxBytes
1074
- }
1075
- };
1076
- }
1077
- return { ok: true, acceptedBytes: current.acceptedBytes + requested };
1078
- }
1079
- function contains(fact, point) {
1080
- return fact.halfExtents.every((extent, axis) => {
1081
- const center = fact.center[axis] ?? 0;
1082
- const coordinate = point[axis] ?? 0;
1083
- return Math.abs(coordinate - center) <= extent;
1084
- });
1085
- }
1086
- function normalizedDistance(fact, point) {
1087
- let squared = 0;
1088
- for (let axis = 0; axis < 3; axis += 1) {
1089
- const delta = (point[axis] ?? 0) - (fact.center[axis] ?? 0);
1090
- const extent = fact.halfExtents[axis] ?? 1;
1091
- squared += (delta / extent) ** 2;
1092
- }
1093
- return squared;
1094
- }
1095
- function isBetter(candidate, current, facts) {
1096
- const candidateFact = facts.find(
1097
- (fact) => fact.worldId === candidate.worldId && fact.entityKey === candidate.entityKey
1098
- );
1099
- const currentFact = facts.find(
1100
- (fact) => fact.worldId === current.worldId && fact.entityKey === current.entityKey
1101
- );
1102
- if (candidateFact === void 0 || currentFact === void 0) return false;
1103
- if (candidateFact.priority !== currentFact.priority)
1104
- return candidateFact.priority > currentFact.priority;
1105
- if (candidate.normalizedDistance !== current.normalizedDistance) {
1106
- return candidate.normalizedDistance < current.normalizedDistance;
1107
- }
1108
- return candidate.worldId < current.worldId || candidate.worldId === current.worldId && candidate.entityKey < current.entityKey;
1109
- }
1110
- function selectReflectionProbe(facts, primitiveCenter) {
1111
- let selected;
1112
- for (const fact of facts) {
1113
- if (!contains(fact, primitiveCenter)) continue;
1114
- const candidate = {
1115
- kind: "probe",
1116
- worldId: fact.worldId,
1117
- entityKey: fact.entityKey,
1118
- normalizedDistance: normalizedDistance(fact, primitiveCenter)
1119
- };
1120
- if (selected === void 0 || isBetter(candidate, selected, facts)) selected = candidate;
1121
- }
1122
- return selected ?? { kind: "skylight" };
1123
- }
1124
- function primitiveKey(worldId, entityKey) {
1125
- return `${worldId}:${entityKey}`;
1126
- }
1127
- var ReflectionProbeProjection = class {
1128
- revision = 0;
1129
- facts = [];
1130
- selected = /* @__PURE__ */ new Map();
1131
- signature = "";
1132
- scannedPrimitives = 0;
1133
- update(facts, primitives) {
1134
- const nextFacts = facts.slice().sort((a, b) => a.worldId - b.worldId || a.entityKey - b.entityKey);
1135
- const signature = JSON.stringify({ facts: nextFacts, primitives });
1136
- if (signature === this.signature) return this.snapshot();
1137
- this.signature = signature;
1138
- this.facts = nextFacts;
1139
- this.selected = /* @__PURE__ */ new Map();
1140
- for (const primitive of primitives) {
1141
- this.selected.set(
1142
- primitiveKey(primitive.worldId, primitive.entityKey),
1143
- selectReflectionProbe(nextFacts, primitive.center)
1144
- );
1145
- }
1146
- this.scannedPrimitives = primitives.length;
1147
- this.revision += 1;
1148
- return this.snapshot();
1149
- }
1150
- snapshot() {
1151
- return {
1152
- revision: this.revision,
1153
- facts: this.facts,
1154
- selected: this.selected,
1155
- scannedPrimitives: this.scannedPrimitives
1156
- };
1157
- }
1158
- selection(worldId, entityKey) {
1159
- return this.selected.get(primitiveKey(worldId, entityKey)) ?? { kind: "skylight" };
1160
- }
1161
- };
1162
- var VISIBILITY_CACHE = /* @__PURE__ */ new WeakMap();
1163
936
  function resolveVisibility(world, hierarchy = projectHierarchy(world)) {
1164
- const cached = VISIBILITY_CACHE.get(world);
1165
- const changes = cached?.changes ?? createWorldProjection(world, { components: [Visibility] });
1166
- if (cached !== void 0) {
1167
- const evidence = changes.poll();
1168
- if (evidence.status === "delta" && evidence.changes.length === 0 && cached.hierarchy === hierarchy) {
1169
- return cached.snapshot;
1170
- }
1171
- }
1172
937
  const query = world.query({ read: [Visibility] });
1173
938
  const visitVisibilityRows = (visit) => {
1174
939
  if (!query.ok) return;
@@ -1242,7 +1007,6 @@ function resolveVisibility(world, hierarchy = projectHierarchy(world)) {
1242
1007
  return resolveEntity?.(entity)?.effective ?? "visible";
1243
1008
  }
1244
1009
  };
1245
- VISIBILITY_CACHE.set(world, { changes, hierarchy, snapshot });
1246
1010
  return snapshot;
1247
1011
  }
1248
1012
  var VolumetricFog = defineComponent("VolumetricFog", {
@@ -1289,6 +1053,6 @@ function extractVolumetricFog(inputs) {
1289
1053
  return ok({ status: "available", fog: validated.value });
1290
1054
  }
1291
1055
 
1292
- export { ANTIALIAS_FXAA, ANTIALIAS_MSAA, ANTIALIAS_NONE, ANTIALIAS_TAA, Atmosphere, BLOOM_DISABLED, BLOOM_ENABLED, CAMERA_PROJECTION_ORTHOGRAPHIC, CAMERA_PROJECTION_PERSPECTIVE, CUBE_CAMERA_FACE_ORDER, CUBE_CAMERA_UPDATE_CONTINUOUS, CUBE_CAMERA_UPDATE_ONCE, CUBE_CAMERA_UPDATE_ON_DEMAND, Camera, CubeCamera, DEFAULT_REFLECTION_PROBE_LIMITS, DirectionalLight, DirectionalShadowFilterValue, Fog, Instances, Layer, Lines, MeshFilter, MeshRenderer, MotionBlur, PointLight, PointLightShadow, PointShapeValue, Points, PostProcessParams, REFLECTION_PROBE_UPDATE_CONTINUOUS, REFLECTION_PROBE_UPDATE_ONCE, REFLECTION_PROBE_UPDATE_ON_CHANGE, ReflectionProbe, ReflectionProbeProjection, SKYBOX_MODE_CUBEMAP, SceneInstance, SkyboxBackground, Skylight, SortKey, SpotLight, TONEMAP_ACES_FILMIC, TONEMAP_AGX, TONEMAP_CINEON, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE, TONEMAP_REINHARD, TONEMAP_REINHARD_EXTENDED, Visibility, VisibilityStateValue, VolumetricFog, admitPointsLines, admitReflectionProbe, advanceProbeFilter, antialiasFromF32, bloomEnabledFromF32, boxProjectReflectionDirection, buildCubeCameraFaceViews, buildReflectionProbeTable, cameraProjectionFromF32, commitProbeFilterStep, createProbeFilterState, cubeCameraUpdateIntentFromF32, cubeCameraUpdateIntentToF32, directionalShadowQualityFromF32, estimateReflectionProbeBytes, extractVolumetricFog, hasVolumetricFogCapability, inspectPointShadow, inspectVolumetricFog, orthographic, perspective, pointShapeFromU32, probeFilterIsSteady, projectMeshMaterialBindingObservation, reflectionProbeTableBytes, reflectionProbeUpdateIntentFromF32, reflectionProbeUpdateIntentToF32, resolveIntegratedVolumeConsumer, resolveMeshMaterialBindings, resolveSelectedVolumetricLight, resolveVisibility, resolveVolumetricFogLightPair, selectReflectionProbe, summarizeMeshMaterialBindings, tonemapFromF32, tonemapToU32, validateReflectionProbeInput, validateVolumetricFog, visibilityStateFromU32 };
1293
- //# sourceMappingURL=chunk-FS2KNUQH.mjs.map
1294
- //# sourceMappingURL=chunk-FS2KNUQH.mjs.map
1056
+ export { ANTIALIAS_FXAA, ANTIALIAS_MSAA, ANTIALIAS_NONE, ANTIALIAS_TAA, Atmosphere, BLOOM_DISABLED, BLOOM_ENABLED, CAMERA_PROJECTION_ORTHOGRAPHIC, CAMERA_PROJECTION_PERSPECTIVE, CUBE_CAMERA_FACE_ORDER, CUBE_CAMERA_UPDATE_CONTINUOUS, CUBE_CAMERA_UPDATE_ONCE, CUBE_CAMERA_UPDATE_ON_DEMAND, Camera, CubeCamera, DirectionalLight, DirectionalShadowFilterValue, Fog, Instances, Layer, LightProbe, Lines, MeshFilter, MeshRenderer, MotionBlur, PointLight, PointLightShadow, PointShapeValue, Points, PostProcessParams, REFLECTION_PROBE_UPDATE_CONTINUOUS, REFLECTION_PROBE_UPDATE_ONCE, REFLECTION_PROBE_UPDATE_ON_CHANGE, RectAreaLight, ReflectionProbe, SKYBOX_MODE_CUBEMAP, SceneInstance, SkyboxBackground, Skylight, SortKey, SpotLight, TONEMAP_ACES_FILMIC, TONEMAP_AGX, TONEMAP_CINEON, TONEMAP_LINEAR, TONEMAP_NEUTRAL, TONEMAP_NONE, TONEMAP_REINHARD, TONEMAP_REINHARD_EXTENDED, Visibility, VisibilityStateValue, VolumetricFog, antialiasFromF32, bloomEnabledFromF32, cameraProjectionFromF32, computeInvRangeSquared, createVisibilityBudget, cubeCameraUpdateIntentFromF32, cubeCameraUpdateIntentToF32, degToCos, directionalShadowQualityFromF32, extractVolumetricFog, hasVolumetricFogCapability, orthographic, perspective, pointShapeFromU32, projectMeshMaterialBindingObservation, reflectionProbeUpdateIntentFromF32, reflectionProbeUpdateIntentToF32, resolveIntegratedVolumeConsumer, resolveMeshMaterialBindings, resolveSelectedVolumetricLight, resolveVisibility, resolveVolumetricFogLightPair, summarizeMeshMaterialBindings, tonemapFromF32, tonemapToU32, validateDirection, validateDirectionalLightData, validateLightProbeData, validatePointLightData, validatePointLightShadowData, validateRectAreaLightData, validateSpotLightData, validateVolumetricFog, visibilityStateFromU32 };
1057
+ //# sourceMappingURL=chunk-Q752SHI5.mjs.map
1058
+ //# sourceMappingURL=chunk-Q752SHI5.mjs.map