@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
@@ -27,6 +27,7 @@
27
27
 
28
28
  import { type Mat4, type Vec3, vec3 } from '@forgeax/engine-math';
29
29
  import { err, ok, type Result } from '@forgeax/engine-rhi';
30
+ import type { RectAreaWorldFrame } from './render-system-extract';
30
31
 
31
32
  // ── types ──────────────────────────────────────────────────────────────────
32
33
 
@@ -174,6 +175,36 @@ export function deriveCullingRadius(range: number, intensity: number, threshold
174
175
  return Math.min(derived, 1000);
175
176
  }
176
177
 
178
+ /** Conservative bounding-sphere radius for a finite Rect and its light range. */
179
+ export function rectAreaClusterRadius(frame: RectAreaWorldFrame, range: number): number {
180
+ return Math.max(0, range) + Math.hypot(frame.halfWidth, frame.halfHeight);
181
+ }
182
+
183
+ /** Test the finite Rect's closest-point distance against a strict range window. */
184
+ export function rectAreaIsInRange(
185
+ frame: RectAreaWorldFrame,
186
+ point: ArrayLike<number>,
187
+ range: number,
188
+ ): boolean {
189
+ const toPoint = vec3.create(
190
+ (point[0] ?? 0) - (frame.center[0] ?? 0),
191
+ (point[1] ?? 0) - (frame.center[1] ?? 0),
192
+ (point[2] ?? 0) - (frame.center[2] ?? 0),
193
+ );
194
+ const localX = Math.min(
195
+ frame.halfWidth,
196
+ Math.max(-frame.halfWidth, vec3.dot(toPoint, frame.axisX)),
197
+ );
198
+ const localY = Math.min(
199
+ frame.halfHeight,
200
+ Math.max(-frame.halfHeight, vec3.dot(toPoint, frame.axisY)),
201
+ );
202
+ const dx = (toPoint[0] ?? 0) - (frame.axisX[0] ?? 0) * localX - (frame.axisY[0] ?? 0) * localY;
203
+ const dy = (toPoint[1] ?? 0) - (frame.axisX[1] ?? 0) * localX - (frame.axisY[1] ?? 0) * localY;
204
+ const dz = (toPoint[2] ?? 0) - (frame.axisX[2] ?? 0) * localX - (frame.axisY[2] ?? 0) * localY;
205
+ return dx * dx + dy * dy + dz * dz < range * range;
206
+ }
207
+
177
208
  // ── view_z_to_z_slice ──────────────────────────────────────────────────────
178
209
 
179
210
  /**
@@ -0,0 +1,39 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ LightProbe,
4
+ RectAreaLight,
5
+ SpotLight,
6
+ validateLightProbeData,
7
+ validateRectAreaLightData,
8
+ } from '../index';
9
+
10
+ describe('lighting authoring contracts', () => {
11
+ it('exposes only the declared Rect, Spot modifier, and Probe fields', () => {
12
+ expect(Object.keys(RectAreaLight.fields)).toEqual([
13
+ 'color',
14
+ 'intensity',
15
+ 'width',
16
+ 'height',
17
+ 'range',
18
+ ]);
19
+ expect(Object.keys(LightProbe.fields)).toEqual(['irradiance', 'radius']);
20
+ expect(SpotLight.fields.iesProfile.type).toBe('shared<IesProfileAsset>');
21
+ expect(SpotLight.fields.cookie.type).toBe('shared<TextureAsset>');
22
+ expect(SpotLight.fields.rollDeg.default).toBe(0);
23
+ });
24
+
25
+ it('keeps defaults and rejects invalid Rect/Probe facts before rendering', () => {
26
+ expect(RectAreaLight.fields.width.default).toBe(1);
27
+ expect(RectAreaLight.fields.height.default).toBe(1);
28
+ expect(LightProbe.fields.irradiance.type).toBe('array<f32, 27>');
29
+ expect(LightProbe.fields.radius.default).toBe(1e-4);
30
+
31
+ expect(validateRectAreaLightData({}).ok).toBe(true);
32
+ expect(validateRectAreaLightData({ width: 0 }).ok).toBe(false);
33
+ expect(validateRectAreaLightData({ intensity: Number.NaN }).ok).toBe(false);
34
+ expect(validateLightProbeData({ irradiance: new Float32Array(26), radius: 1 }).ok).toBe(false);
35
+ expect(validateLightProbeData({ irradiance: new Float32Array(27), radius: 1e-5 }).ok).toBe(
36
+ false,
37
+ );
38
+ });
39
+ });
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildRectAreaWorldFrame, rectAreaFacesPoint } from '../../render-system-extract';
3
+
4
+ describe('RectAreaLight world frame', () => {
5
+ it('normalizes world axes while preserving authored half extents', () => {
6
+ const frame = buildRectAreaWorldFrame({
7
+ center: [1, 2, 3],
8
+ axisX: [0, 2, 0],
9
+ axisY: [-3, 0, 0],
10
+ width: 4,
11
+ height: 2,
12
+ });
13
+
14
+ expect(Array.from(frame.axisX)).toEqual([0, 1, 0]);
15
+ expect(Array.from(frame.axisY)).toEqual([-1, 0, 0]);
16
+ expect(Array.from(frame.normal)).toEqual([0, 0, 1]);
17
+ expect(frame.halfWidth).toBe(2);
18
+ expect(frame.halfHeight).toBe(1);
19
+ });
20
+
21
+ it('defines the front from the world-axis cross product', () => {
22
+ const frame = buildRectAreaWorldFrame({
23
+ center: [0, 0, 0],
24
+ axisX: [1, 0, 0],
25
+ axisY: [0, 1, 0],
26
+ width: 2,
27
+ height: 2,
28
+ });
29
+
30
+ expect(rectAreaFacesPoint(frame, [0, 0, 1])).toBe(true);
31
+ expect(rectAreaFacesPoint(frame, [0, 0, -1])).toBe(false);
32
+ });
33
+ });
@@ -14,7 +14,7 @@
14
14
  // outside M3 scope — the short-name mat4.perspective
15
15
  // already writes [0, 1] NDC, matching the ortho branch.
16
16
  // projection === 1 → orthographic path; RenderSystem builds
17
- // mat4.orthographic(out, left, right, bottom, top,
17
+ // mat4.orthographic(out, left, right, top, bottom,
18
18
  // near, far) (WebGPU [0, 1] NDC; same z convention).
19
19
  //
20
20
  // Naming convention: forgeax uses the bare `Camera` name (no `Component`
@@ -5,6 +5,8 @@ export * from './directional-light';
5
5
  export * from './fog';
6
6
  export { Instances, type InstancesData } from './instances';
7
7
  export { Layer } from './layer';
8
+ export * from './light-helpers';
9
+ export { LightProbe } from './light-probe';
8
10
  export { Lines } from './lines';
9
11
  export * from './mesh-filter';
10
12
  export * from './mesh-renderer';
@@ -18,6 +20,7 @@ export {
18
20
  pointShapeFromU32,
19
21
  } from './points';
20
22
  export { PostProcessParams } from './post-process-params';
23
+ export { RectAreaLight } from './rect-area-light';
21
24
  export * from './reflection-probe';
22
25
  export {
23
26
  SceneInstance,
@@ -14,7 +14,7 @@
14
14
  // transparent to AI users) + D-S5 (Layer 1 host-side range = 0 ->
15
15
  // invRangeSquared = 1e8 protects the 0 * Infinity = NaN intermediate).
16
16
 
17
- import { err, ok, type Result } from '@forgeax/engine-types';
17
+ import { err, ok, R_MIN, type Result } from '@forgeax/engine-types';
18
18
  import { SpawnLightInvalidBoundsError } from '../errors/ecs-validation';
19
19
  import { ShadowInvalidConfigError } from '../errors/render';
20
20
  import { DirectionalShadowFilterValue } from './directional-shadow-filter';
@@ -264,3 +264,54 @@ export function validatePointLightShadowData(
264
264
  }
265
265
  return ok(undefined);
266
266
  }
267
+
268
+ /** Validate rectangular area-light authoring facts before renderer admission. */
269
+ export function validateRectAreaLightData(
270
+ data: Readonly<Record<string, unknown>>,
271
+ ): LightValidationResult {
272
+ const intensity = (data.intensity as number | undefined) ?? 1;
273
+ if (typeof intensity !== 'number' || !Number.isFinite(intensity) || intensity < 0) {
274
+ return err(new SpawnLightInvalidBoundsError('RectAreaLight', 'intensity', intensity));
275
+ }
276
+ const color = (data.color as ArrayLike<number> | undefined) ?? [1, 1, 1];
277
+ if (
278
+ color.length !== 3 ||
279
+ Array.from(color).some(
280
+ (value) => typeof value !== 'number' || !Number.isFinite(value) || value < 0,
281
+ )
282
+ ) {
283
+ return err(new SpawnLightInvalidBoundsError('RectAreaLight', 'color', Array.from(color)));
284
+ }
285
+ for (const field of ['width', 'height', 'range'] as const) {
286
+ const value = (data[field] as number | undefined) ?? (field === 'range' ? 10 : 1);
287
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
288
+ return err(new SpawnLightInvalidBoundsError('RectAreaLight', field, value));
289
+ }
290
+ }
291
+ return ok(undefined);
292
+ }
293
+
294
+ /** Validate the fixed 27-value SH payload and minimum finite radius. */
295
+ export function validateLightProbeData(
296
+ data: Readonly<Record<string, unknown>>,
297
+ ): LightValidationResult {
298
+ const irradiance = data.irradiance as ArrayLike<number> | undefined;
299
+ if (
300
+ irradiance === undefined ||
301
+ irradiance.length !== 27 ||
302
+ Array.from(irradiance).some((value) => typeof value !== 'number' || !Number.isFinite(value))
303
+ ) {
304
+ return err(
305
+ new SpawnLightInvalidBoundsError(
306
+ 'LightProbe',
307
+ 'irradiance',
308
+ irradiance === undefined ? [] : Array.from(irradiance),
309
+ ),
310
+ );
311
+ }
312
+ const radius = (data.radius as number | undefined) ?? R_MIN;
313
+ if (typeof radius !== 'number' || !Number.isFinite(radius) || radius < R_MIN) {
314
+ return err(new SpawnLightInvalidBoundsError('LightProbe', 'radius', radius));
315
+ }
316
+ return ok(undefined);
317
+ }
@@ -0,0 +1,13 @@
1
+ // @forgeax/engine-render - local diffuse LightProbe authoring facts.
2
+
3
+ import { defineComponent } from '@forgeax/engine-ecs';
4
+ import { R_MIN } from '@forgeax/engine-types';
5
+
6
+ /**
7
+ * Local diffuse irradiance probe. Transform supplies position; the 27 SH
8
+ * values are nine RGB groups in the fixed real-SH order.
9
+ */
10
+ export const LightProbe = defineComponent('LightProbe', {
11
+ irradiance: { type: 'array<f32, 27>' },
12
+ radius: { type: 'f32', default: R_MIN },
13
+ });
@@ -0,0 +1,15 @@
1
+ // @forgeax/engine-render - single-sided rectangular area-light authoring facts.
2
+
3
+ import { defineComponent } from '@forgeax/engine-ecs';
4
+
5
+ /**
6
+ * Single-sided rectangular area light. Transform supplies the center and
7
+ * world orientation; width and height remain authored emitter dimensions.
8
+ */
9
+ export const RectAreaLight = defineComponent('RectAreaLight', {
10
+ color: { type: 'array<f32, 3>', default: new Float32Array([1, 1, 1]) },
11
+ intensity: { type: 'f32', default: 1 },
12
+ width: { type: 'f32', default: 1 },
13
+ height: { type: 'f32', default: 1 },
14
+ range: { type: 'f32', default: 10 },
15
+ });
@@ -94,6 +94,12 @@ export interface SceneInstanceState {
94
94
  */
95
95
  readonly source: import('@forgeax/engine-types').Handle<'SceneAsset', 'shared'>;
96
96
 
97
+ /** Author scene identity used by instance-relative SceneEntityRef resolution. */
98
+ readonly sceneSourceKey?: string;
99
+
100
+ /** Stable author bindingKey to live Entity mapping for this concrete instance. */
101
+ readonly bindings: Map<string, EntityHandle>;
102
+
97
103
  /**
98
104
  * Reverse mapping (live `Entity` -> source `LocalEntityId`). Used by
99
105
  * `world.setSceneOverride` to validate the member entity belongs to this
@@ -124,6 +124,9 @@ export const SpotLight = defineComponent('SpotLight', {
124
124
  range: { type: 'f32', default: 10.0 },
125
125
  innerConeDeg: { type: 'f32', default: 0 },
126
126
  outerConeDeg: { type: 'f32', default: 45 },
127
+ iesProfile: { type: 'shared<IesProfileAsset>' },
128
+ cookie: { type: 'shared<TextureAsset>' },
129
+ rollDeg: { type: 'f32', default: 0 },
127
130
  // Shadow opt-out gate: defaults to true so zero-config spawns cast shadows.
128
131
  castShadow: { type: 'bool', default: true },
129
132
  // 7 shadow fields aligned with the shared light shadow vocabulary.
@@ -23,8 +23,8 @@ export function addTypedDebugOverlayPass(
23
23
  projection,
24
24
  frame.camera.orthoLeft,
25
25
  frame.camera.orthoRight,
26
- frame.camera.orthoBottom,
27
26
  frame.camera.orthoTop,
27
+ frame.camera.orthoBottom,
28
28
  frame.camera.near,
29
29
  frame.camera.far,
30
30
  );
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ createExtendedLightingResourceCandidate,
4
+ inspectExtendedLightingResources,
5
+ } from '../../prepare/extended-lighting/resources';
6
+ import { DeviceScope } from '../device-scope';
7
+
8
+ describe('extended lighting device recovery', () => {
9
+ it('retires the old scope and rebuilds one accepted resource generation', async () => {
10
+ const oldScope = DeviceScope.create(8, 'renderer');
11
+ const oldResource = oldScope.ref('texture', { id: 'old' });
12
+ const candidate = await createExtendedLightingResourceCandidate({
13
+ device: undefined,
14
+ scope: oldScope,
15
+ iesSliceCount: 0,
16
+ cookieSliceCount: 0,
17
+ cookieMatrices: 0,
18
+ });
19
+
20
+ expect(candidate.ok).toBe(false);
21
+ expect(oldResource.isCurrent(oldScope)).toBe(true);
22
+ expect(inspectExtendedLightingResources(oldScope).generation).toBe(8);
23
+ });
24
+ });
@@ -46,6 +46,17 @@ interface OwnedResource {
46
46
  readonly cleanup: (value: unknown) => void | Promise<void>;
47
47
  }
48
48
 
49
+ function idempotentCleanup<T>(
50
+ cleanup: (value: T) => void | Promise<void>,
51
+ ): (value: T) => void | Promise<void> {
52
+ let cleaned = false;
53
+ return (value: T) => {
54
+ if (cleaned) return;
55
+ cleaned = true;
56
+ return cleanup(value);
57
+ };
58
+ }
59
+
49
60
  export class DeviceScope {
50
61
  readonly generation: number;
51
62
  readonly owner: string;
@@ -117,7 +128,7 @@ export class DeviceScope {
117
128
  const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);
118
129
  this.resources.push({
119
130
  ref: ref as DeviceResourceRef<unknown>,
120
- cleanup: cleanup as (resource: unknown) => void | Promise<void>,
131
+ cleanup: idempotentCleanup(cleanup) as (resource: unknown) => void | Promise<void>,
121
132
  });
122
133
  return ref;
123
134
  }
@@ -142,9 +153,21 @@ export class DeviceScope {
142
153
  if (this.lifecycleState === 'active') this.lifecycleState = 'retiring';
143
154
  }
144
155
 
156
+ private clearChildren(): void {
157
+ for (const child of [...this.children].reverse()) {
158
+ child.retire();
159
+ }
160
+ }
161
+
162
+ private detachChild(child: DeviceScope): void {
163
+ const index = this.children.indexOf(child);
164
+ if (index >= 0) this.children.splice(index, 1);
165
+ }
166
+
145
167
  retire(): void {
146
168
  if (this.lifecycleState !== 'active' && this.lifecycleState !== 'retiring') return;
147
169
  this.lifecycleState = 'retiring';
170
+ this.clearChildren();
148
171
  this._clearResources();
149
172
  this.lifecycleState = 'retired';
150
173
  }
@@ -152,12 +175,14 @@ export class DeviceScope {
152
175
  abandon(): void {
153
176
  if (this.lifecycleState !== 'active') return;
154
177
  this.lifecycleState = 'abandoned';
178
+ this.clearChildren();
155
179
  this._clearResources();
156
180
  }
157
181
 
158
182
  dispose(): void {
159
183
  if (this.lifecycleState === 'disposed') return;
160
184
  this.lifecycleState = 'disposed';
185
+ this.clearChildren();
161
186
  this._clearResources();
162
187
  }
163
188
 
@@ -177,6 +202,9 @@ export class DeviceScope {
177
202
  replacement.dispose();
178
203
  return transaction.failure('dispose');
179
204
  }
205
+ // The replacement is now the new owner. Detach it before retiring the
206
+ // old parent so parent cleanup cannot retire the just-published child.
207
+ this.detachChild(replacement);
180
208
  this.retire();
181
209
  return ok(replacement);
182
210
  }
@@ -217,6 +245,7 @@ export interface LifecycleTransactionOptions {
217
245
  interface CreatedResource {
218
246
  readonly spec: LifecycleResourceSpec<unknown>;
219
247
  readonly value: unknown;
248
+ readonly cleanup: (value: unknown) => void | Promise<void>;
220
249
  }
221
250
 
222
251
  export class LifecycleTransaction {
@@ -250,10 +279,10 @@ export class LifecycleTransaction {
250
279
  }
251
280
  const value = await spec.create();
252
281
  if (!this.scope.isAlive()) {
253
- await this.cleanupOne(spec, value, created);
282
+ await this.cleanupOne(value, created, idempotentCleanup(spec.cleanup));
254
283
  return this.failure('dispose');
255
284
  }
256
- created.push({ spec, value });
285
+ created.push({ spec, value, cleanup: idempotentCleanup(spec.cleanup) });
257
286
  } catch (cause) {
258
287
  const cleanupFailures = await this.cleanupCreated(created);
259
288
  return this.failure('create', spec.kind, cleanupFailures, cause);
@@ -296,7 +325,7 @@ export class LifecycleTransaction {
296
325
  const item = created[index];
297
326
  if (item === undefined) continue;
298
327
  try {
299
- await item.spec.cleanup(item.value);
328
+ await item.cleanup(item.value);
300
329
  } catch (cause) {
301
330
  failures.push({ resourceKind: item.spec.kind, cause });
302
331
  }
@@ -305,13 +334,13 @@ export class LifecycleTransaction {
305
334
  }
306
335
 
307
336
  private async cleanupOne(
308
- spec: LifecycleResourceSpec<unknown>,
309
337
  value: unknown,
310
338
  created: readonly CreatedResource[],
339
+ cleanup: (value: unknown) => void | Promise<void>,
311
340
  ): Promise<void> {
312
341
  await this.cleanupCreated(created);
313
342
  try {
314
- await spec.cleanup(value);
343
+ await cleanup(value);
315
344
  } catch {
316
345
  // The terminal dispose result is intentionally bounded; prior cleanup
317
346
  // evidence remains in the transaction failure shape.