@forgeax/engine-render 0.1.19 → 0.1.21

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 (452) hide show
  1. package/README.md +215 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/assembly/device-feature-admission.d.ts +18 -0
  4. package/dist/assembly/device-feature-admission.d.ts.map +1 -0
  5. package/dist/assembly/directional-shadow-inspection.d.ts +38 -0
  6. package/dist/assembly/directional-shadow-inspection.d.ts.map +1 -0
  7. package/dist/assembly/factory.d.ts +34 -20
  8. package/dist/assembly/factory.d.ts.map +1 -1
  9. package/dist/assembly/host-contract.d.ts +9 -0
  10. package/dist/assembly/host-contract.d.ts.map +1 -1
  11. package/dist/assembly/render-target-host.d.ts +46 -0
  12. package/dist/assembly/render-target-host.d.ts.map +1 -0
  13. package/dist/assets/render-asset-port.d.ts.map +1 -1
  14. package/dist/authoring.mjs +3 -0
  15. package/dist/authoring.mjs.map +1 -1
  16. package/dist/capture/cube-views.d.ts +21 -0
  17. package/dist/capture/cube-views.d.ts.map +1 -0
  18. package/dist/capture/scheduler.d.ts +54 -0
  19. package/dist/capture/scheduler.d.ts.map +1 -0
  20. package/dist/{chunk-RJRUS55L.mjs → chunk-5YADUCA7.mjs} +1896 -1624
  21. package/dist/chunk-5YADUCA7.mjs.map +1 -0
  22. package/dist/{chunk-LOSO4CTV.mjs → chunk-6OPXDQ2E.mjs} +423 -46
  23. package/dist/chunk-6OPXDQ2E.mjs.map +1 -0
  24. package/dist/{chunk-IPXCABEP.mjs → chunk-BXBQQKFQ.mjs} +3 -9
  25. package/dist/chunk-BXBQQKFQ.mjs.map +1 -0
  26. package/dist/chunk-FS2KNUQH.mjs +1294 -0
  27. package/dist/chunk-FS2KNUQH.mjs.map +1 -0
  28. package/dist/components/camera.d.ts +1 -0
  29. package/dist/components/camera.d.ts.map +1 -1
  30. package/dist/components/cube-camera.d.ts +20 -0
  31. package/dist/components/cube-camera.d.ts.map +1 -0
  32. package/dist/components/directional-light.d.ts +11 -2
  33. package/dist/components/directional-light.d.ts.map +1 -1
  34. package/dist/components/directional-shadow-filter.d.ts +25 -0
  35. package/dist/components/directional-shadow-filter.d.ts.map +1 -0
  36. package/dist/components/index.d.ts +2 -0
  37. package/dist/components/index.d.ts.map +1 -1
  38. package/dist/components/light-helpers.d.ts.map +1 -1
  39. package/dist/components/reflection-probe.d.ts +17 -0
  40. package/dist/components/reflection-probe.d.ts.map +1 -0
  41. package/dist/components/spot-light.d.ts +12 -0
  42. package/dist/components/spot-light.d.ts.map +1 -1
  43. package/dist/construct-renderer.mjs +8552 -1612
  44. package/dist/construct-renderer.mjs.map +1 -1
  45. package/dist/device/gpu-residency.d.ts +19 -2
  46. package/dist/device/gpu-residency.d.ts.map +1 -1
  47. package/dist/environment/frame.d.ts.map +1 -1
  48. package/dist/environment/lifecycle.d.ts +5 -0
  49. package/dist/environment/lifecycle.d.ts.map +1 -1
  50. package/dist/errors/render.d.ts +209 -93
  51. package/dist/errors/render.d.ts.map +1 -1
  52. package/dist/extract/directional-shadow-projection.d.ts +23 -0
  53. package/dist/extract/directional-shadow-projection.d.ts.map +1 -0
  54. package/dist/extract/environment.d.ts +14 -0
  55. package/dist/extract/environment.d.ts.map +1 -1
  56. package/dist/extract/visibility.d.ts.map +1 -1
  57. package/dist/features/fullscreen.d.ts.map +1 -1
  58. package/dist/features/targets.d.ts.map +1 -1
  59. package/dist/features/types.d.ts +10 -0
  60. package/dist/features/types.d.ts.map +1 -1
  61. package/dist/fullscreen-post-process-pass.d.ts +13 -2
  62. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  63. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  64. package/dist/gpu-driven/production-raster.d.ts +0 -1
  65. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  66. package/dist/gpu-scene.d.ts.map +1 -1
  67. package/dist/gpu-usage.d.ts +2 -0
  68. package/dist/gpu-usage.d.ts.map +1 -1
  69. package/dist/hdrp-buffers.d.ts +19 -17
  70. package/dist/hdrp-buffers.d.ts.map +1 -1
  71. package/dist/ibl/IblPipelineCache.d.ts +4 -0
  72. package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
  73. package/dist/ibl/kernel-cache.d.ts +36 -0
  74. package/dist/ibl/kernel-cache.d.ts.map +1 -0
  75. package/dist/index.d.ts +35 -4
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.mjs +4 -4
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/inspection-types.d.ts +51 -0
  80. package/dist/inspection-types.d.ts.map +1 -1
  81. package/dist/instances-derived-bounds.d.ts +50 -0
  82. package/dist/instances-derived-bounds.d.ts.map +1 -0
  83. package/dist/internal.mjs +1 -1
  84. package/dist/light-buffer-layout.d.ts +30 -13
  85. package/dist/light-buffer-layout.d.ts.map +1 -1
  86. package/dist/mesh-material-bindings.d.ts +54 -0
  87. package/dist/mesh-material-bindings.d.ts.map +1 -1
  88. package/dist/pbr-pipeline.d.ts +20 -7
  89. package/dist/pbr-pipeline.d.ts.map +1 -1
  90. package/dist/pipeline/standard-forward-lane.d.ts +2 -1
  91. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  92. package/dist/pipeline/standard-lighting/errors.d.ts +4 -0
  93. package/dist/pipeline/standard-lighting/errors.d.ts.map +1 -0
  94. package/dist/pipeline/standard-lighting/graph.d.ts +24 -0
  95. package/dist/pipeline/standard-lighting/graph.d.ts.map +1 -0
  96. package/dist/pipeline/standard-lighting/inspection.d.ts +38 -0
  97. package/dist/pipeline/standard-lighting/inspection.d.ts.map +1 -0
  98. package/dist/pipeline/standard-lighting/layout.d.ts +28 -0
  99. package/dist/pipeline/standard-lighting/layout.d.ts.map +1 -0
  100. package/dist/pipeline/standard-lighting/light-frame.d.ts +33 -0
  101. package/dist/pipeline/standard-lighting/light-frame.d.ts.map +1 -0
  102. package/dist/pipeline/standard-lighting/membership.d.ts +14 -0
  103. package/dist/pipeline/standard-lighting/membership.d.ts.map +1 -0
  104. package/dist/pipeline/standard-lighting/prepare.d.ts +16 -0
  105. package/dist/pipeline/standard-lighting/prepare.d.ts.map +1 -0
  106. package/dist/pipeline/standard-lighting/topology.d.ts +45 -0
  107. package/dist/pipeline/standard-lighting/topology.d.ts.map +1 -0
  108. package/dist/pipeline/standard-lighting/transport.d.ts +36 -0
  109. package/dist/pipeline/standard-lighting/transport.d.ts.map +1 -0
  110. package/dist/pipeline/standard-pipeline.d.ts +4 -13
  111. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  112. package/dist/pipeline/standard-post.d.ts.map +1 -1
  113. package/dist/pipeline/standard-profile.d.ts +12 -20
  114. package/dist/pipeline/standard-profile.d.ts.map +1 -1
  115. package/dist/pipeline-spec.d.ts +40 -7
  116. package/dist/pipeline-spec.d.ts.map +1 -1
  117. package/dist/point-shadow-inspection.d.ts +21 -0
  118. package/dist/point-shadow-inspection.d.ts.map +1 -0
  119. package/dist/record/frame-lighting.d.ts +29 -32
  120. package/dist/record/frame-lighting.d.ts.map +1 -1
  121. package/dist/record/frame-snapshot.d.ts +65 -15
  122. package/dist/record/frame-snapshot.d.ts.map +1 -1
  123. package/dist/record/frame-targets.d.ts +5 -0
  124. package/dist/record/frame-targets.d.ts.map +1 -1
  125. package/dist/record/frame.d.ts +12 -5
  126. package/dist/record/frame.d.ts.map +1 -1
  127. package/dist/record/gpu-pass-timing/contract.d.ts +96 -0
  128. package/dist/record/gpu-pass-timing/contract.d.ts.map +1 -0
  129. package/dist/record/gpu-pass-timing/errors.d.ts +18 -0
  130. package/dist/record/gpu-pass-timing/errors.d.ts.map +1 -0
  131. package/dist/record/gpu-pass-timing/index.d.ts +8 -0
  132. package/dist/record/gpu-pass-timing/index.d.ts.map +1 -0
  133. package/dist/record/gpu-pass-timing/parser.d.ts +11 -0
  134. package/dist/record/gpu-pass-timing/parser.d.ts.map +1 -0
  135. package/dist/record/gpu-pass-timing/session.d.ts +43 -0
  136. package/dist/record/gpu-pass-timing/session.d.ts.map +1 -0
  137. package/dist/record/gpu-timing.d.ts +37 -0
  138. package/dist/record/gpu-timing.d.ts.map +1 -0
  139. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  140. package/dist/record/main-pass-material.d.ts +23 -2
  141. package/dist/record/main-pass-material.d.ts.map +1 -1
  142. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  143. package/dist/record/main-pass.d.ts +2 -0
  144. package/dist/record/main-pass.d.ts.map +1 -1
  145. package/dist/record/render-context.d.ts +48 -3
  146. package/dist/record/render-context.d.ts.map +1 -1
  147. package/dist/record/shadow-pass.d.ts.map +1 -1
  148. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  149. package/dist/record/typed-frame-graph.d.ts +81 -5
  150. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  151. package/dist/record/view-ubo.d.ts +7 -4
  152. package/dist/record/view-ubo.d.ts.map +1 -1
  153. package/dist/reflection/filter.d.ts +22 -0
  154. package/dist/reflection/filter.d.ts.map +1 -0
  155. package/dist/reflection/gpu-table.d.ts +25 -0
  156. package/dist/reflection/gpu-table.d.ts.map +1 -0
  157. package/dist/reflection/projection.d.ts +91 -0
  158. package/dist/reflection/projection.d.ts.map +1 -0
  159. package/dist/render-contract.d.ts +114 -7
  160. package/dist/render-contract.d.ts.map +1 -1
  161. package/dist/render-data.d.ts +10 -6
  162. package/dist/render-data.d.ts.map +1 -1
  163. package/dist/render-graph-primitives.d.ts +1 -0
  164. package/dist/render-graph-primitives.d.ts.map +1 -1
  165. package/dist/render-pipeline.d.ts +78 -2
  166. package/dist/render-pipeline.d.ts.map +1 -1
  167. package/dist/render-system-extract.d.ts +113 -20
  168. package/dist/render-system-extract.d.ts.map +1 -1
  169. package/dist/render-system.d.ts +24 -3
  170. package/dist/render-system.d.ts.map +1 -1
  171. package/dist/renderer-inspect.d.ts +29 -0
  172. package/dist/renderer-inspect.d.ts.map +1 -0
  173. package/dist/renderer.d.ts +43 -0
  174. package/dist/renderer.d.ts.map +1 -0
  175. package/dist/scene/render-scene.d.ts +14 -0
  176. package/dist/scene/render-scene.d.ts.map +1 -1
  177. package/dist/shadow-atlas.d.ts +3 -3
  178. package/dist/shadow-atlas.d.ts.map +1 -1
  179. package/dist/ssao-buffers.d.ts +3 -0
  180. package/dist/ssao-buffers.d.ts.map +1 -1
  181. package/dist/targets/contracts.d.ts +66 -0
  182. package/dist/targets/contracts.d.ts.map +1 -0
  183. package/dist/targets/graph-projection.d.ts +29 -0
  184. package/dist/targets/graph-projection.d.ts.map +1 -0
  185. package/dist/targets/material-source.d.ts +34 -0
  186. package/dist/targets/material-source.d.ts.map +1 -0
  187. package/dist/targets/owner.d.ts +32 -0
  188. package/dist/targets/owner.d.ts.map +1 -0
  189. package/dist/targets/physical.d.ts +18 -0
  190. package/dist/targets/physical.d.ts.map +1 -0
  191. package/dist/targets/readback.d.ts +39 -0
  192. package/dist/targets/readback.d.ts.map +1 -0
  193. package/dist/temporal/frame.d.ts +44 -0
  194. package/dist/temporal/frame.d.ts.map +1 -0
  195. package/dist/temporal/index.mjs +3 -3
  196. package/dist/typed-render-graph-primitives.d.ts +6 -1
  197. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  198. package/dist/typed-shadow-atlas.d.ts +10 -0
  199. package/dist/typed-shadow-atlas.d.ts.map +1 -0
  200. package/dist/typed-shadow-passes.d.ts +1 -1
  201. package/dist/typed-shadow-passes.d.ts.map +1 -1
  202. package/dist/volume/capability.d.ts +57 -0
  203. package/dist/volume/capability.d.ts.map +1 -0
  204. package/dist/volume/component.d.ts +61 -0
  205. package/dist/volume/component.d.ts.map +1 -0
  206. package/dist/volume/extract.d.ts +11 -0
  207. package/dist/volume/extract.d.ts.map +1 -0
  208. package/dist/volume/inspection.d.ts +38 -0
  209. package/dist/volume/inspection.d.ts.map +1 -0
  210. package/dist/volume/passes.d.ts +38 -0
  211. package/dist/volume/passes.d.ts.map +1 -0
  212. package/dist/volume/recovery.d.ts +38 -0
  213. package/dist/volume/recovery.d.ts.map +1 -0
  214. package/dist/volume/resources.d.ts +57 -0
  215. package/dist/volume/resources.d.ts.map +1 -0
  216. package/dist/volume/temporal.d.ts +35 -0
  217. package/dist/volume/temporal.d.ts.map +1 -0
  218. package/package.json +20 -20
  219. package/src/__tests__/bloom-exact-zero.unit.test.ts +48 -19
  220. package/src/__tests__/bloom-lifecycle.integration.test.ts +41 -13
  221. package/src/__tests__/camera-target-consumption.unit.test.ts +53 -0
  222. package/src/__tests__/cluster-binner.unit.test.ts +35 -0
  223. package/src/__tests__/cluster-grid-default-surface.unit.test.ts +7 -2
  224. package/src/__tests__/cube-camera-scheduler.unit.test.ts +70 -0
  225. package/src/__tests__/cube-camera-single-submit.perf.test.ts +75 -0
  226. package/src/__tests__/cube-camera-view-matrices.unit.test.ts +41 -0
  227. package/src/__tests__/cube-camera-vocabulary.unit.test.ts +47 -0
  228. package/src/__tests__/cube-camera.integration.test.ts +42 -0
  229. package/src/__tests__/device-feature-admission.unit.test.ts +73 -0
  230. package/src/__tests__/direct-light-snapshot.unit.test.ts +3 -3
  231. package/src/__tests__/docs-gate-green.unit.test.ts +38 -0
  232. package/src/__tests__/factory-contract.integration.test.ts +255 -29
  233. package/src/__tests__/fog-component.unit.test.ts +67 -0
  234. package/src/__tests__/fog.integration.test.ts +86 -0
  235. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +37 -0
  236. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +10 -9
  237. package/src/__tests__/gpu-driven-indirect-raster.dawn.test.ts +17 -1
  238. package/src/__tests__/gpu-driven-production.integration.test.ts +16 -17
  239. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +12 -4
  240. package/src/__tests__/gpu-pass-timing-browser-runner.ts +281 -0
  241. package/src/__tests__/gpu-pass-timing-coexistence.integration.test.ts +80 -0
  242. package/src/__tests__/gpu-pass-timing-contract.unit.test.ts +243 -0
  243. package/src/__tests__/gpu-pass-timing-exact-zero.unit.test.ts +131 -0
  244. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +230 -0
  245. package/src/__tests__/gpu-pass-timing-observation.unit.test.ts +233 -0
  246. package/src/__tests__/gpu-pass-timing-session.unit.test.ts +438 -0
  247. package/src/__tests__/gpu-pass-timing.browser.test.ts +26 -0
  248. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +125 -0
  249. package/src/__tests__/hdrp-group2-visibility.unit.test.ts +24 -0
  250. package/src/__tests__/instances-culling.integration.test.ts +94 -0
  251. package/src/__tests__/instances-derived-bounds.unit.test.ts +118 -0
  252. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +14 -14
  253. package/src/__tests__/material-observation.integration.test.ts +101 -0
  254. package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -1
  255. package/src/__tests__/pbr-view-layout.unit.test.ts +16 -0
  256. package/src/__tests__/point-shadow-inspection.unit.test.ts +60 -0
  257. package/src/__tests__/public-surface.test-d.ts +10 -0
  258. package/src/__tests__/reflection-probe-authoring.unit.test.ts +71 -0
  259. package/src/__tests__/reflection-probe-filter.unit.test.ts +54 -0
  260. package/src/__tests__/reflection-probe-ibl-topology.unit.test.ts +45 -0
  261. package/src/__tests__/reflection-probe-pass-encode.integration.test.ts +101 -0
  262. package/src/__tests__/reflection-probe-performance.perf.test.ts +60 -0
  263. package/src/__tests__/reflection-probe-recovery.integration.test.ts +55 -0
  264. package/src/__tests__/reflection-probe-selection.unit.test.ts +46 -0
  265. package/src/__tests__/render-error-code-owner.test-d.ts +23 -3
  266. package/src/__tests__/render-feature-docs.unit.test.ts +1 -1
  267. package/src/__tests__/render-target-admission.unit.test.ts +80 -0
  268. package/src/__tests__/render-target-graph-projection.unit.test.ts +102 -0
  269. package/src/__tests__/render-target-inspection.unit.test.ts +52 -0
  270. package/src/__tests__/render-target-material-source.test-d.ts +30 -0
  271. package/src/__tests__/render-target-material-source.unit.test.ts +97 -0
  272. package/src/__tests__/render-target-owner-placement.unit.test.ts +203 -0
  273. package/src/__tests__/render-target-owner.unit.test.ts +122 -0
  274. package/src/__tests__/render-target-probe-soak.perf.test.ts +94 -0
  275. package/src/__tests__/render-target-public-schema.json +107 -0
  276. package/src/__tests__/render-target-public-schema.unit.test.ts +91 -0
  277. package/src/__tests__/render-target-public-surface.test-d.ts +83 -0
  278. package/src/__tests__/render-target-readback.integration.test.ts +90 -0
  279. package/src/__tests__/render-target-recovery.integration.test.ts +85 -0
  280. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +76 -0
  281. package/src/__tests__/renderer-frame-transaction.integration.test.ts +1 -1
  282. package/src/__tests__/renderer-lifecycle.integration.test.ts +14 -0
  283. package/src/__tests__/shader-stage-surface.unit.test.ts +19 -4
  284. package/src/__tests__/skin-motion-regression.unit.test.ts +132 -0
  285. package/src/__tests__/skinned-shadow-caster.test.ts +32 -2
  286. package/src/__tests__/standard-cluster-capability.integration.test.ts +63 -0
  287. package/src/__tests__/standard-cluster-transport.unit.test.ts +121 -0
  288. package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +232 -0
  289. package/src/__tests__/standard-clustered-pipeline.unit.test.ts +8 -5
  290. package/src/__tests__/standard-lighting-inspection.integration.test.ts +138 -0
  291. package/src/__tests__/standard-lighting-ssot.unit.test.ts +18 -0
  292. package/src/__tests__/standard-lighting-write.unit.test.ts +377 -0
  293. package/src/__tests__/standard-lighting.integration.test.ts +67 -0
  294. package/src/__tests__/standard-pipeline.dawn.test.ts +206 -5
  295. package/src/__tests__/standard-pipeline.integration.test.ts +181 -150
  296. package/src/__tests__/standard-probe-binding.unit.test.ts +25 -0
  297. package/src/__tests__/standard-profile-oracle.unit.test.ts +23 -36
  298. package/src/__tests__/typed-pipeline-topology.unit.test.ts +395 -14
  299. package/src/__tests__/urp-pipeline-targets.unit.test.ts +2 -2
  300. package/src/__tests__/visibility-resolver.unit.test.ts +15 -0
  301. package/src/__tests__/volume-optics-oracle.unit.test.ts +85 -0
  302. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +655 -0
  303. package/src/__tests__/volumetric-fog-component.unit.test.ts +71 -0
  304. package/src/__tests__/volumetric-fog-composite-stage-readback.dawn.test.ts +376 -0
  305. package/src/__tests__/volumetric-fog-errors.unit.test.ts +51 -0
  306. package/src/__tests__/volumetric-fog-inspection.unit.test.ts +77 -0
  307. package/src/__tests__/volumetric-fog-light-capability.unit.test.ts +19 -0
  308. package/src/__tests__/volumetric-fog-light-consumers.integration.test.ts +18 -0
  309. package/src/__tests__/volumetric-fog-light-errors.unit.test.ts +17 -0
  310. package/src/__tests__/volumetric-fog-light-topology.unit.test.ts +21 -0
  311. package/src/__tests__/volumetric-fog-light-transaction.integration.test.ts +53 -0
  312. package/src/__tests__/volumetric-fog-m9-watcher.integration.test.ts +27 -0
  313. package/src/__tests__/volumetric-fog-point-light-owner.integration.test.ts +44 -0
  314. package/src/__tests__/volumetric-fog-point-spot-accumulation.integration.test.ts +49 -0
  315. package/src/__tests__/volumetric-fog-point-spot-contract.unit.test.ts +28 -0
  316. package/src/__tests__/volumetric-fog-point-spot-lkg.integration.test.ts +65 -0
  317. package/src/__tests__/volumetric-fog-point-spot-selection.integration.test.ts +49 -0
  318. package/src/__tests__/volumetric-fog-point-spot-temporal.unit.test.ts +55 -0
  319. package/src/__tests__/volumetric-fog-projector-contract.unit.test.ts +22 -0
  320. package/src/__tests__/volumetric-fog-projector-inspection.unit.test.ts +12 -0
  321. package/src/__tests__/volumetric-fog-projector-surface-volume.integration.test.ts +11 -0
  322. package/src/__tests__/volumetric-fog-projector-transaction.integration.test.ts +26 -0
  323. package/src/__tests__/volumetric-fog-recovery.integration.test.ts +47 -0
  324. package/src/__tests__/volumetric-fog-selected-light-resolution.integration.test.ts +63 -0
  325. package/src/__tests__/volumetric-fog-spot-closure.integration.test.ts +26 -0
  326. package/src/__tests__/volumetric-fog-spot-contract.test-d.ts +21 -0
  327. package/src/__tests__/volumetric-fog-spot-contract.unit.test.ts +27 -0
  328. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +14 -0
  329. package/src/__tests__/volumetric-fog-spot-optics.integration.test.ts +29 -0
  330. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +550 -0
  331. package/src/__tests__/volumetric-fog-temporal-selected-light.unit.test.ts +33 -0
  332. package/src/__tests__/volumetric-fog-temporal.unit.test.ts +45 -0
  333. package/src/__tests__/volumetric-fog-topology.unit.test.ts +237 -0
  334. package/src/__tests__/volumetric-fog-transparent.integration.test.ts +27 -0
  335. package/src/assembly/device-feature-admission.ts +73 -0
  336. package/src/assembly/directional-shadow-inspection.ts +122 -0
  337. package/src/assembly/factory.ts +1093 -246
  338. package/src/assembly/host-contract.ts +25 -0
  339. package/src/assembly/render-target-host.ts +847 -0
  340. package/src/assets/asset-decoders.ts +1 -1
  341. package/src/assets/render-asset-port.ts +7 -1
  342. package/src/capture/cube-views.ts +69 -0
  343. package/src/capture/scheduler.ts +265 -0
  344. package/src/components/__tests__/schema-contract.unit.test.ts +12 -0
  345. package/src/components/__tests__/schema-parity.unit.test.ts +9 -0
  346. package/src/components/camera.ts +4 -0
  347. package/src/components/cube-camera.ts +52 -0
  348. package/src/components/directional-light.ts +22 -2
  349. package/src/components/directional-shadow-filter.ts +57 -0
  350. package/src/components/index.ts +2 -0
  351. package/src/components/light-helpers.ts +85 -7
  352. package/src/components/reflection-probe.ts +49 -0
  353. package/src/components/spot-light.ts +22 -3
  354. package/src/device/gpu-residency.ts +168 -58
  355. package/src/environment/frame.ts +6 -24
  356. package/src/environment/lifecycle.ts +12 -0
  357. package/src/errors/render.ts +405 -143
  358. package/src/extract/directional-shadow-projection.ts +61 -0
  359. package/src/extract/environment.ts +57 -0
  360. package/src/extract/visibility.ts +25 -1
  361. package/src/features/fullscreen.ts +3 -0
  362. package/src/features/targets.ts +4 -1
  363. package/src/features/types.ts +10 -0
  364. package/src/fullscreen-post-process-pass.ts +43 -2
  365. package/src/gpu-driven/batch-topology.ts +1 -0
  366. package/src/gpu-driven/production-raster.ts +1 -3
  367. package/src/gpu-scene.ts +8 -1
  368. package/src/gpu-usage.ts +2 -0
  369. package/src/hdrp-buffers.ts +165 -59
  370. package/src/ibl/IblPipelineCache.ts +11 -0
  371. package/src/ibl/kernel-cache.ts +88 -0
  372. package/src/index.ts +186 -1
  373. package/src/inspection-types.ts +56 -0
  374. package/src/instances-derived-bounds.ts +171 -0
  375. package/src/light-buffer-layout.ts +74 -26
  376. package/src/mesh-material-bindings.ts +132 -0
  377. package/src/pbr-pipeline.ts +139 -27
  378. package/src/pipeline/standard-forward-lane.ts +65 -15
  379. package/src/pipeline/standard-lighting/errors.ts +6 -0
  380. package/src/pipeline/standard-lighting/graph.ts +157 -0
  381. package/src/pipeline/standard-lighting/inspection.ts +88 -0
  382. package/src/pipeline/standard-lighting/layout.ts +31 -0
  383. package/src/pipeline/standard-lighting/light-frame.ts +34 -0
  384. package/src/pipeline/standard-lighting/membership.ts +43 -0
  385. package/src/pipeline/standard-lighting/prepare.ts +37 -0
  386. package/src/pipeline/standard-lighting/topology.ts +120 -0
  387. package/src/pipeline/standard-lighting/transport.ts +77 -0
  388. package/src/pipeline/standard-pipeline.ts +141 -192
  389. package/src/pipeline/standard-post.ts +26 -7
  390. package/src/pipeline/standard-profile.ts +23 -30
  391. package/src/pipeline-spec.ts +84 -21
  392. package/src/point-shadow-inspection.ts +55 -0
  393. package/src/record/__tests__/temporal-payload.unit.test.ts +42 -1
  394. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +73 -0
  395. package/src/record/__tests__/view-ubo-layout.unit.test.ts +40 -0
  396. package/src/record/frame-lighting.ts +470 -516
  397. package/src/record/frame-snapshot.ts +76 -28
  398. package/src/record/frame-targets.ts +23 -2
  399. package/src/record/frame.ts +1169 -79
  400. package/src/record/gpu-pass-timing/contract.ts +180 -0
  401. package/src/record/gpu-pass-timing/errors.ts +34 -0
  402. package/src/record/gpu-pass-timing/index.ts +37 -0
  403. package/src/record/gpu-pass-timing/parser.ts +97 -0
  404. package/src/record/gpu-pass-timing/session.ts +938 -0
  405. package/src/record/gpu-timing.ts +233 -0
  406. package/src/record/main-pass-geometry.ts +120 -80
  407. package/src/record/main-pass-material.ts +101 -11
  408. package/src/record/main-pass-sprite-draws.ts +54 -25
  409. package/src/record/main-pass.ts +71 -15
  410. package/src/record/render-context.ts +77 -0
  411. package/src/record/shadow-pass.ts +104 -66
  412. package/src/record/skybox-post-pass.ts +20 -4
  413. package/src/record/typed-frame-graph.ts +1016 -32
  414. package/src/record/view-ubo.ts +63 -28
  415. package/src/reflection/filter.ts +81 -0
  416. package/src/reflection/gpu-table.ts +44 -0
  417. package/src/reflection/projection.ts +281 -0
  418. package/src/render-contract.ts +147 -4
  419. package/src/render-data.ts +50 -22
  420. package/src/render-graph-primitives.ts +9 -4
  421. package/src/render-pipeline.ts +161 -2
  422. package/src/render-system-extract.ts +886 -103
  423. package/src/render-system.ts +1174 -66
  424. package/src/renderer-inspect.ts +66 -0
  425. package/src/renderer.ts +222 -0
  426. package/src/scene/render-scene.ts +117 -9
  427. package/src/shadow-atlas.ts +5 -5
  428. package/src/ssao-buffers.ts +9 -2
  429. package/src/targets/contracts.ts +182 -0
  430. package/src/targets/graph-projection.ts +169 -0
  431. package/src/targets/material-source.ts +143 -0
  432. package/src/targets/owner.ts +214 -0
  433. package/src/targets/physical.ts +18 -0
  434. package/src/targets/readback.ts +153 -0
  435. package/src/temporal/frame.ts +128 -0
  436. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +61 -23
  437. package/src/typed-render-graph-primitives.ts +34 -2
  438. package/src/typed-shadow-atlas.ts +17 -0
  439. package/src/typed-shadow-passes.ts +47 -40
  440. package/src/volume/capability.ts +173 -0
  441. package/src/volume/component.ts +110 -0
  442. package/src/volume/extract.ts +21 -0
  443. package/src/volume/inspection.ts +78 -0
  444. package/src/volume/passes.ts +686 -0
  445. package/src/volume/recovery.ts +86 -0
  446. package/src/volume/resources.ts +236 -0
  447. package/src/volume/temporal.ts +89 -0
  448. package/dist/chunk-IPXCABEP.mjs.map +0 -1
  449. package/dist/chunk-LOSO4CTV.mjs.map +0 -1
  450. package/dist/chunk-RJRUS55L.mjs.map +0 -1
  451. package/dist/chunk-YTQ5C7YQ.mjs +0 -584
  452. package/dist/chunk-YTQ5C7YQ.mjs.map +0 -1
package/src/index.ts CHANGED
@@ -11,6 +11,13 @@ export {
11
11
  renderPipelineContribution,
12
12
  samplerContribution,
13
13
  } from './assets/asset-decoders';
14
+ // Runtime contract: leases, frame receipts, detached inspection, profile,
15
+ // lifecycle state, and the single renderer event stream.
16
+ export type {
17
+ CubeCameraFaceView,
18
+ CubeCameraFaceViewInput,
19
+ } from './capture/cube-views';
20
+ export { buildCubeCameraFaceViews } from './capture/cube-views';
14
21
  export { Atmosphere } from './components/atmosphere';
15
22
  // ECS render vocabulary and grouped closed values.
16
23
  export type {
@@ -42,6 +49,18 @@ export {
42
49
  TONEMAP_REINHARD,
43
50
  TONEMAP_REINHARD_EXTENDED,
44
51
  } from './components/camera';
52
+ export {
53
+ CUBE_CAMERA_FACE_ORDER,
54
+ CUBE_CAMERA_UPDATE_CONTINUOUS,
55
+ CUBE_CAMERA_UPDATE_ON_DEMAND,
56
+ CUBE_CAMERA_UPDATE_ONCE,
57
+ CubeCamera,
58
+ type CubeCameraData,
59
+ type CubeCameraFace,
60
+ type CubeCameraUpdateIntent,
61
+ cubeCameraUpdateIntentFromF32,
62
+ cubeCameraUpdateIntentToF32,
63
+ } from './components/cube-camera';
45
64
  export * from './components/directional-light';
46
65
  export { Fog } from './components/fog';
47
66
  export { Instances, type InstancesData } from './components/instances';
@@ -59,6 +78,16 @@ export {
59
78
  pointShapeFromU32,
60
79
  } from './components/points';
61
80
  export { PostProcessParams } from './components/post-process-params';
81
+ export {
82
+ REFLECTION_PROBE_UPDATE_CONTINUOUS,
83
+ REFLECTION_PROBE_UPDATE_ON_CHANGE,
84
+ REFLECTION_PROBE_UPDATE_ONCE,
85
+ ReflectionProbe,
86
+ type ReflectionProbeData,
87
+ type ReflectionProbeUpdateIntent,
88
+ reflectionProbeUpdateIntentFromF32,
89
+ reflectionProbeUpdateIntentToF32,
90
+ } from './components/reflection-probe';
62
91
  export { SceneInstance } from './components/scene-instance';
63
92
  export {
64
93
  SKYBOX_MODE_CUBEMAP,
@@ -67,6 +96,7 @@ export {
67
96
  } from './components/skybox-background';
68
97
  export { Skylight } from './components/skylight';
69
98
  export { SortKey } from './components/sort-key';
99
+ export type { SpotLightAuthoring, SpotLightProjector } from './components/spot-light';
70
100
  export { SpotLight } from './components/spot-light';
71
101
  export {
72
102
  Visibility,
@@ -83,8 +113,14 @@ export type {
83
113
  // Public structured operation failure union. Concrete error classes stay
84
114
  // behind the Renderer Result/event boundary.
85
115
  export type {
116
+ ReflectionProbeBudgetExceededDetail,
86
117
  RenderError,
87
118
  RenderErrorCode,
119
+ RenderIntentInvalidDetail,
120
+ RenderTargetCapabilityMissingDetail,
121
+ RenderTargetDescriptorInvalidDetail,
122
+ RenderTargetOperationFailedDetail,
123
+ RenderTargetStateInvalidDetail,
88
124
  SceneDataUnavailableDetail,
89
125
  SceneDataUnavailableReason,
90
126
  } from './errors/render';
@@ -130,17 +166,55 @@ export type {
130
166
  RenderFeatureStatus,
131
167
  RenderFeatureWorldVisibilitySnapshot,
132
168
  } from './features/types';
169
+ export {
170
+ beginProbeIblUpdate,
171
+ createIblKernelCache,
172
+ createProbeIblOutput,
173
+ type IblKernelCache,
174
+ type ProbeIblOutput,
175
+ type ProbeIblUpdate,
176
+ publishProbeIblOutput,
177
+ REFLECTION_PROBE_IBL_STAGES,
178
+ type ReflectionProbeIblStage,
179
+ resetIblKernelCaches,
180
+ } from './ibl/kernel-cache';
133
181
  export type {
134
182
  BloomInspection,
135
183
  MotionBlurInspection,
136
184
  MotionBlurInspectionStatus,
185
+ ReflectionProbeInspection,
186
+ ReflectionProbeSelectionInspection,
137
187
  TransmissionInspection,
138
188
  } from './inspection-types';
139
189
  export { Materials, MaterialTransmissionContractError } from './materials';
190
+ export {
191
+ type MeshMaterialBindingObservation,
192
+ type MeshMaterialBindingPreparationFailure,
193
+ type MeshMaterialBindingReadiness,
194
+ type MeshMaterialBindingResidency,
195
+ type MeshMaterialBindingSamplerObservation,
196
+ type MeshMaterialBindingSummary,
197
+ type MeshMaterialBindingTextureObservation,
198
+ projectMeshMaterialBindingObservation,
199
+ summarizeMeshMaterialBindings,
200
+ } from './mesh-material-bindings';
201
+ export type {
202
+ StandardClusterTransportInspection,
203
+ StandardLightingInspection,
204
+ StandardNoLocalLightingInspection,
205
+ } from './pipeline/standard-lighting/inspection';
140
206
  // The host-facing default is a stable profile value; implementation-only
141
207
  // pipeline helpers remain behind the package boundary.
142
- export { DEFAULT_STANDARD_PROFILE } from './pipeline/standard-profile';
208
+ export {
209
+ DEFAULT_STANDARD_PROFILE,
210
+ type StandardVolumetricFogProfile,
211
+ type StandardVolumetricFogQuality,
212
+ } from './pipeline/standard-profile';
143
213
  export { renderComponentsPlugin } from './plugin';
214
+ export {
215
+ inspectPointShadow,
216
+ type PointShadowInspection,
217
+ } from './point-shadow-inspection';
144
218
  export {
145
219
  admitPointsLines,
146
220
  type LinesStyleInput,
@@ -151,9 +225,67 @@ export {
151
225
  type PointsStyleInput,
152
226
  } from './points-lines/admission';
153
227
  export type { PointsLinesInspection } from './points-lines/inspection';
228
+ /**
229
+ * Public bounded GPU pass facts. Use the single `gpuPassTiming` opt-in,
230
+ * `draw()` receipt, and `observe(receipt, { include: ['timings'] })` route.
231
+ * Branch on the closed statuses `complete`, `partial`, `unavailable`, and
232
+ * `failed`; each reason/error exposes `code`, `expected`, `hint`, and `detail`.
233
+ * `latestKnownGood` is separate from current status and completeness. These
234
+ * facts describe pass durations, never frame latency. The bounded contract is
235
+ * in `record/gpu-pass-timing/contract.ts`; benchmark acceptance is fail-closed
236
+ * in `bench/gpu-pass-timing/validator.ts`, and recovery follows the producer's
237
+ * structured hint rather than a second timing API.
238
+ */
239
+ export type {
240
+ GpuPassTimingCapability,
241
+ GpuPassTimingEntry,
242
+ GpuPassTimingError,
243
+ GpuPassTimingErrorCode,
244
+ GpuPassTimingFrame,
245
+ GpuPassTimingMeasuredEntry,
246
+ GpuPassTimingMeasurementSource,
247
+ GpuPassTimingObservation,
248
+ GpuPassTimingOptions,
249
+ GpuPassTimingPassIdentity,
250
+ GpuPassTimingReason,
251
+ GpuPassTimingReasonCode,
252
+ GpuPassTimingRef,
253
+ GpuPassTimingUnmeasuredEntry,
254
+ } from './record/gpu-pass-timing/index.js';
154
255
  // Runtime contract: leases, frame receipts, detached inspection, profile,
155
256
  // lifecycle state, and the single renderer event stream.
257
+ export {
258
+ advanceProbeFilter,
259
+ boxProjectReflectionDirection,
260
+ commitProbeFilterStep,
261
+ createProbeFilterState,
262
+ type ProbeFilterState,
263
+ probeFilterIsSteady,
264
+ } from './reflection/filter';
265
+ export {
266
+ buildReflectionProbeTable,
267
+ type ReflectionProbeTable,
268
+ type ReflectionProbeTableRow,
269
+ reflectionProbeTableBytes,
270
+ } from './reflection/gpu-table';
271
+ export {
272
+ admitReflectionProbe,
273
+ DEFAULT_REFLECTION_PROBE_LIMITS,
274
+ estimateReflectionProbeBytes,
275
+ type ReflectionProbeAdmission,
276
+ type ReflectionProbeAdmissionLimits,
277
+ type ReflectionProbeFact,
278
+ type ReflectionProbeInput,
279
+ ReflectionProbeProjection,
280
+ type ReflectionProbeProjectionSnapshot,
281
+ type ReflectionProbeSelection,
282
+ type ReflectionProbeSelectionResult,
283
+ type SkylightSelection,
284
+ selectReflectionProbe,
285
+ validateReflectionProbeInput,
286
+ } from './reflection/projection';
156
287
  export type {
288
+ CubeCameraSnapshot,
157
289
  FrameCamera,
158
290
  FrameEnvironment,
159
291
  FrameObservationRequest,
@@ -170,6 +302,31 @@ export type {
170
302
  RenderWorldLease,
171
303
  } from './render-contract';
172
304
  export { RENDER_PHASE_CATALOG } from './render-contract';
305
+ export type {
306
+ TemporalInspectionInput,
307
+ TemporalInspectionStatus,
308
+ } from './renderer-inspect';
309
+ export {
310
+ SHADOW_ATLAS_DEFAULT_FACE_SIZE,
311
+ SHADOW_ATLAS_DEFAULT_LAYERS,
312
+ ShadowAtlas,
313
+ } from './shadow-atlas';
314
+ export type {
315
+ RenderTarget,
316
+ RenderTargetAdmissionLimits,
317
+ RenderTargetDepthFormat,
318
+ RenderTargetDescriptor,
319
+ RenderTargetFormat,
320
+ RenderTargetMipLevels,
321
+ RenderTargetReadbackData,
322
+ RenderTargetReadbackRequest,
323
+ RenderTargetReadbackTicket,
324
+ RenderTargetSampleCount,
325
+ RenderTargetShape,
326
+ RenderTargetTextureAspect,
327
+ RenderTargetTextureSource,
328
+ RenderTargetTextureSourceOptions,
329
+ } from './targets/contracts';
173
330
  export type { TemporalInspection, TemporalResourceInspection } from './temporal/inspection';
174
331
  export {
175
332
  SCENE_DATA_TEMPORAL_V1_DESCRIPTOR,
@@ -187,3 +344,31 @@ export {
187
344
  type SceneDataInspection,
188
345
  } from './temporal/scene-data-catalog';
189
346
  export type { TemporalView } from './temporal/view';
347
+ export {
348
+ hasVolumetricFogCapability,
349
+ type IntegratedVolumeResource,
350
+ resolveIntegratedVolumeConsumer,
351
+ resolveSelectedVolumetricLight,
352
+ resolveVolumetricFogLightPair,
353
+ type VolumeConsumer,
354
+ type VolumetricFogLightKind,
355
+ type VolumetricFogLightPairResolution,
356
+ type VolumetricFogLightResolution,
357
+ } from './volume/capability';
358
+ export {
359
+ type ValidatedVolumetricFog,
360
+ type VolumeBounds,
361
+ type VolumeDensityBinding,
362
+ VolumetricFog,
363
+ type VolumetricFogAuthoring,
364
+ type VolumetricFogLightSelection,
365
+ validateVolumetricFog,
366
+ } from './volume/component';
367
+ export { extractVolumetricFog, type VolumetricFogExtract } from './volume/extract';
368
+ export {
369
+ inspectVolumetricFog,
370
+ type VolumetricFogInspection,
371
+ type VolumetricFogInspectionInput,
372
+ type VolumetricFogInspectionStatus,
373
+ type VolumetricFogResourceStage,
374
+ } from './volume/inspection';
@@ -4,6 +4,7 @@
4
4
  * extract/record dependency graph.
5
5
  */
6
6
 
7
+ import type { DirectionalShadowFilterLabel } from './components/directional-shadow-filter';
7
8
  import type { PointsLinesInspection } from './points-lines/inspection';
8
9
 
9
10
  export type BloomGraphStatus = 'empty' | 'valid' | 'invalid';
@@ -65,6 +66,61 @@ export interface GpuDrivenProductionInspection {
65
66
  readonly cpuFallbackDrawItems: number;
66
67
  }
67
68
 
69
+ export type DirectionalShadowEffectiveProfile =
70
+ | 'off'
71
+ | DirectionalShadowFilterLabel
72
+ | 'rhi-null-structural';
73
+
74
+ export type DirectionalShadowProfile = 'off' | DirectionalShadowFilterLabel;
75
+
76
+ export interface DirectionalShadowInspectionError {
77
+ readonly code: string;
78
+ readonly expected: string;
79
+ readonly hint: string;
80
+ readonly detail?: unknown;
81
+ }
82
+
83
+ /** Bounded, detached Directional shadow facts for AI-readable inspection. */
84
+ export interface DirectionalShadowInspection {
85
+ readonly requested: DirectionalShadowProfile;
86
+ readonly effective: DirectionalShadowEffectiveProfile;
87
+ readonly status: 'accepted' | 'fallback' | 'rejected';
88
+ readonly fallbackReason?: 'webgl2-unsupported' | 'rhi-null-structural' | 'candidate-failed';
89
+ readonly lastKnownGood: boolean;
90
+ readonly pixelEvidence: 'available' | 'not-available';
91
+ readonly cascadeCount: number;
92
+ readonly mapSize: number;
93
+ readonly atlasBytes: number;
94
+ readonly writerPasses: number;
95
+ readonly blockerTaps: number;
96
+ readonly filterTapUpperBound: number;
97
+ readonly seamTapUpperBound: number;
98
+ readonly shadowAngularRadius: number | undefined;
99
+ readonly maxPenumbraTexels: number | undefined;
100
+ readonly deviceGeneration: number;
101
+ readonly graphGeneration: number;
102
+ readonly error?: DirectionalShadowInspectionError;
103
+ }
104
+
105
+ export type ReflectionProbeSelectionInspection =
106
+ | { readonly kind: 'probe'; readonly worldId: number; readonly entityKey: number }
107
+ | { readonly kind: 'skylight' };
108
+
109
+ export interface ReflectionProbeInspection {
110
+ readonly selection: ReflectionProbeSelectionInspection;
111
+ readonly factCount: number;
112
+ readonly acceptedCount: number;
113
+ readonly activeCount: number;
114
+ readonly rawFacesCaptured: number;
115
+ readonly filteredStepsCompleted: number;
116
+ readonly filteredMipLevels: readonly number[];
117
+ readonly scheduledRawFaces: number;
118
+ readonly scheduledFilteredSteps: number;
119
+ readonly pipelineReady: boolean;
120
+ readonly pipelineWarmupAttempts: number;
121
+ readonly pipelineWarmupFailure?: string;
122
+ }
123
+
68
124
  /** Detached semantic descriptor for the Standard scene-temporal producer. */
69
125
  export interface TemporalTargetInspection {
70
126
  readonly identity: 'standard-scene-temporal';
@@ -0,0 +1,171 @@
1
+ import { box3, type Mat4Like, mat4 } from '@forgeax/engine-math';
2
+
3
+ /**
4
+ * Inputs owned by the render extract/persistent-scene boundary. Bounds are
5
+ * deliberately derived here instead of being added to the author-facing
6
+ * `Instances` component or written back to a Pack asset.
7
+ */
8
+ export interface DerivedInstancesUnionBoundsInput {
9
+ readonly meshAabb: ArrayLike<number> | undefined;
10
+ readonly entityWorld: ArrayLike<number>;
11
+ readonly transforms: ArrayLike<number> | undefined;
12
+ }
13
+
14
+ /**
15
+ * Renderer-owned cache key. Each generation is supplied by the owner that can
16
+ * observe that mutation: mesh/AABB publication, entity world transform, and
17
+ * the packed instance matrix array respectively.
18
+ */
19
+ export interface InstanceBoundsCacheKey {
20
+ /** Optional scene/world scope for composite scenes; omitted for standalone tests. */
21
+ readonly worldId?: number;
22
+ readonly entityKey: number;
23
+ readonly meshGeneration: number;
24
+ readonly transformGeneration: number;
25
+ readonly matrixGeneration: number;
26
+ }
27
+
28
+ export type InstanceBoundsCacheInput = InstanceBoundsCacheKey & DerivedInstancesUnionBoundsInput;
29
+
30
+ /**
31
+ * Stable bitwise fingerprint for detached numeric facts used by the cache.
32
+ * Float32 bits are hashed rather than decimal text so a real matrix/AABB
33
+ * change invalidates the projection without keeping another mutable ledger.
34
+ */
35
+ export function fingerprintNumericArray(values: ArrayLike<number>): number {
36
+ let hash = 0x811c9dc5;
37
+ const scalar = new Float32Array(1);
38
+ const bits = new Uint32Array(scalar.buffer);
39
+ for (let index = 0; index < values.length; index += 1) {
40
+ scalar[0] = Number(values[index]);
41
+ hash = Math.imul(hash ^ (bits[0] ?? 0), 0x01000193) >>> 0;
42
+ }
43
+ return hash >>> 0;
44
+ }
45
+
46
+ function finiteAabb(aabb: ArrayLike<number> | undefined): aabb is ArrayLike<number> {
47
+ if (aabb === undefined || aabb.length < 6) return false;
48
+ const minX = aabb[0] as number;
49
+ const minY = aabb[1] as number;
50
+ const minZ = aabb[2] as number;
51
+ const maxX = aabb[3] as number;
52
+ const maxY = aabb[4] as number;
53
+ const maxZ = aabb[5] as number;
54
+ return (
55
+ Number.isFinite(minX) &&
56
+ Number.isFinite(minY) &&
57
+ Number.isFinite(minZ) &&
58
+ Number.isFinite(maxX) &&
59
+ Number.isFinite(maxY) &&
60
+ Number.isFinite(maxZ) &&
61
+ minX <= maxX &&
62
+ minY <= maxY &&
63
+ minZ <= maxZ
64
+ );
65
+ }
66
+
67
+ function finiteMatrix(matrix: ArrayLike<number>): matrix is Mat4Like {
68
+ if (matrix.length < 16) return false;
69
+ for (let index = 0; index < 16; index += 1) {
70
+ if (!Number.isFinite(matrix[index] as number)) return false;
71
+ }
72
+ return true;
73
+ }
74
+
75
+ function includeBox(out: box3.Box3, candidate: box3.Box3Like): void {
76
+ for (const x of [candidate[0] as number, candidate[3] as number]) {
77
+ for (const y of [candidate[1] as number, candidate[4] as number]) {
78
+ for (const z of [candidate[2] as number, candidate[5] as number]) {
79
+ box3.expandByPoint(out, [x, y, z]);
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Derive the world-space AABB enclosing every instance of a mesh.
87
+ *
88
+ * `undefined` is a conservative signal: the caller must skip CPU culling
89
+ * when an input is missing, malformed, or empty. This prevents an empty
90
+ * `Instances` row from becoming a synthetic identity draw/bounds candidate.
91
+ */
92
+ export function deriveInstancesUnionBounds(
93
+ input: DerivedInstancesUnionBoundsInput,
94
+ ): Float32Array | undefined {
95
+ const { meshAabb, entityWorld, transforms } = input;
96
+ if (!finiteAabb(meshAabb) || !finiteMatrix(entityWorld) || transforms === undefined) {
97
+ return undefined;
98
+ }
99
+ if (transforms.length === 0 || transforms.length % 16 !== 0) return undefined;
100
+
101
+ const local = box3.create(
102
+ meshAabb[0] as number,
103
+ meshAabb[1] as number,
104
+ meshAabb[2] as number,
105
+ meshAabb[3] as number,
106
+ meshAabb[4] as number,
107
+ meshAabb[5] as number,
108
+ );
109
+ const union = box3.create();
110
+ const composed = mat4.create();
111
+ const transformed = box3.create();
112
+ for (let offset = 0; offset < transforms.length; offset += 16) {
113
+ const instance = new Float32Array(16);
114
+ for (let lane = 0; lane < 16; lane += 1) {
115
+ instance[lane] = transforms[offset + lane] as number;
116
+ }
117
+ if (!finiteMatrix(instance)) return undefined;
118
+ mat4.multiply(composed, entityWorld, instance);
119
+ box3.transformBox3(transformed, local, composed);
120
+ if (!finiteAabb(transformed)) return undefined;
121
+ includeBox(union, transformed);
122
+ }
123
+ return new Float32Array(union);
124
+ }
125
+
126
+ interface InstanceBoundsCacheEntry extends InstanceBoundsCacheKey {
127
+ readonly bounds: Float32Array | undefined;
128
+ }
129
+
130
+ /**
131
+ * Small renderer-owned per-entity cache. A changed generation replaces the
132
+ * entry atomically; packed-id reuse is safe when its owner supplies a new
133
+ * generation (the normal RenderScene slot generation contract).
134
+ */
135
+ export class InstanceBoundsCache {
136
+ private readonly entries = new Map<string, InstanceBoundsCacheEntry>();
137
+
138
+ private key(input: Pick<InstanceBoundsCacheKey, 'worldId' | 'entityKey'>): string {
139
+ return `${input.worldId === undefined ? '' : `${input.worldId}:`}${input.entityKey}`;
140
+ }
141
+
142
+ get(input: InstanceBoundsCacheInput): Float32Array | undefined {
143
+ const previous = this.entries.get(this.key(input));
144
+ if (
145
+ previous !== undefined &&
146
+ previous.meshGeneration === input.meshGeneration &&
147
+ previous.transformGeneration === input.transformGeneration &&
148
+ previous.matrixGeneration === input.matrixGeneration
149
+ ) {
150
+ return previous.bounds;
151
+ }
152
+ const bounds = deriveInstancesUnionBounds(input);
153
+ this.entries.set(this.key(input), {
154
+ ...(input.worldId === undefined ? {} : { worldId: input.worldId }),
155
+ entityKey: input.entityKey,
156
+ meshGeneration: input.meshGeneration,
157
+ transformGeneration: input.transformGeneration,
158
+ matrixGeneration: input.matrixGeneration,
159
+ bounds,
160
+ });
161
+ return bounds;
162
+ }
163
+
164
+ invalidate(entityKey?: number, worldId?: number): void {
165
+ if (entityKey === undefined) {
166
+ this.entries.clear();
167
+ } else {
168
+ this.entries.delete(this.key({ entityKey, ...(worldId === undefined ? {} : { worldId }) }));
169
+ }
170
+ }
171
+ }