@forgeax/engine-render 0.1.33 → 0.1.35

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 (624) hide show
  1. package/README.md +1062 -127
  2. package/dist/assembly/backend-contract.d.ts +2 -0
  3. package/dist/assembly/backend-contract.d.ts.map +1 -1
  4. package/dist/assembly/barrel-distortion-inspection.d.ts +3 -0
  5. package/dist/assembly/barrel-distortion-inspection.d.ts.map +1 -0
  6. package/dist/assembly/canvas-draw-guard.d.ts +3 -0
  7. package/dist/assembly/canvas-draw-guard.d.ts.map +1 -0
  8. package/dist/assembly/cloud-shadow-entry.d.ts +4 -0
  9. package/dist/assembly/cloud-shadow-entry.d.ts.map +1 -0
  10. package/dist/assembly/device-feature-admission.d.ts +2 -2
  11. package/dist/assembly/dynamic-geometry-host.d.ts +4 -1
  12. package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
  13. package/dist/assembly/dynamic-geometry-runtime.d.ts +1 -1
  14. package/dist/assembly/dynamic-geometry-runtime.d.ts.map +1 -1
  15. package/dist/assembly/factory.d.ts +1 -1
  16. package/dist/assembly/factory.d.ts.map +1 -1
  17. package/dist/assembly/host-contract.d.ts +6 -5
  18. package/dist/assembly/host-contract.d.ts.map +1 -1
  19. package/dist/assembly/material/assembly.d.ts.map +1 -1
  20. package/dist/assembly/material/pipeline-helpers.d.ts +5 -0
  21. package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -1
  22. package/dist/assembly/material-shader-policy.d.ts +16 -2
  23. package/dist/assembly/material-shader-policy.d.ts.map +1 -1
  24. package/dist/assembly/material-shader-prewarm.d.ts.map +1 -1
  25. package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
  26. package/dist/assembly/recovery/renderer-recover.d.ts +2 -0
  27. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  28. package/dist/assembly/render-feature-post-processes.d.ts +6 -0
  29. package/dist/assembly/render-feature-post-processes.d.ts.map +1 -0
  30. package/dist/assembly/render-target-host.d.ts +5 -0
  31. package/dist/assembly/render-target-host.d.ts.map +1 -1
  32. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  33. package/dist/assembly/renderer-feature-inspection.d.ts +1 -1
  34. package/dist/assembly/renderer-feature-inspection.d.ts.map +1 -1
  35. package/dist/assembly/renderer-frame-transaction.d.ts +12 -0
  36. package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
  37. package/dist/assembly/renderer-inspection.d.ts +11 -0
  38. package/dist/assembly/renderer-inspection.d.ts.map +1 -1
  39. package/dist/assembly/webgpu-pbr-ready.d.ts +1 -0
  40. package/dist/assembly/webgpu-pbr-ready.d.ts.map +1 -1
  41. package/dist/assembly/webgpu-ready-per-pass.d.ts +39 -0
  42. package/dist/assembly/webgpu-ready-per-pass.d.ts.map +1 -0
  43. package/dist/assembly/webgpu-ready.d.ts +1 -1
  44. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  45. package/dist/assembly/webgpu-renderer-bootstrap.d.ts.map +1 -1
  46. package/dist/assembly/webgpu-renderer-observation-owner.d.ts +35 -0
  47. package/dist/assembly/webgpu-renderer-observation-owner.d.ts.map +1 -0
  48. package/dist/assembly/webgpu-renderer.d.ts +2 -1
  49. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  50. package/dist/authoring.mjs +2 -4
  51. package/dist/authoring.mjs.map +1 -1
  52. package/dist/barrel-distortion.d.ts +47 -0
  53. package/dist/barrel-distortion.d.ts.map +1 -0
  54. package/dist/chunk-3XUBWRY2.mjs +1842 -0
  55. package/dist/chunk-3XUBWRY2.mjs.map +1 -0
  56. package/dist/{chunk-OO3DRYK7.mjs → chunk-G6HDNGY7.mjs} +2400 -1767
  57. package/dist/chunk-G6HDNGY7.mjs.map +1 -0
  58. package/dist/{chunk-ZDQWGQW7.mjs → chunk-LM5IE7GF.mjs} +4 -4
  59. package/dist/{chunk-ZDQWGQW7.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
  60. package/dist/{chunk-VOZWDM3L.mjs → chunk-LNIUIKQ7.mjs} +1514 -498
  61. package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
  62. package/dist/chunk-MXTWKZO4.mjs +3268 -0
  63. package/dist/chunk-MXTWKZO4.mjs.map +1 -0
  64. package/dist/chunk-MZ4C7EHF.mjs +6942 -0
  65. package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
  66. package/dist/chunk-RIPAEGI6.mjs +48 -0
  67. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  68. package/dist/{chunk-LEAXOMYJ.mjs → chunk-SGPUJW3F.mjs} +117 -5
  69. package/dist/chunk-SGPUJW3F.mjs.map +1 -0
  70. package/dist/{chunk-PA5DRJNI.mjs → chunk-X2KA6WHM.mjs} +29 -4
  71. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  72. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  73. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  74. package/dist/cloud/density.d.ts +55 -0
  75. package/dist/cloud/density.d.ts.map +1 -0
  76. package/dist/cloud/extract.d.ts +25 -0
  77. package/dist/cloud/extract.d.ts.map +1 -0
  78. package/dist/cloud/feature.d.ts +57 -0
  79. package/dist/cloud/feature.d.ts.map +1 -0
  80. package/dist/cloud/frame-context.d.ts +8 -0
  81. package/dist/cloud/frame-context.d.ts.map +1 -0
  82. package/dist/cloud/inspection.d.ts +59 -0
  83. package/dist/cloud/inspection.d.ts.map +1 -0
  84. package/dist/cloud/optics.d.ts +56 -0
  85. package/dist/cloud/optics.d.ts.map +1 -0
  86. package/dist/cloud/parameters.d.ts +73 -0
  87. package/dist/cloud/parameters.d.ts.map +1 -0
  88. package/dist/cloud/resources.d.ts +60 -0
  89. package/dist/cloud/resources.d.ts.map +1 -0
  90. package/dist/cloud/shadow.d.ts +42 -0
  91. package/dist/cloud/shadow.d.ts.map +1 -0
  92. package/dist/cloud/temporal.d.ts +74 -0
  93. package/dist/cloud/temporal.d.ts.map +1 -0
  94. package/dist/components/barrel-distortion.d.ts +13 -0
  95. package/dist/components/barrel-distortion.d.ts.map +1 -0
  96. package/dist/components/cloud-layer.d.ts +29 -0
  97. package/dist/components/cloud-layer.d.ts.map +1 -0
  98. package/dist/components/index.d.ts +2 -0
  99. package/dist/components/index.d.ts.map +1 -1
  100. package/dist/components/instances.d.ts +20 -6
  101. package/dist/components/instances.d.ts.map +1 -1
  102. package/dist/construct-renderer.d.ts +1 -1
  103. package/dist/construct-renderer.d.ts.map +1 -1
  104. package/dist/construct-renderer.mjs +8406 -5785
  105. package/dist/construct-renderer.mjs.map +1 -1
  106. package/dist/device/gpu-residency.d.ts +19 -19
  107. package/dist/device/gpu-residency.d.ts.map +1 -1
  108. package/dist/dynamic-geometry.d.ts +5 -1
  109. package/dist/dynamic-geometry.d.ts.map +1 -1
  110. package/dist/errors/cloud.d.ts +59 -0
  111. package/dist/errors/cloud.d.ts.map +1 -0
  112. package/dist/errors/render.d.ts +20 -5
  113. package/dist/errors/render.d.ts.map +1 -1
  114. package/dist/examples/single-layer-medium-surface.d.ts +47 -0
  115. package/dist/examples/single-layer-medium-surface.d.ts.map +1 -0
  116. package/dist/extract/camera.d.ts.map +1 -1
  117. package/dist/extract/contracts.d.ts +5 -1
  118. package/dist/extract/contracts.d.ts.map +1 -1
  119. package/dist/extract/material-context.d.ts +7 -0
  120. package/dist/extract/material-context.d.ts.map +1 -0
  121. package/dist/features/barrel-distortion.d.ts +29 -0
  122. package/dist/features/barrel-distortion.d.ts.map +1 -0
  123. package/dist/features/error-reporting.d.ts +6 -2
  124. package/dist/features/error-reporting.d.ts.map +1 -1
  125. package/dist/features/host.d.ts +15 -0
  126. package/dist/features/host.d.ts.map +1 -1
  127. package/dist/features/plan.d.ts +10 -0
  128. package/dist/features/plan.d.ts.map +1 -1
  129. package/dist/features/render-graph-contribution.d.ts +5 -0
  130. package/dist/features/render-graph-contribution.d.ts.map +1 -1
  131. package/dist/features/render-graph-raster.d.ts +1 -0
  132. package/dist/features/render-graph-raster.d.ts.map +1 -1
  133. package/dist/features/targets.d.ts +2 -0
  134. package/dist/features/targets.d.ts.map +1 -1
  135. package/dist/features/types.d.ts +48 -0
  136. package/dist/features/types.d.ts.map +1 -1
  137. package/dist/fullscreen-post-process-pass.d.ts +15 -7
  138. package/dist/fullscreen-post-process-pass.d.ts.map +1 -1
  139. package/dist/glyph-text-layout-system.d.ts +1 -1
  140. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  141. package/dist/gpu-dirty-ranges.d.ts +11 -0
  142. package/dist/gpu-dirty-ranges.d.ts.map +1 -0
  143. package/dist/gpu-driven/batch-topology.d.ts +17 -0
  144. package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
  145. package/dist/gpu-driven/material-artifacts.d.ts +6 -0
  146. package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
  147. package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
  148. package/dist/gpu-driven/production-raster-material.d.ts +178 -0
  149. package/dist/gpu-driven/production-raster-material.d.ts.map +1 -0
  150. package/dist/gpu-driven/production-raster.d.ts +47 -3
  151. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  152. package/dist/gpu-driven/resource-allocation.d.ts +31 -0
  153. package/dist/gpu-driven/resource-allocation.d.ts.map +1 -0
  154. package/dist/gpu-driven/shadow-ownership.d.ts +14 -0
  155. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -0
  156. package/dist/gpu-driven/view-gpu.d.ts +26 -2
  157. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  158. package/dist/gpu-scene.d.ts +5 -0
  159. package/dist/gpu-scene.d.ts.map +1 -1
  160. package/dist/hdrp-buffers.d.ts +2 -2
  161. package/dist/hdrp-buffers.d.ts.map +1 -1
  162. package/dist/ibl/frame-resources.d.ts.map +1 -1
  163. package/dist/ibl/skylight-bind-group.d.ts +14 -5
  164. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  165. package/dist/index.d.ts +30 -7
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.mjs +780 -9
  168. package/dist/index.mjs.map +1 -1
  169. package/dist/inspection-types.d.ts +135 -1
  170. package/dist/inspection-types.d.ts.map +1 -1
  171. package/dist/instance-buffer-cache.d.ts +4 -4
  172. package/dist/instance-buffer-cache.d.ts.map +1 -1
  173. package/dist/instances.d.ts +47 -100
  174. package/dist/instances.d.ts.map +1 -1
  175. package/dist/internal.mjs +7 -8
  176. package/dist/internal.mjs.map +1 -1
  177. package/dist/pbr-pipeline.d.ts +22 -4
  178. package/dist/pbr-pipeline.d.ts.map +1 -1
  179. package/dist/pipeline/single-layer-medium-passes.d.ts +73 -0
  180. package/dist/pipeline/single-layer-medium-passes.d.ts.map +1 -0
  181. package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
  182. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  183. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  184. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  185. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  186. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  187. package/dist/pipeline/standard-output/types.d.ts +4 -2
  188. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  189. package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
  190. package/dist/pipeline/standard-post.d.ts.map +1 -1
  191. package/dist/pipeline-builder.d.ts +1 -1
  192. package/dist/pipeline-builder.d.ts.map +1 -1
  193. package/dist/plugin.d.ts.map +1 -1
  194. package/dist/prepare/prepared-graphics-resolver.d.ts +2 -0
  195. package/dist/prepare/prepared-graphics-resolver.d.ts.map +1 -1
  196. package/dist/publication/contract.d.ts +77 -0
  197. package/dist/publication/contract.d.ts.map +1 -0
  198. package/dist/publication/dependencies.d.ts +7 -0
  199. package/dist/publication/dependencies.d.ts.map +1 -0
  200. package/dist/publication/prepare-geometry.d.ts +9 -0
  201. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  202. package/dist/publication/programs.d.ts +5 -0
  203. package/dist/publication/programs.d.ts.map +1 -0
  204. package/dist/publication/publisher.d.ts +33 -0
  205. package/dist/publication/publisher.d.ts.map +1 -0
  206. package/dist/publication/receiver.d.ts +29 -0
  207. package/dist/publication/receiver.d.ts.map +1 -0
  208. package/dist/publication/resource-scope.d.ts +18 -0
  209. package/dist/publication/resource-scope.d.ts.map +1 -0
  210. package/dist/publication/targets.d.ts +33 -0
  211. package/dist/publication/targets.d.ts.map +1 -0
  212. package/dist/publication/video.d.ts +5 -0
  213. package/dist/publication/video.d.ts.map +1 -0
  214. package/dist/record/barrel-distortion-frame.d.ts +15 -0
  215. package/dist/record/barrel-distortion-frame.d.ts.map +1 -0
  216. package/dist/record/dynamic-geometry-consumption.d.ts +10 -2
  217. package/dist/record/dynamic-geometry-consumption.d.ts.map +1 -1
  218. package/dist/record/fold-buckets.d.ts +95 -0
  219. package/dist/record/fold-buckets.d.ts.map +1 -0
  220. package/dist/record/fold-instance-buffer.d.ts +6 -0
  221. package/dist/record/fold-instance-buffer.d.ts.map +1 -0
  222. package/dist/record/frame-lighting.d.ts +1 -0
  223. package/dist/record/frame-lighting.d.ts.map +1 -1
  224. package/dist/record/frame-snapshot.d.ts +43 -9
  225. package/dist/record/frame-snapshot.d.ts.map +1 -1
  226. package/dist/record/frame.d.ts +15 -65
  227. package/dist/record/frame.d.ts.map +1 -1
  228. package/dist/record/gpu-draw-receipts.d.ts +11 -0
  229. package/dist/record/gpu-draw-receipts.d.ts.map +1 -0
  230. package/dist/record/gpu-timing.d.ts +8 -0
  231. package/dist/record/gpu-timing.d.ts.map +1 -1
  232. package/dist/record/helpers.d.ts +2 -2
  233. package/dist/record/helpers.d.ts.map +1 -1
  234. package/dist/record/main-pass-geometry.d.ts +22 -6
  235. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  236. package/dist/record/main-pass-material.d.ts +14 -10
  237. package/dist/record/main-pass-material.d.ts.map +1 -1
  238. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  239. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  240. package/dist/record/main-pass.d.ts +13 -2
  241. package/dist/record/main-pass.d.ts.map +1 -1
  242. package/dist/record/motion-blur-receipt.d.ts +11 -0
  243. package/dist/record/motion-blur-receipt.d.ts.map +1 -0
  244. package/dist/record/prepared-material-bindings.d.ts +3 -3
  245. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  246. package/dist/record/probe-blend-buffer.d.ts +16 -0
  247. package/dist/record/probe-blend-buffer.d.ts.map +1 -0
  248. package/dist/record/recovery-pipeline.d.ts.map +1 -1
  249. package/dist/record/render-context.d.ts +24 -5
  250. package/dist/record/render-context.d.ts.map +1 -1
  251. package/dist/record/shadow-pass.d.ts +2 -0
  252. package/dist/record/shadow-pass.d.ts.map +1 -1
  253. package/dist/record/skybox-post-pass.d.ts +1 -1
  254. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  255. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  256. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  257. package/dist/record/target-capture-graph.d.ts +19 -0
  258. package/dist/record/target-capture-graph.d.ts.map +1 -0
  259. package/dist/record/typed-frame-graph.d.ts +24 -15
  260. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  261. package/dist/record/view-ubo.d.ts +11 -3
  262. package/dist/record/view-ubo.d.ts.map +1 -1
  263. package/dist/record/volume-params.d.ts +9 -0
  264. package/dist/record/volume-params.d.ts.map +1 -0
  265. package/dist/recovery/render-system-candidate.d.ts +14 -4
  266. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  267. package/dist/reflection/record-owner.d.ts.map +1 -1
  268. package/dist/render-contract.d.ts +46 -5
  269. package/dist/render-contract.d.ts.map +1 -1
  270. package/dist/render-graph-primitives.d.ts.map +1 -1
  271. package/dist/render-pipeline.d.ts +103 -2
  272. package/dist/render-pipeline.d.ts.map +1 -1
  273. package/dist/render-system-extract-tail.d.ts +3 -2
  274. package/dist/render-system-extract-tail.d.ts.map +1 -1
  275. package/dist/render-system-extract.d.ts +18 -9
  276. package/dist/render-system-extract.d.ts.map +1 -1
  277. package/dist/render-system-presentation.d.ts +23 -0
  278. package/dist/render-system-presentation.d.ts.map +1 -0
  279. package/dist/render-system-producer-roots.d.ts +10 -0
  280. package/dist/render-system-producer-roots.d.ts.map +1 -0
  281. package/dist/render-system-projections.d.ts +3 -2
  282. package/dist/render-system-projections.d.ts.map +1 -1
  283. package/dist/render-system-residency.d.ts +12 -0
  284. package/dist/render-system-residency.d.ts.map +1 -0
  285. package/dist/render-system.d.ts +22 -21
  286. package/dist/render-system.d.ts.map +1 -1
  287. package/dist/scene/probe-blend.d.ts +27 -0
  288. package/dist/scene/probe-blend.d.ts.map +1 -1
  289. package/dist/scene/render-scene.d.ts +18 -7
  290. package/dist/scene/render-scene.d.ts.map +1 -1
  291. package/dist/scene/render-source.d.ts +42 -0
  292. package/dist/scene/render-source.d.ts.map +1 -0
  293. package/dist/scene/source-systems.d.ts +6 -0
  294. package/dist/scene/source-systems.d.ts.map +1 -0
  295. package/dist/ssao-buffers.d.ts +9 -0
  296. package/dist/ssao-buffers.d.ts.map +1 -1
  297. package/dist/surface/dynamic-input.d.ts +133 -0
  298. package/dist/surface/dynamic-input.d.ts.map +1 -0
  299. package/dist/surface/gpu-driven.d.ts +41 -0
  300. package/dist/surface/gpu-driven.d.ts.map +1 -0
  301. package/dist/surface/submission-observation.d.ts +136 -0
  302. package/dist/surface/submission-observation.d.ts.map +1 -0
  303. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  304. package/dist/systems/skin-palette-types.d.ts +10 -0
  305. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  306. package/dist/systems/transparent-dispatch.d.ts +2 -2
  307. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  308. package/dist/systems/transparent-sort-config.d.ts +2 -1
  309. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  310. package/dist/temporal/gpu.d.ts +13 -1
  311. package/dist/temporal/gpu.d.ts.map +1 -1
  312. package/dist/temporal/index.mjs +6 -7
  313. package/dist/temporal/inspection.d.ts.map +1 -1
  314. package/dist/temporal/standard-scene-data.d.ts.map +1 -1
  315. package/dist/temporal/target-coverage-attachment.d.ts.map +1 -1
  316. package/dist/transmission/single-layer-medium.d.ts +89 -0
  317. package/dist/transmission/single-layer-medium.d.ts.map +1 -0
  318. package/dist/typed-render-graph-primitives.d.ts +14 -2
  319. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  320. package/dist/volume/component.d.ts +9 -4
  321. package/dist/volume/component.d.ts.map +1 -1
  322. package/dist/volume/extract.d.ts +1 -1
  323. package/dist/volume/extract.d.ts.map +1 -1
  324. package/dist/volume/inspection.d.ts +2 -0
  325. package/dist/volume/inspection.d.ts.map +1 -1
  326. package/dist/volume/passes.d.ts +4 -1
  327. package/dist/volume/passes.d.ts.map +1 -1
  328. package/dist/volume/resources.d.ts.map +1 -1
  329. package/package.json +22 -21
  330. package/src/__tests__/atmosphere-daylight.dawn.test.ts +72 -0
  331. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  332. package/src/__tests__/barrel-distortion-lkg.integration.test.ts +353 -0
  333. package/src/__tests__/barrel-distortion.dawn.test.ts +41 -0
  334. package/src/__tests__/barrel-distortion.unit.test.ts +364 -0
  335. package/src/__tests__/construct-renderer-identity.unit.test.ts +49 -0
  336. package/src/__tests__/detached-recovery-graph.unit.test.ts +277 -0
  337. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  338. package/src/__tests__/device-loss-fanout.unit.test.ts +36 -1
  339. package/src/__tests__/docs-gate-green.unit.test.ts +112 -1
  340. package/src/__tests__/factory-contract.integration.test.ts +295 -45
  341. package/src/__tests__/feature-depth-input.dawn.test.ts +129 -2
  342. package/src/__tests__/fullscreen-feature-plan.unit.test.ts +14 -3
  343. package/src/__tests__/gpu-dirty-ranges.unit.test.ts +22 -0
  344. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +16 -3
  345. package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +12 -0
  346. package/src/__tests__/gpu-driven-material-artifacts.unit.test.ts +143 -0
  347. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +5 -6
  348. package/src/__tests__/gpu-driven-production.integration.test.ts +482 -3
  349. package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +6 -5
  350. package/src/__tests__/gpu-driven-view-gpu-evidence.ts +94 -6
  351. package/src/__tests__/gpu-driven-view-graph.integration.test.ts +18 -2
  352. package/src/__tests__/gpu-driven-view.browser.test.ts +5 -8
  353. package/src/__tests__/gpu-driven-view.dawn.test.ts +6 -2
  354. package/src/__tests__/gpu-driven-view.unit.test.ts +1 -1
  355. package/src/__tests__/gpu-pass-timing-lifecycle.integration.test.ts +1 -0
  356. package/src/__tests__/gpu-pass-timing.browser.test.ts +6 -4
  357. package/src/__tests__/gpu-pass-timing.rhi-null.unit.test.ts +1 -0
  358. package/src/__tests__/gpu-scene.unit.test.ts +119 -9
  359. package/src/__tests__/instance-allocation-failure.unit.test.ts +57 -0
  360. package/src/__tests__/instances-culling.integration.test.ts +10 -36
  361. package/src/__tests__/instances-store.unit.test.ts +97 -305
  362. package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
  363. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  364. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +145 -0
  365. package/src/__tests__/material-shader-prewarm.unit.test.ts +59 -0
  366. package/src/__tests__/material-snapshot-mutation.integration.test.ts +39 -1
  367. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  368. package/src/__tests__/morph-culling-reentry.dawn.test.ts +5 -5
  369. package/src/__tests__/morph-visual-evidence.integration.test.ts +8 -7
  370. package/src/__tests__/motion-blur-compute.dawn.test.ts +13 -7
  371. package/src/__tests__/motion-blur.pixel.integration.test.ts +2 -2
  372. package/src/__tests__/nineslice-handle-surface.unit.test.ts +4 -4
  373. package/src/__tests__/pbr-view-layout.unit.test.ts +9 -0
  374. package/src/__tests__/physical-clearcoat.integration.test.ts +66 -8
  375. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  376. package/src/__tests__/prepared-graphics-capability.unit.test.ts +66 -2
  377. package/src/__tests__/probe-bindings.unit.test.ts +582 -1
  378. package/src/__tests__/probe-scene-dirty.integration.test.ts +28 -1
  379. package/src/__tests__/receipt-observation-retirement.unit.test.ts +65 -0
  380. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +69 -0
  381. package/src/__tests__/render-error-code-owner.test-d.ts +8 -0
  382. package/src/__tests__/render-feature-diagnostics.unit.test.ts +15 -2
  383. package/src/__tests__/render-feature-error-reporting.unit.test.ts +21 -1
  384. package/src/__tests__/render-feature-prepared-diagnostics.unit.test.ts +10 -1
  385. package/src/__tests__/render-feature-retry.unit.test.ts +12 -1
  386. package/src/__tests__/render-scene-mixed-updates.integration.test.ts +145 -19
  387. package/src/__tests__/render-scene-projection.unit.test.ts +36 -11
  388. package/src/__tests__/render-scene-temporal-retry.unit.test.ts +20 -20
  389. package/src/__tests__/render-target-probe-soak.perf.test.ts +2 -2
  390. package/src/__tests__/render-temporal-environment-consumer.browser.test.ts +3 -3
  391. package/src/__tests__/render-temporal-environment-consumer.dawn.test.ts +5 -2
  392. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +42 -8
  393. package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +16 -0
  394. package/src/__tests__/renderer-frame-transaction.integration.test.ts +26 -10
  395. package/src/__tests__/resource-allocation.unit.test.ts +123 -0
  396. package/src/__tests__/single-layer-medium-passes.unit.test.ts +275 -0
  397. package/src/__tests__/skin-motion-regression.unit.test.ts +70 -1
  398. package/src/__tests__/skin-palette-recycling.dawn.test.ts +97 -0
  399. package/src/__tests__/skinned-shadow-caster.test.ts +15 -0
  400. package/src/__tests__/ssr-carrier-public-contract.unit.test.ts +21 -0
  401. package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +4 -4
  402. package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +2 -2
  403. package/src/__tests__/ssr-gpu-dispatch.ts +1 -1
  404. package/src/__tests__/ssr-receiver-coverage.dawn.test.ts +6 -2
  405. package/src/__tests__/standard-output-chain-contract.unit.test.ts +28 -0
  406. package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +46 -1
  407. package/src/__tests__/standard-pipeline.integration.test.ts +182 -1
  408. package/src/__tests__/surface-dynamic-buffer-lifecycle.unit.test.ts +506 -0
  409. package/src/__tests__/surface-submission-observation.unit.test.ts +812 -0
  410. package/src/__tests__/temporal-history-lifecycle.unit.test.ts +32 -0
  411. package/src/__tests__/temporal-performance.integration.test.ts +3 -3
  412. package/src/__tests__/visibility-instances.integration.test.ts +7 -19
  413. package/src/__tests__/visibility-producer-matrix.integration.test.ts +9 -20
  414. package/src/__tests__/volume-optics-oracle.unit.test.ts +4 -2
  415. package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +30 -20
  416. package/src/__tests__/volumetric-fog-errors.unit.test.ts +4 -3
  417. package/src/__tests__/volumetric-fog-multiple.unit.test.ts +55 -0
  418. package/src/__tests__/volumetric-fog-spot-frame-optics.integration.test.ts +1 -1
  419. package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +113 -9
  420. package/src/__tests__/volumetric-fog-topology.unit.test.ts +5 -3
  421. package/src/assembly/backend-contract.ts +30 -0
  422. package/src/assembly/barrel-distortion-inspection.ts +22 -0
  423. package/src/assembly/canvas-draw-guard.ts +11 -0
  424. package/src/assembly/cloud-shadow-entry.ts +22 -0
  425. package/src/assembly/device-feature-admission.ts +2 -2
  426. package/src/assembly/dynamic-geometry-host.ts +65 -37
  427. package/src/assembly/dynamic-geometry-runtime.ts +7 -1
  428. package/src/assembly/factory.ts +2 -30
  429. package/src/assembly/host-contract.ts +8 -5
  430. package/src/assembly/material/assembly.ts +25 -13
  431. package/src/assembly/material/pipeline-helpers.ts +53 -12
  432. package/src/assembly/material-shader-policy.ts +55 -0
  433. package/src/assembly/material-shader-prewarm.ts +21 -10
  434. package/src/assembly/recovery/device-loss-fanout.ts +13 -0
  435. package/src/assembly/recovery/renderer-recover.ts +50 -18
  436. package/src/assembly/render-feature-post-processes.ts +54 -0
  437. package/src/assembly/render-target-host.ts +57 -47
  438. package/src/assembly/renderer-facade.ts +7 -2
  439. package/src/assembly/renderer-feature-inspection.ts +8 -2
  440. package/src/assembly/renderer-frame-transaction.ts +23 -0
  441. package/src/assembly/renderer-inspection.ts +28 -0
  442. package/src/assembly/skin-palette-owner.ts +1 -1
  443. package/src/assembly/temporal-post-process-prewarm.ts +3 -3
  444. package/src/assembly/webgpu-pbr-ready.ts +9 -1
  445. package/src/assembly/webgpu-ready-per-pass.ts +104 -0
  446. package/src/assembly/webgpu-ready.ts +116 -62
  447. package/src/assembly/webgpu-renderer-bootstrap.ts +0 -12
  448. package/src/assembly/webgpu-renderer-observation-owner.ts +222 -0
  449. package/src/assembly/webgpu-renderer.ts +303 -313
  450. package/src/assembly/webgpu-vertex-layouts.ts +1 -1
  451. package/src/barrel-distortion.ts +247 -0
  452. package/src/cloud/__tests__/cloud-density-parity.dawn.test.ts +173 -0
  453. package/src/cloud/__tests__/cloud-layer-framebuffer-y.dawn.test.ts +265 -0
  454. package/src/cloud/__tests__/cloud-layer.browser.test.ts +432 -0
  455. package/src/cloud/__tests__/cloud-layer.unit.test.ts +634 -0
  456. package/src/cloud/density.ts +600 -0
  457. package/src/cloud/extract.ts +110 -0
  458. package/src/cloud/feature.ts +1810 -0
  459. package/src/cloud/frame-context.ts +42 -0
  460. package/src/cloud/inspection.ts +130 -0
  461. package/src/cloud/optics.ts +285 -0
  462. package/src/cloud/parameters.ts +255 -0
  463. package/src/cloud/resources.ts +122 -0
  464. package/src/cloud/shadow.ts +167 -0
  465. package/src/cloud/temporal.ts +226 -0
  466. package/src/components/barrel-distortion.ts +46 -0
  467. package/src/components/cloud-layer.ts +47 -0
  468. package/src/components/index.ts +2 -0
  469. package/src/components/instances.ts +18 -45
  470. package/src/components/sprite-instances.ts +1 -1
  471. package/src/construct-renderer.ts +1 -1
  472. package/src/device/gpu-residency.ts +26 -25
  473. package/src/dynamic-geometry.ts +12 -1
  474. package/src/errors/cloud.ts +103 -0
  475. package/src/errors/render.ts +47 -8
  476. package/src/examples/single-layer-medium-surface.ts +59 -0
  477. package/src/extract/camera.ts +15 -1
  478. package/src/extract/contracts.ts +5 -0
  479. package/src/extract/material-context.ts +21 -0
  480. package/src/features/barrel-distortion.ts +172 -0
  481. package/src/features/error-reporting.ts +26 -6
  482. package/src/features/host.ts +128 -19
  483. package/src/features/plan.ts +10 -0
  484. package/src/features/render-graph-contribution.ts +9 -0
  485. package/src/features/render-graph-raster.ts +45 -3
  486. package/src/features/targets.ts +66 -0
  487. package/src/features/types.ts +51 -0
  488. package/src/fullscreen-post-process-pass.ts +41 -9
  489. package/src/glyph-text-layout-system.ts +2 -2
  490. package/src/gpu-dirty-ranges.ts +48 -0
  491. package/src/gpu-driven/batch-topology.ts +53 -0
  492. package/src/gpu-driven/material-artifacts.ts +33 -25
  493. package/src/gpu-driven/prepared-draw.ts +12 -4
  494. package/src/gpu-driven/production-raster-material.ts +1894 -0
  495. package/src/gpu-driven/production-raster.ts +825 -784
  496. package/src/gpu-driven/resource-allocation.ts +142 -0
  497. package/src/gpu-driven/shadow-ownership.ts +71 -0
  498. package/src/gpu-driven/view-gpu.ts +164 -10
  499. package/src/gpu-scene.ts +75 -84
  500. package/src/hdrp-buffers.ts +4 -3
  501. package/src/ibl/frame-resources.ts +0 -1
  502. package/src/ibl/skylight-bind-group.ts +62 -32
  503. package/src/index.ts +205 -9
  504. package/src/inspection-types.ts +162 -0
  505. package/src/instance-buffer-cache.ts +4 -4
  506. package/src/instances.ts +152 -569
  507. package/src/pbr-pipeline.ts +230 -30
  508. package/src/pipeline/single-layer-medium-passes.ts +267 -0
  509. package/src/pipeline/standard-forward-lane.ts +313 -57
  510. package/src/pipeline/standard-output/graph.ts +8 -2
  511. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  512. package/src/pipeline/standard-output/resources.ts +2 -2
  513. package/src/pipeline/standard-output/types.ts +12 -1
  514. package/src/pipeline/standard-pipeline.ts +291 -18
  515. package/src/pipeline/standard-post.ts +90 -24
  516. package/src/pipeline-builder.ts +1 -1
  517. package/src/plugin.ts +4 -0
  518. package/src/points-lines/__tests__/points-lines.bench.ts +17 -8
  519. package/src/prepare/prepared-graphics-resolver.ts +2 -0
  520. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  521. package/src/publication/__tests__/features.integration.test.ts +122 -0
  522. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  523. package/src/publication/__tests__/publication.integration.test.ts +370 -0
  524. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  525. package/src/publication/__tests__/video.browser.test.ts +50 -0
  526. package/src/publication/contract.ts +104 -0
  527. package/src/publication/dependencies.ts +54 -0
  528. package/src/publication/prepare-geometry.ts +94 -0
  529. package/src/publication/programs.ts +45 -0
  530. package/src/publication/publisher.ts +618 -0
  531. package/src/publication/receiver.ts +297 -0
  532. package/src/publication/resource-scope.ts +31 -0
  533. package/src/publication/targets.ts +182 -0
  534. package/src/publication/video.ts +33 -0
  535. package/src/record/__tests__/main-pass-geometry.unit.test.ts +30 -0
  536. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  537. package/src/record/__tests__/sprite-material-abi.unit.test.ts +9 -11
  538. package/src/record/__tests__/temporal-payload.unit.test.ts +1 -1
  539. package/src/record/__tests__/transparent-group2-selection.unit.test.ts +11 -0
  540. package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -0
  541. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  542. package/src/record/__tests__/view-ubo-layout.unit.test.ts +4 -3
  543. package/src/record/barrel-distortion-frame.ts +110 -0
  544. package/src/record/dynamic-geometry-consumption.ts +39 -9
  545. package/src/record/fold-buckets.ts +855 -0
  546. package/src/record/fold-instance-buffer.ts +51 -0
  547. package/src/record/frame-lighting.ts +36 -2
  548. package/src/record/frame-snapshot.ts +45 -9
  549. package/src/record/frame.ts +258 -1105
  550. package/src/record/gpu-draw-receipts.ts +38 -0
  551. package/src/record/gpu-timing.ts +48 -5
  552. package/src/record/helpers.ts +2 -2
  553. package/src/record/main-pass-geometry.ts +272 -84
  554. package/src/record/main-pass-material.ts +102 -36
  555. package/src/record/main-pass-sprite-draws.ts +13 -217
  556. package/src/record/main-pass.ts +164 -27
  557. package/src/record/motion-blur-receipt.ts +91 -0
  558. package/src/record/prepared-material-bindings.ts +11 -6
  559. package/src/record/probe-blend-buffer.ts +180 -0
  560. package/src/record/recovery-pipeline.ts +35 -3
  561. package/src/record/render-context.ts +41 -5
  562. package/src/record/shadow-pass.ts +30 -4
  563. package/src/record/skybox-post-pass.ts +28 -4
  564. package/src/record/sprite-instance-buffer.ts +155 -0
  565. package/src/record/target-capture-graph.ts +258 -0
  566. package/src/record/typed-frame-graph.ts +776 -340
  567. package/src/record/view-ubo.ts +27 -4
  568. package/src/record/volume-params.ts +225 -0
  569. package/src/recovery/render-system-candidate.ts +243 -50
  570. package/src/reflection/record-owner.ts +7 -3
  571. package/src/render-contract.ts +54 -5
  572. package/src/render-graph-primitives.ts +7 -1
  573. package/src/render-pipeline.ts +130 -0
  574. package/src/render-system-extract-tail.ts +90 -78
  575. package/src/render-system-extract.ts +76 -76
  576. package/src/render-system-presentation.ts +56 -0
  577. package/src/render-system-producer-roots.ts +96 -0
  578. package/src/render-system-projections.ts +3 -2
  579. package/src/render-system-residency.ts +159 -0
  580. package/src/render-system.ts +421 -408
  581. package/src/scene/probe-blend.ts +96 -4
  582. package/src/scene/render-scene.ts +416 -337
  583. package/src/scene/render-source.ts +90 -0
  584. package/src/scene/source-systems.ts +33 -0
  585. package/src/ssao-buffers.ts +95 -2
  586. package/src/surface/__tests__/dynamic-input.unit.test.ts +374 -0
  587. package/src/surface/__tests__/gpu-driven.unit.test.ts +87 -0
  588. package/src/surface/dynamic-input.ts +658 -0
  589. package/src/surface/gpu-driven.ts +147 -0
  590. package/src/surface/submission-observation.ts +517 -0
  591. package/src/systems/skin-palette-allocator.ts +5 -1
  592. package/src/systems/skin-palette-types.ts +11 -0
  593. package/src/systems/transparent-dispatch.ts +2 -2
  594. package/src/systems/transparent-sort-config.ts +3 -1
  595. package/src/temporal/gpu.ts +101 -17
  596. package/src/temporal/inspection.ts +7 -1
  597. package/src/temporal/standard-scene-data.ts +5 -0
  598. package/src/temporal/target-coverage-attachment.ts +4 -0
  599. package/src/transmission/__tests__/single-layer-medium.unit.test.ts +149 -0
  600. package/src/transmission/__tests__/standard-transmission.dawn.test.ts +12 -11
  601. package/src/transmission/single-layer-medium.ts +322 -0
  602. package/src/typed-render-graph-primitives.ts +70 -2
  603. package/src/volume/component.ts +10 -9
  604. package/src/volume/extract.ts +11 -5
  605. package/src/volume/inspection.ts +3 -0
  606. package/src/volume/passes.ts +87 -4
  607. package/src/volume/resources.ts +2 -1
  608. package/dist/chunk-3RTCJTH4.mjs +0 -1610
  609. package/dist/chunk-3RTCJTH4.mjs.map +0 -1
  610. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  611. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  612. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  613. package/dist/chunk-LEAXOMYJ.mjs.map +0 -1
  614. package/dist/chunk-NB2S7ZRX.mjs +0 -1783
  615. package/dist/chunk-NB2S7ZRX.mjs.map +0 -1
  616. package/dist/chunk-NNQL7CB3.mjs +0 -1713
  617. package/dist/chunk-NNQL7CB3.mjs.map +0 -1
  618. package/dist/chunk-OO3DRYK7.mjs.map +0 -1
  619. package/dist/chunk-PA5DRJNI.mjs.map +0 -1
  620. package/dist/chunk-PLAXOOX5.mjs +0 -1907
  621. package/dist/chunk-PLAXOOX5.mjs.map +0 -1
  622. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  623. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  624. package/dist/chunk-VOZWDM3L.mjs.map +0 -1
@@ -37,11 +37,11 @@ import {
37
37
  ASSET_ERROR_HINTS,
38
38
  AssetError,
39
39
  derive,
40
- err,
41
40
  handleSlot,
42
41
  materialValuesToLinearRuntime,
43
42
  toShared,
44
43
  } from '@forgeax/engine-types';
44
+ import { type ExtractedCloudLayer, extractCloudLayer } from './cloud/extract';
45
45
  import {
46
46
  Atmosphere,
47
47
  DirectionalLight,
@@ -92,11 +92,7 @@ import type {
92
92
  RenderFeatureWorldVisibilitySnapshot,
93
93
  } from './features/types';
94
94
  import { ensureGlyphMeshMaterialSlots } from './glyph-text-layout-system';
95
- import {
96
- InstanceCollectionError,
97
- type InstanceCollectionId,
98
- type InstanceCollectionStore,
99
- } from './instances';
95
+ import { type InstanceProjectionStore, validateInstanceTransforms } from './instances';
100
96
  import { deriveInstancesUnionBounds } from './instances-derived-bounds';
101
97
  import {
102
98
  type MeshMaterialBindingDiagnostic,
@@ -187,7 +183,7 @@ import {
187
183
  } from './render-system-extract';
188
184
  import { buildShadowFrusta } from './scene/shadow-visibility';
189
185
  import { SHADOW_ATLAS_DEFAULT_LAYERS } from './shadow-atlas';
190
- import type { SkinPaletteReceipt } from './systems/skin-palette-types';
186
+ import type { SkinPaletteReceipt, SkinPose } from './systems/skin-palette-types';
191
187
 
192
188
  function skinPaletteIdentity(world: World, entity: number): string {
193
189
  return `skin:${world.identity}:${entity}`;
@@ -234,11 +230,12 @@ export function extractFrames(
234
230
  request?: {
235
231
  readonly vertexColorAvailable?: boolean;
236
232
  readonly deformation?: 'rigid' | 'skin';
233
+ readonly variantSet?: string;
237
234
  readonly pass?: 'forward' | 'shadow' | 'depth';
238
235
  readonly address?: 'direct' | 'scene-index';
239
236
  },
240
237
  ) => MaterialShaderArtifact | undefined;
241
- readonly instanceCollections?: InstanceCollectionStore;
238
+ readonly instanceCollections?: InstanceProjectionStore;
242
239
  } = {},
243
240
  ): ExtractedFrame {
244
241
  // w4: normalize the owner argument. A bare number is the legacy single-owner
@@ -569,6 +566,7 @@ export function extractFrames(
569
566
  };
570
567
 
571
568
  const volumetricFog = resourceOwnerFrame?.volumetricFog;
569
+ const cloudLayer = resourceOwnerFrame?.cloudLayer;
572
570
  const skylight = resourceOwnerFrame?.skylight;
573
571
  const skylightCount = resourceOwnerFrame?.skylightCount ?? 0;
574
572
  const skybox = resourceOwnerFrame?.skybox;
@@ -651,6 +649,7 @@ export function extractFrames(
651
649
  ...(volumetricFog === undefined
652
650
  ? {}
653
651
  : { volumetricFog: { ...volumetricFog, worldId: resourceOwner } }),
652
+ ...(cloudLayer === undefined ? {} : { cloudLayer }),
654
653
  renderables,
655
654
  dispatch: dispatchEntries,
656
655
  shadowCasterEntityKeys,
@@ -795,6 +794,16 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
795
794
  // calls survive untouched, only the entity source changes).
796
795
  const worldInternal = createWorldInternalView(world);
797
796
  let volumetricFog = extractVolumeSnapshot(world, assets, worldInternal);
797
+ let cloudLayer: ExtractedCloudLayer | undefined;
798
+ const extractedCloudLayer = extractCloudLayer(world);
799
+ if (extractedCloudLayer.ok) {
800
+ cloudLayer = extractedCloudLayer.value;
801
+ } else {
802
+ worldInternal._routeError(extractedCloudLayer.error, {
803
+ severity: Severity.Error,
804
+ systemName: 'RenderSystem.extract (cloud-layer)',
805
+ });
806
+ }
798
807
 
799
808
  const cameraRoles = selectCameraRoles(world, context.cameraEntityKey);
800
809
  const cameras = [...cameraRoles.display];
@@ -1708,13 +1717,6 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
1708
1717
  // extraction. Shared handles are immutable inputs for the frame, while
1709
1718
  // dispatch entries still need to be rebuilt for each entity.
1710
1719
  const materialSnapshotCache: MaterialSnapshotCache = new Map();
1711
- // A collection can be associated with more than one entity. Snapshot its
1712
- // renderer-owned bytes once per extracted frame so culling and every
1713
- // submission lane consume the same detached revision without repeat copies.
1714
- const instanceSnapshotCache = new Map<
1715
- InstanceCollectionId,
1716
- ReturnType<InstanceCollectionStore['snapshot']>
1717
- >();
1718
1720
  const skinnedMaterialSnapshotCache: MaterialSnapshotCache = new Map();
1719
1721
  // tweak-20260611 M1: MeshRenderer renderable archetype walk routes
1720
1722
  // through one World-owned Query. K-2 sniffing scheme B
@@ -1779,22 +1781,25 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
1779
1781
  const flushPendingDispatch = (pending: readonly DispatchEntry[]): void => {
1780
1782
  for (const entry of pending) dispatch.push(entry);
1781
1783
  };
1782
- for (const row of meshRendererQuery) {
1783
- if (
1784
- context.renderables === 'full' &&
1785
- renderableEntities !== undefined &&
1786
- !renderableEntities.has(row.entity)
1787
- ) {
1788
- continue;
1789
- }
1784
+ const requestedRows =
1785
+ renderableEntities === undefined
1786
+ ? meshRendererQuery
1787
+ : {
1788
+ *[Symbol.iterator]() {
1789
+ for (const entity of renderableEntities) {
1790
+ const row = meshRendererQuery.at(entity as EntityHandle);
1791
+ if (row !== undefined) yield row;
1792
+ }
1793
+ },
1794
+ };
1795
+ for (const row of requestedRows) {
1790
1796
  // K-2 archetype-edge sniff (scheme B): a missing optional component
1791
1797
  // surfaces as an absent bundle key, not a row-internal optional chain.
1792
1798
  // Presence-only checks use QueryRow.has so large array-bearing components
1793
1799
  // are not materialised merely to answer a boolean question.
1794
1800
  const hasTransform = row.has(Transform);
1795
1801
  const meshFilter = row.get(MeshFilter);
1796
- const instancesData = row.get(Instances);
1797
- const hasInstances = instancesData !== undefined;
1802
+ const hasInstances = row.has(Instances);
1798
1803
  const skin = row.get(Skin);
1799
1804
  const morphWeightsView = worldInternal._getArrayView(row.entity, MorphWeights, 'weights');
1800
1805
  const hasMeshFilter = meshFilter !== undefined;
@@ -2574,6 +2579,16 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2574
2579
  baseColor,
2575
2580
  metallic: metallicPv,
2576
2581
  roughness: roughnessPv,
2582
+ ...(resolved.surface?.model === undefined
2583
+ ? {}
2584
+ : { surfaceModel: resolved.surface.model }),
2585
+ deferredPass: allPasses.some(
2586
+ (pass) =>
2587
+ String(
2588
+ (pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ??
2589
+ pass.name,
2590
+ ) === 'Deferred',
2591
+ ),
2577
2592
  ...(specularColorPv !== undefined && {
2578
2593
  specularColor: [
2579
2594
  specularColorPv[0] ?? 1,
@@ -2724,6 +2739,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2724
2739
  // resolve / validate / write chain (D-9 reset already fired at
2725
2740
  // extractFrame entry; per-entity allocate + writeJointPalette here).
2726
2741
  let skinSlice: SkinPaletteReceipt | undefined;
2742
+ let skinPose: SkinPose | undefined;
2727
2743
  const skinIdentity = hasSkin ? skinPaletteIdentity(world, entity) : undefined;
2728
2744
  const releaseSkinIdentity = (): void => {
2729
2745
  if (skinIdentity !== undefined) {
@@ -2835,6 +2851,17 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2835
2851
  });
2836
2852
  skinPaletteAllocator.writePersistentJointPalette(receipt, ibms, jointWorlds);
2837
2853
  skinSlice = receipt;
2854
+ } else {
2855
+ skinPose = {
2856
+ identity: skinPaletteIdentity(world, entity),
2857
+ generation: ((skeletonHandleRaw >>> 0) ^ skeleton.jointCount) >>> 0,
2858
+ jointCount: skeleton.jointCount,
2859
+ ...(hasFiniteOrderedLocalAabb(skeleton.bounds)
2860
+ ? { bounds: new Float32Array(skeleton.bounds) }
2861
+ : {}),
2862
+ inverseBindMatrices: ibms,
2863
+ jointWorlds,
2864
+ };
2838
2865
  }
2839
2866
  }
2840
2867
  }
@@ -2843,7 +2870,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
2843
2870
  // projection. Do not publish a renderable or its staged dispatch when
2844
2871
  // palette extraction was unavailable; the record stage must never
2845
2872
  // reinterpret a skinned vertex stream through an ordinary mesh group.
2846
- if (skinSlice === undefined && hasSkin) {
2873
+ if (skinSlice === undefined && skinPose === undefined && hasSkin) {
2847
2874
  releaseSkinIdentity();
2848
2875
  if (
2849
2876
  materialSnap.materialShaderId === 'forgeax::pbr-skin' ||
@@ -3073,49 +3100,29 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
3073
3100
  // make the cull and draw disagree within one frame).
3074
3101
  let instancesSnap: InstancesSnapshot | undefined;
3075
3102
  if (hasInstances) {
3076
- const collectionId = instancesData?.collectionId as InstanceCollectionId | undefined;
3077
- let collectionResult =
3078
- collectionId !== undefined ? instanceSnapshotCache.get(collectionId) : undefined;
3079
- if (collectionResult === undefined) {
3080
- collectionResult =
3081
- collectionId !== undefined && collectionId > 0 && instanceCollections !== undefined
3082
- ? instanceCollections.snapshot(collectionId)
3083
- : err(
3084
- new InstanceCollectionError(
3085
- 'instance-collection-invalid',
3086
- 'Instances.collectionId references a live renderer-owned collection',
3087
- 'create the collection through renderer.instances before attaching Instances',
3088
- {
3089
- operation: 'inspect',
3090
- expected: 'a positive collectionId with a live renderer owner',
3091
- actual: Number(collectionId ?? 0),
3092
- ...(collectionId === undefined ? {} : { collectionId }),
3093
- },
3094
- ),
3095
- );
3096
- if (collectionId !== undefined)
3097
- instanceSnapshotCache.set(collectionId, collectionResult);
3098
- }
3099
- if (collectionResult === undefined) continue;
3100
- if (!collectionResult.ok) {
3101
- worldInternal._routeError(collectionResult.error, {
3103
+ const transforms =
3104
+ worldInternal._getArrayView(entity, Instances, 'transforms') ?? new Float32Array();
3105
+ const invalid = validateInstanceTransforms(transforms);
3106
+ if (invalid !== undefined) {
3107
+ worldInternal._routeError(invalid, {
3102
3108
  severity: Severity.Error,
3103
- systemName: 'RenderSystem.extract (Instances collection)',
3109
+ systemName: 'RenderSystem.extract (Instances transforms)',
3104
3110
  });
3105
3111
  continue;
3106
3112
  }
3113
+ const projected = instanceCollections?.project(world, entity, transforms);
3107
3114
  instancesSnap = {
3108
- transforms: collectionResult.value.transforms,
3109
- generations: collectionResult.value.generations,
3110
- instanceCount: collectionResult.value.count,
3111
- collectionId: collectionResult.value.collectionId,
3112
- revision: collectionResult.value.revision,
3113
- capacity: collectionResult.value.capacity,
3114
- dirtyRanges: collectionResult.value.dirtyRanges,
3115
+ transforms: projected?.transforms ?? new Float32Array(transforms),
3116
+ instanceCount: transforms.length / 16,
3115
3117
  cacheKey: entity,
3116
- // Explicit collection revisions supersede ECS archetype content
3117
- // hashes; retain zero as the legacy sprite-only field value.
3118
- archVersion: 0,
3118
+ archVersion: projected === undefined ? archVersion : 0,
3119
+ ...(projected === undefined
3120
+ ? {}
3121
+ : {
3122
+ collectionId: projected.collectionId,
3123
+ revision: projected.revision,
3124
+ generations: projected.generations,
3125
+ }),
3119
3126
  };
3120
3127
  }
3121
3128
 
@@ -3133,6 +3140,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
3133
3140
  entityKey: entity,
3134
3141
  ...(authorVisible ? {} : { authorVisible: false }),
3135
3142
  ...(skinSlice !== undefined ? { skin: skinSlice } : {}),
3143
+ ...(skinPose === undefined ? {} : { skinPose }),
3136
3144
  ...(skin?.joints === undefined
3137
3145
  ? {}
3138
3146
  : { skinJointEntities: Array.from(skin.joints, (joint) => Number(joint)) }),
@@ -3141,21 +3149,24 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
3141
3149
  ...(spriteInstancesSnap !== undefined ? { spriteInstances: spriteInstancesSnap } : {}),
3142
3150
  ...(pointsLines !== undefined ? { pointsLines } : {}),
3143
3151
  };
3144
- const gpuDrivenDraws = buildGpuDrivenDraws({
3145
- mesh: gpuDrivenMesh,
3146
- materials: materialsArr,
3147
- fallbackMaterial: materialSnap,
3148
- baseSnapshot: baseRenderable,
3149
- ...(getMaterialShaderArtifact === undefined ? {} : { getMaterialShaderArtifact }),
3150
- ...(lods === undefined
3151
- ? {}
3152
- : {
3153
- lodMeshes: lods.map((lod) => {
3154
- const lower = assets?.lookup<Asset>(lod.mesh);
3155
- return lower?.kind === 'mesh' ? lower : undefined;
3156
- }),
3157
- }),
3158
- });
3152
+ const gpuDrivenDraws =
3153
+ skinPose === undefined
3154
+ ? buildGpuDrivenDraws({
3155
+ mesh: gpuDrivenMesh,
3156
+ materials: materialsArr,
3157
+ fallbackMaterial: materialSnap,
3158
+ baseSnapshot: baseRenderable,
3159
+ ...(getMaterialShaderArtifact === undefined ? {} : { getMaterialShaderArtifact }),
3160
+ ...(lods === undefined
3161
+ ? {}
3162
+ : {
3163
+ lodMeshes: lods.map((lod) => {
3164
+ const lower = assets?.lookup<Asset>(lod.mesh);
3165
+ return lower?.kind === 'mesh' ? lower : undefined;
3166
+ }),
3167
+ }),
3168
+ })
3169
+ : [];
3159
3170
  for (const draw of gpuDrivenDraws) {
3160
3171
  if (draw.preparationError === undefined) continue;
3161
3172
  worldInternal._routeError(draw.preparationError, {
@@ -3391,6 +3402,7 @@ export function extractFrame(world: World, context: PreparedExtractContext): Ext
3391
3402
  environment,
3392
3403
  environmentReady: true,
3393
3404
  ...(volumetricFog === undefined ? {} : { volumetricFog }),
3405
+ ...(cloudLayer === undefined ? {} : { cloudLayer }),
3394
3406
  renderables,
3395
3407
  dispatch,
3396
3408
  shadowCasterEntityKeys,
@@ -78,18 +78,11 @@ import type { MaterialCookProgramContext } from '@forgeax/engine-pack/material-c
78
78
  // non-renderable state and is skipped
79
79
  // (charter proposition 5; AC-11).
80
80
  //
81
- // Renderer-owned Large Instances:
82
- // `Instances { collectionId }` is an ECS association to the renderer's
83
- // `InstanceCollectionStore`, not an ECS transform-array column. The extract
84
- // tail resolves the identity against that store and snapshots canonical
85
- // transforms together with collection revision, capacity, dirty ranges,
86
- // and residency facts. Invalid or stale associations route the existing
87
- // typed `InstanceCollectionError` through the World error boundary; the
88
- // record stage owns GPU residency and upload decisions.
89
- //
90
- // `SpriteInstances` remains the separate ECS-owned array-view path. Its
91
- // snapshot is intentionally independent from renderer-owned Large Instances,
92
- // so the extract stage does not duplicate collection storage or GPU policy.
81
+ // World owns Instances.transforms. Extraction borrows the managed array during
82
+ // the read phase and retains a detached projection only when its values change.
83
+ // RenderScene accepts that projection with the source publication; recording
84
+ // owns device residency, upload revisions and backend-specific chunking.
85
+ // SpriteInstances remains the independent 2D component and snapshot contract.
93
86
 
94
87
  import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
95
88
  import {
@@ -127,6 +120,7 @@ import type {
127
120
  MaterialPass,
128
121
  MaterialProgramAbi,
129
122
  MaterialRenderState,
123
+ MaterialSurfaceModel,
130
124
  MaterialTextureCoordinates,
131
125
  MaterialTextureValue,
132
126
  MeshLodLevel,
@@ -142,6 +136,7 @@ import {
142
136
  import { buildCubeCameraFaceViews } from './capture/cube-views';
143
137
  import {
144
138
  antialiasFromF32,
139
+ BarrelDistortion,
145
140
  CAMERA_EXPOSURE_MODE_MANUAL,
146
141
  Camera,
147
142
  CubeCamera,
@@ -159,6 +154,7 @@ import {
159
154
  validateCameraBloom,
160
155
  validateDynamicResolutionCamera,
161
156
  } from './components';
157
+ import { validateBarrelDistortionParameters } from './components/barrel-distortion';
162
158
  import { DepthOfField } from './components/depth-of-field';
163
159
  import type { DirectionalShadowQuality } from './components/directional-shadow-filter';
164
160
  import type { LightValidationError } from './components/light-helpers';
@@ -185,7 +181,7 @@ import type {
185
181
  RenderFeatureHiddenEntityReport,
186
182
  RenderFeatureWorldVisibilitySnapshot,
187
183
  } from './features/types';
188
- import type { InstanceCollectionId, InstanceCollectionStore } from './instances';
184
+ import type { InstanceCollectionId, InstanceProjectionStore } from './instances';
189
185
  import type {
190
186
  MeshMaterialBindingDiagnostic,
191
187
  MeshMaterialBindingSource,
@@ -658,15 +654,16 @@ export interface SkyboxSnapshot {
658
654
  }
659
655
 
660
656
  /**
661
- * Resource-owner projection for the single ECS VolumetricFog singleton.
657
+ * Resource-owner projection for an ECS VolumetricFog collection.
662
658
  *
663
659
  * The renderer carries the validated authoring facts and the source POD all
664
660
  * the way to the record stage. No profile flag or source/catalog byte is
665
661
  * allowed to enable the graph: `status: 'available'` is produced only after
666
662
  * the ECS component, its shared TextureAsset, and the volume validator all
667
- * agree on one linear 3D density owner.
663
+ * agree on every linear 3D density owner.
668
664
  */
669
665
  export interface ExtractedVolumetricFog {
666
+ readonly additional?: readonly ExtractedVolumetricFog[];
670
667
  readonly status: 'off' | 'available' | 'degraded';
671
668
  readonly fog?: ValidatedVolumetricFog;
672
669
  readonly densityHandle?: Handle<'TextureAsset', 'shared'>;
@@ -795,6 +792,8 @@ export interface RenderableSnapshot {
795
792
  * Absent (`undefined`) means the entity is not skinned.
796
793
  */
797
794
  readonly skin?: SkinPaletteReceipt;
795
+ /** Source pose waiting for the receiving Renderer to assign a palette. */
796
+ readonly skinPose?: import('./systems/skin-palette-types').SkinPose;
798
797
  /** Joint identities consumed by the retained scene dependency index. */
799
798
  readonly skinJointEntities?: readonly number[];
800
799
  /** Source pass ownership retained with the scene record across view changes. */
@@ -857,8 +856,6 @@ export interface InstancesSnapshot {
857
856
  readonly instanceCount: number;
858
857
  /** Collection revision captured by this detached frame snapshot. */
859
858
  readonly revision?: number;
860
- /** Logical collection capacity at snapshot time. */
861
- readonly capacity?: number;
862
859
  /** Coalesced matrix ordinals dirtied since the previous authoring update. */
863
860
  readonly dirtyRanges?: readonly {
864
861
  readonly start: number;
@@ -944,6 +941,10 @@ export interface MaterialSnapshot {
944
941
  readonly baseColor: Vec3;
945
942
  readonly metallic: number;
946
943
  readonly roughness: number;
944
+ /** Root-owned Surface model used only for typed pass routing. */
945
+ readonly surfaceModel?: MaterialSurfaceModel | undefined;
946
+ /** Whether this material publishes a Deferred pass consumed before the forward-only lane. */
947
+ readonly deferredPass?: boolean | undefined;
947
948
  /** Authored Standard PBR specular color in linear runtime color space. */
948
949
  readonly specularColor?: readonly [number, number, number] | undefined;
949
950
  /**
@@ -1243,6 +1244,8 @@ export interface ExtractedFrame {
1243
1244
  readonly environmentReady: boolean;
1244
1245
  /** One resource-owner volume projection; absent means no authored fog. */
1245
1246
  readonly volumetricFog?: ExtractedVolumetricFog;
1247
+ /** Resource-owner CloudLayer facts selected once at the extract boundary. */
1248
+ readonly cloudLayer?: import('./cloud/extract').ExtractedCloudLayer;
1246
1249
  readonly renderables: RenderableSnapshot[];
1247
1250
  /**
1248
1251
  * Single dispatch list sorted by queue value (ascending, stable sort).
@@ -2459,6 +2462,13 @@ export function resolveMaterialSnapshot(
2459
2462
  baseColor,
2460
2463
  metallic: metallicPv,
2461
2464
  roughness: roughnessPv,
2465
+ ...(resolved.surface?.model === undefined ? {} : { surfaceModel: resolved.surface.model }),
2466
+ deferredPass: allPasses.some(
2467
+ (pass) =>
2468
+ String(
2469
+ (pass.renderState?.tags as Record<string, unknown> | undefined)?.LightMode ?? pass.name,
2470
+ ) === 'Deferred',
2471
+ ),
2462
2472
  ...(specularColorPv !== undefined && {
2463
2473
  specularColor: [
2464
2474
  specularColorPv[0] ?? 1,
@@ -2981,13 +2991,14 @@ export interface PreparedExtractContext {
2981
2991
  request?: {
2982
2992
  readonly vertexColorAvailable?: boolean;
2983
2993
  readonly deformation?: 'rigid' | 'skin';
2994
+ readonly variantSet?: string;
2984
2995
  readonly pass?: 'forward' | 'shadow' | 'depth';
2985
2996
  readonly address?: 'direct' | 'scene-index';
2986
2997
  },
2987
2998
  ) => MaterialShaderArtifact | undefined)
2988
2999
  | undefined;
2989
- /** Renderer-owned canonical source for explicit large instance collections. */
2990
- readonly instanceCollections: InstanceCollectionStore | undefined;
3000
+ /** Renderer-private projection of World-authored instance matrices. */
3001
+ readonly instanceCollections: InstanceProjectionStore | undefined;
2991
3002
  }
2992
3003
 
2993
3004
  const ALL_VISIBLE: VisibilitySnapshot = {
@@ -3004,13 +3015,20 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3004
3015
  const cameraQuery = world
3005
3016
  .query({
3006
3017
  read: [Camera],
3007
- optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection, DepthOfField],
3018
+ optional: [
3019
+ MotionBlur,
3020
+ DynamicResolution,
3021
+ ScreenSpaceReflection,
3022
+ DepthOfField,
3023
+ BarrelDistortion,
3024
+ ],
3008
3025
  with: [Transform, GlobalTransform],
3009
3026
  })
3010
3027
  .unwrap();
3011
3028
  for (const row of cameraQuery) {
3012
3029
  const cam = row.get(Camera);
3013
3030
  const motionBlur = row.get(MotionBlur);
3031
+ const barrelDistortion = row.get(BarrelDistortion);
3014
3032
  const motionBlurResult = resolveMotionBlurParams(motionBlur);
3015
3033
  if (!motionBlurResult.ok) throw motionBlurResult.error;
3016
3034
  const motionBlurParams = motionBlurResult.value;
@@ -3051,6 +3069,8 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3051
3069
  const antialias = antialiasFromF32(cam.antialias);
3052
3070
  const dynamicResolutionResult = validateDynamicResolutionCamera(dynamicResolution, antialias);
3053
3071
  if (!dynamicResolutionResult.ok) throw dynamicResolutionResult.error;
3072
+ const barrelDistortionResult = validateBarrelDistortionParameters(barrelDistortion);
3073
+ if (!barrelDistortionResult.ok) throw barrelDistortionResult.error;
3054
3074
  cameras.push({
3055
3075
  entityKey: entity as number,
3056
3076
  ...(target === undefined ? {} : { target }),
@@ -3105,6 +3125,7 @@ function collectCameraSnapshots(world: World): CameraSnapshot[] {
3105
3125
  targetFps: motionBlurParams.targetFps,
3106
3126
  },
3107
3127
  }),
3128
+ ...(barrelDistortion === undefined ? {} : { barrelDistortion: barrelDistortionResult.value }),
3108
3129
  ...(screenSpaceReflection === undefined
3109
3130
  ? {}
3110
3131
  : {
@@ -3257,11 +3278,12 @@ export function prepareExtractContext(
3257
3278
  request?: {
3258
3279
  readonly vertexColorAvailable?: boolean;
3259
3280
  readonly deformation?: 'rigid' | 'skin';
3281
+ readonly variantSet?: string;
3260
3282
  readonly pass?: 'forward' | 'shadow' | 'depth';
3261
3283
  readonly address?: 'direct' | 'scene-index';
3262
3284
  },
3263
3285
  ) => MaterialShaderArtifact | undefined;
3264
- readonly instanceCollections?: InstanceCollectionStore;
3286
+ readonly instanceCollections?: InstanceProjectionStore;
3265
3287
  } = {},
3266
3288
  ): PreparedExtractContext {
3267
3289
  const renderables = options.renderables ?? 'full';
@@ -3364,6 +3386,7 @@ export function extractVolumeSnapshot(
3364
3386
  const worldTimeSeconds = Number.isFinite(elapsed) ? Math.max(0, elapsed) : 0;
3365
3387
  const query = world.query({ read: [VolumetricFog] }).unwrap();
3366
3388
  const authorings: VolumetricFogAuthoring[] = [];
3389
+ const members: ExtractedVolumetricFog[] = [];
3367
3390
  let selectedLight:
3368
3391
  | {
3369
3392
  readonly entity: EntityHandle;
@@ -3372,15 +3395,9 @@ export function extractVolumeSnapshot(
3372
3395
  readonly spotLightEntity?: EntityHandle;
3373
3396
  }
3374
3397
  | undefined;
3375
- let first:
3376
- | {
3377
- readonly densityHandle: Handle<'TextureAsset', 'shared'>;
3378
- readonly densityAsset: TextureAsset;
3379
- readonly guid: string;
3380
- }
3381
- | undefined;
3382
3398
 
3383
3399
  for (const row of query) {
3400
+ selectedLight = undefined;
3384
3401
  const source = row.get(VolumetricFog);
3385
3402
  if (source.light === null) continue;
3386
3403
  const selected = resolveSelectedVolumetricLight(world, source.light);
@@ -3457,9 +3474,30 @@ export function extractVolumeSnapshot(
3457
3474
  emission: [source.emission[0] ?? 0, source.emission[1] ?? 0, source.emission[2] ?? 0],
3458
3475
  anisotropy: source.anisotropy,
3459
3476
  maxDistance: source.maxDistance,
3477
+ sampling: source.sampling === 1 ? 'density' : 'noise',
3460
3478
  };
3461
3479
  authorings.push(authoring);
3462
- first ??= { densityHandle, densityAsset, guid };
3480
+ members.push({
3481
+ status: 'available',
3482
+ worldTimeSeconds,
3483
+ densityHandle,
3484
+ densityAsset,
3485
+ guid,
3486
+ generation: 1,
3487
+ digest: textureDigest(densityAsset),
3488
+ ...(selectedLight === undefined
3489
+ ? {}
3490
+ : {
3491
+ lightEntity: selectedLight.entity,
3492
+ lightKind: selectedLight.kind,
3493
+ ...(selectedLight.pointLightEntity === undefined
3494
+ ? {}
3495
+ : { pointLightEntity: selectedLight.pointLightEntity }),
3496
+ ...(selectedLight.spotLightEntity === undefined
3497
+ ? {}
3498
+ : { spotLightEntity: selectedLight.spotLightEntity }),
3499
+ }),
3500
+ });
3463
3501
  }
3464
3502
 
3465
3503
  if (authorings.length === 0) return undefined;
@@ -3469,56 +3507,18 @@ export function extractVolumeSnapshot(
3469
3507
  severity: Severity.Error,
3470
3508
  systemName: 'RenderSystem.extract (volumetric-fog)',
3471
3509
  });
3472
- return {
3473
- status: 'degraded',
3474
- worldTimeSeconds,
3475
- ...(first === undefined
3476
- ? {}
3477
- : {
3478
- densityHandle: first.densityHandle,
3479
- densityAsset: first.densityAsset,
3480
- guid: first.guid,
3481
- generation: 1,
3482
- digest: textureDigest(first.densityAsset),
3483
- ...(selectedLight === undefined
3484
- ? {}
3485
- : {
3486
- lightEntity: selectedLight.entity,
3487
- lightKind: selectedLight.kind,
3488
- ...(selectedLight.pointLightEntity === undefined
3489
- ? {}
3490
- : { pointLightEntity: selectedLight.pointLightEntity }),
3491
- ...(selectedLight.spotLightEntity === undefined
3492
- ? {}
3493
- : { spotLightEntity: selectedLight.spotLightEntity }),
3494
- }),
3495
- }),
3496
- };
3510
+ return { ...members[0], status: 'degraded' };
3497
3511
  }
3498
- if (extracted.value.status === 'off' || first === undefined) return { status: 'off' };
3499
- const selectedLightFields =
3500
- selectedLight === undefined
3501
- ? {}
3502
- : {
3503
- lightEntity: selectedLight.entity,
3504
- lightKind: selectedLight.kind,
3505
- ...(selectedLight.pointLightEntity === undefined
3506
- ? {}
3507
- : { pointLightEntity: selectedLight.pointLightEntity }),
3508
- ...(selectedLight.spotLightEntity === undefined
3509
- ? {}
3510
- : { spotLightEntity: selectedLight.spotLightEntity }),
3511
- };
3512
+ if (extracted.value.status === 'off') return { status: 'off' };
3513
+ const validatedMembers = extracted.value.fogs.map((fog, index) => ({
3514
+ ...members[index],
3515
+ status: 'available' as const,
3516
+ fog,
3517
+ }));
3512
3518
  return {
3513
3519
  status: 'available',
3514
- worldTimeSeconds,
3515
- fog: extracted.value.fog,
3516
- densityHandle: first.densityHandle,
3517
- densityAsset: first.densityAsset,
3518
- guid: first.guid,
3519
- generation: 1,
3520
- digest: textureDigest(first.densityAsset),
3521
- ...selectedLightFields,
3520
+ ...validatedMembers[0],
3521
+ additional: validatedMembers.slice(1),
3522
3522
  };
3523
3523
  }
3524
3524
 
@@ -0,0 +1,56 @@
1
+ import type { RenderResourceScope } from './publication/resource-scope';
2
+ import type { RenderSystemInternals } from './record/render-context';
3
+ import type { FramePresentation } from './render-contract';
4
+ import type { DispatchEntry, RenderableSnapshot } from './render-system-extract';
5
+ import { observeMaterialResidency } from './render-system-residency';
6
+
7
+ export interface FramePresentationProjection {
8
+ readonly renderables: readonly RenderableSnapshot[];
9
+ readonly presentation: FramePresentation;
10
+ }
11
+
12
+ /**
13
+ * Derive the startup presentation candidate from the current display workset.
14
+ * Shadow-only retained rows are deliberately excluded, while material facts
15
+ * still come from the producer-owned residency projection.
16
+ */
17
+ export function projectFramePresentation(input: {
18
+ readonly hasCamera: boolean;
19
+ readonly environmentReady: boolean;
20
+ readonly hasEnvironment: boolean;
21
+ readonly submissionRenderables: readonly RenderableSnapshot[];
22
+ readonly submissionDispatch: readonly DispatchEntry[];
23
+ readonly preparedWorlds: readonly RenderResourceScope[];
24
+ readonly internals: RenderSystemInternals;
25
+ }): FramePresentationProjection {
26
+ const displayRenderableIndices = new Set<number>();
27
+ for (const entry of input.submissionDispatch) {
28
+ if (entry.renderableIndex === undefined) continue;
29
+ if (entry.tags.LightMode !== 'ShadowCaster')
30
+ displayRenderableIndices.add(entry.renderableIndex);
31
+ }
32
+ const renderables = input.submissionRenderables.filter(
33
+ (_, index) =>
34
+ displayRenderableIndices.has(index) &&
35
+ input.submissionRenderables[index]?.authorVisible !== false,
36
+ );
37
+
38
+ let presentation: FramePresentation = 'ready';
39
+ if (input.hasCamera && (!input.environmentReady || !input.hasEnvironment)) {
40
+ presentation = 'pending';
41
+ } else if (input.hasCamera) {
42
+ for (const renderable of renderables) {
43
+ const materialWorld = input.preparedWorlds[renderable.worldId];
44
+ for (const material of renderable.materials) {
45
+ if (
46
+ observeMaterialResidency(materialWorld, material, input.internals).readiness === 'pending'
47
+ ) {
48
+ presentation = 'pending';
49
+ break;
50
+ }
51
+ }
52
+ if (presentation === 'pending') break;
53
+ }
54
+ }
55
+ return { renderables, presentation };
56
+ }